diff --git a/Documentation/Doxyfile b/Documentation/Doxyfile
index 03b1ba71c77aa1fc97e0700843726b93dca24605..92c1dd3d09b75bd2e982eccf60d53af2aa05917d 100644
--- a/Documentation/Doxyfile
+++ b/Documentation/Doxyfile
@@ -792,9 +792,9 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT = main-page.md
-INPUT += ../src/TNL
+INPUT += Pages
 INPUT += Tutorials
+INPUT += ../src/TNL
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
diff --git a/Documentation/Pages/core-concepts.md b/Documentation/Pages/core-concepts.md
new file mode 100644
index 0000000000000000000000000000000000000000..1450ada792ded0c5031bd5648c3c3b7800a9bba6
--- /dev/null
+++ b/Documentation/Pages/core-concepts.md
@@ -0,0 +1,33 @@
+\page core_concepts  Core concepts
+
+TNL is based on the following core concepts:
+
+1. \ref TNL::Allocators "Allocators"
+   - Allocator handles memory allocation and deallocation.
+   - TNL allocators are fully compatible with the
+     [standard C++ concept](https://en.cppreference.com/w/cpp/named_req/Allocator)
+   - Multiple allocators can correspond to the same "memory space".
+2. \ref TNL::Devices "Devices"
+   (TODO: rename to `Executor` or something like that)
+   - Device is responsible for the execution of algorithms in a specific way.
+   - Algorithms can be specialized by the `Device` template parameter.
+3. \ref TNL::Containers::Algorithms "Algorithms"
+   - Basic (container-free) algorithms specialized by `Device`/`Executor`.
+   - `ParallelFor`, `Reduction`, `MultiReduction`, `ArrayOperations`, ...
+4. \ref TNL::Containers "Containers"
+   - Classes for general data structures.
+     (TODO: alternatively use "Dense" and "Sparse", because a dense matrix can
+     be an extended alias for 2D array)
+   - `Array`, `Vector` (also `VectorOperations`), `NDArray`, ...
+5. Views
+   - Views wrap only a raw pointer to data and some metadata (such as the array
+     size), they do not do allocation and deallocation of the data. Hence, views
+     have a fixed size which cannot be changed.
+   - Views have a copy-constructor which does a shallow copy. As a result, views
+     can be passed-by-value to CUDA kernels or captured-by-value by device
+     lambda functions.
+   - Views have a copy-assignment operator which does a deep copy.
+   - Views have all other methods present in the relevant container (data
+     structure).
+
+TODO: formalize the concepts involving lambda functions (e.g. in `Reduction`)
diff --git a/Documentation/main-page.md b/Documentation/Pages/main-page.md
similarity index 82%
rename from Documentation/main-page.md
rename to Documentation/Pages/main-page.md
index 5e71c361652a4c5a502ab92be116f7657138b1ba..8cdc9b506ad9e490460a6757628ba840a03fd424 100644
--- a/Documentation/main-page.md
+++ b/Documentation/Pages/main-page.md
@@ -14,14 +14,21 @@ several modules:
 > TODO: Each topic in this list should have a separate page or tutorial.
 
 - _Core concepts_.
-  The main concept used in the TNL is the `Device` type which is used in most of
-  the other parts of the library. For data structures such as
-  \ref TNL::Containers::Array "Array" it specifies where the data should be
-  allocated, whereas for algorithms such as \ref TNL::ParallelFor "ParallelFor"
-  it specifies how the algorithm should be executed.
+  The main concepts used in TNL are the _memory space_, which represents the
+  part of memory where given data is allocated, and the _execution model_,
+  which represents the way how given (typically parallel) algorithm is executed.
+  For example, data can be allocated in the main system memory, in the GPU
+  memory, or using the CUDA Unified Memory which can be accessed from the host
+  as well as from the GPU. On the other hand, algorithms can be executed using
+  either the host CPU or an accelerator (GPU), and for each there are many ways
+  to manage parallel execution. The usage of memory spaces is abstracted with
+  \ref TNL::Allocators "allocators" and the execution model is represented by
+  \ref TNL::Devices "devices". See the \ref core_concepts "Core concepts" page
+  for details.
 - \ref TNL::Containers "Containers".
   TNL provides generic containers such as array, multidimensional array or array
-  views, which abstract data management on different hardware architectures.
+  views, which abstract data management and execution of common operations on
+  different hardware architectures.
 - _Linear algebra._
   TNL provides generic data structures and algorithms for linear algebra, such
   as \ref TNL::Containers::Vector "vectors",
diff --git a/src/Benchmarks/BLAS/array-operations.h b/src/Benchmarks/BLAS/array-operations.h
index 926c729ce1af887c030d2a129bde735374377af1..b689c7e196c18c0a8143cb6a77be82d257d84723 100644
--- a/src/Benchmarks/BLAS/array-operations.h
+++ b/src/Benchmarks/BLAS/array-operations.h
@@ -20,14 +20,15 @@ namespace TNL {
 namespace Benchmarks {
 
 template< typename Real = double,
-          typename Index = int >
-bool
+          typename Index = int,
+          template<typename> class HostAllocator = Allocators::Default< Devices::Host >::Allocator,
+          template<typename> class CudaAllocator = Allocators::Default< Devices::Cuda >::Allocator >
+void
 benchmarkArrayOperations( Benchmark & benchmark,
                           const long & size )
 {
-   typedef Containers::Array< Real, Devices::Host, Index > HostArray;
-   typedef Containers::Array< Real, Devices::Cuda, Index > CudaArray;
-   using namespace std;
+   using HostArray = Containers::Array< Real, Devices::Host, Index, HostAllocator< Real > >;
+   using CudaArray = Containers::Array< Real, Devices::Cuda, Index, CudaAllocator< Real > >;
 
    double datasetSize = (double) size * sizeof( Real ) / oneGB;
 
@@ -155,8 +156,6 @@ benchmarkArrayOperations( Benchmark & benchmark,
 #ifdef HAVE_CUDA
    benchmark.time< Devices::Cuda >( setSize1, "GPU", resetSizeCuda );
 #endif
-
-   return true;
 }
 
 } // namespace Benchmarks
diff --git a/src/Benchmarks/BLAS/spmv.h b/src/Benchmarks/BLAS/spmv.h
index 966a4ec06bc90d8b4e220a2f4e49108c7cb0ece1..7f114e514ab44ba040f436e41f492b890cc3e36d 100644
--- a/src/Benchmarks/BLAS/spmv.h
+++ b/src/Benchmarks/BLAS/spmv.h
@@ -90,9 +90,8 @@ void setCudaTestMatrix( Matrix& matrix,
 
 // TODO: rename as benchmark_SpMV_synthetic and move to spmv-synthetic.h
 template< typename Real,
-          template< typename, typename, typename > class Matrix,
-          template< typename, typename, typename > class Vector = Containers::Vector >
-bool
+          template< typename, typename, typename > class Matrix >
+void
 benchmarkSpMV( Benchmark & benchmark,
                const int & size,
                const int elementsPerRow = 5 )
@@ -165,24 +164,20 @@ benchmarkSpMV( Benchmark & benchmark,
 #ifdef HAVE_CUDA
    benchmark.time< Devices::Cuda >( reset, "GPU", spmvCuda );
 #endif
-
-   return true;
 }
 
 template< typename Real = double,
           typename Index = int >
-bool
+void
 benchmarkSpmvSynthetic( Benchmark & benchmark,
                         const int & size,
                         const int & elementsPerRow )
 {
-   bool result = true;
    // TODO: benchmark all formats from tnl-benchmark-spmv (different parameters of the base formats)
-   result |= benchmarkSpMV< Real, Matrices::CSR >( benchmark, size, elementsPerRow );
-   result |= benchmarkSpMV< Real, Matrices::Ellpack >( benchmark, size, elementsPerRow );
-   result |= benchmarkSpMV< Real, SlicedEllpack >( benchmark, size, elementsPerRow );
-   result |= benchmarkSpMV< Real, Matrices::ChunkedEllpack >( benchmark, size, elementsPerRow );
-   return result;
+   benchmarkSpMV< Real, Matrices::CSR >( benchmark, size, elementsPerRow );
+   benchmarkSpMV< Real, Matrices::Ellpack >( benchmark, size, elementsPerRow );
+   benchmarkSpMV< Real, SlicedEllpack >( benchmark, size, elementsPerRow );
+   benchmarkSpMV< Real, Matrices::ChunkedEllpack >( benchmark, size, elementsPerRow );
 }
 
 } // namespace Benchmarks
diff --git a/src/Benchmarks/BLAS/tnl-benchmark-blas.h b/src/Benchmarks/BLAS/tnl-benchmark-blas.h
index 49c624ac9cefb6a4182d6c372d5eeac2023174e5..b510c383749c0104c3c87c8c111237dfdc5a35b9 100644
--- a/src/Benchmarks/BLAS/tnl-benchmark-blas.h
+++ b/src/Benchmarks/BLAS/tnl-benchmark-blas.h
@@ -12,6 +12,8 @@
 
 #pragma once
 
+#include <TNL/Allocators/CudaHost.h>
+#include <TNL/Allocators/CudaManaged.h>
 #include <TNL/Devices/Host.h>
 #include <TNL/Devices/Cuda.h>
 #include <TNL/Config/ConfigDescription.h>
@@ -19,6 +21,7 @@
 
 #include "array-operations.h"
 #include "vector-operations.h"
+#include "triad.h"
 #include "spmv.h"
 
 using namespace TNL;
@@ -38,7 +41,7 @@ runBlasBenchmarks( Benchmark & benchmark,
    metadata["precision"] = precision;
 
    // Array operations
-   benchmark.newBenchmark( String("Array operations (") + precision + ")",
+   benchmark.newBenchmark( String("Array operations (") + precision + ", host allocator = Host)",
                            metadata );
    for( std::size_t size = minSize; size <= maxSize; size *= 2 ) {
       benchmark.setMetadataColumns( Benchmark::MetadataColumns({
@@ -46,6 +49,24 @@ runBlasBenchmarks( Benchmark & benchmark,
       } ));
       benchmarkArrayOperations< Real >( benchmark, size );
    }
+#ifdef HAVE_CUDA
+   benchmark.newBenchmark( String("Array operations (") + precision + ", host allocator = CudaHost)",
+                           metadata );
+   for( std::size_t size = minSize; size <= maxSize; size *= 2 ) {
+      benchmark.setMetadataColumns( Benchmark::MetadataColumns({
+         { "size", convertToString( size ) },
+      } ));
+      benchmarkArrayOperations< Real, int, Allocators::CudaHost >( benchmark, size );
+   }
+   benchmark.newBenchmark( String("Array operations (") + precision + ", host allocator = CudaManaged)",
+                           metadata );
+   for( std::size_t size = minSize; size <= maxSize; size *= 2 ) {
+      benchmark.setMetadataColumns( Benchmark::MetadataColumns({
+         { "size", convertToString( size ) },
+      } ));
+      benchmarkArrayOperations< Real, int, Allocators::CudaManaged >( benchmark, size );
+   }
+#endif
 
    // Vector operations
    benchmark.newBenchmark( String("Vector operations (") + precision + ")",
@@ -57,6 +78,18 @@ runBlasBenchmarks( Benchmark & benchmark,
       benchmarkVectorOperations< Real >( benchmark, size );
    }
 
+   // Triad benchmark: copy from host, compute, copy to host
+#ifdef HAVE_CUDA
+   benchmark.newBenchmark( String("Triad benchmark (") + precision + ")",
+                           metadata );
+   for( std::size_t size = minSize; size <= maxSize; size *= 2 ) {
+      benchmark.setMetadataColumns( Benchmark::MetadataColumns({
+         { "size", convertToString( size ) },
+      } ));
+      benchmarkTriad< Real >( benchmark, size );
+   }
+#endif
+
    // Sparse matrix-vector multiplication
    benchmark.newBenchmark( String("Sparse matrix-vector multiplication (") + precision + ")",
                            metadata );
diff --git a/src/Benchmarks/BLAS/triad.h b/src/Benchmarks/BLAS/triad.h
new file mode 100644
index 0000000000000000000000000000000000000000..c107944c893f3d799eabdfbaca5a3d32fd8a599a
--- /dev/null
+++ b/src/Benchmarks/BLAS/triad.h
@@ -0,0 +1,194 @@
+/***************************************************************************
+                          triad.h  -  description
+                             -------------------
+    begin                : Jul 4, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+// Implemented by: Jakub Klinkovsky
+
+#pragma once
+
+#include "../Benchmarks.h"
+
+#include <TNL/Containers/Array.h>
+#include <TNL/Allocators/CudaHost.h>
+#include <TNL/Allocators/CudaManaged.h>
+
+namespace TNL {
+namespace Benchmarks {
+
+template< typename Real = double,
+          typename Index = int >
+void
+benchmarkTriad( Benchmark & benchmark,
+                const long & size )
+{
+   using HostAllocator = Allocators::Host< Real >;
+   using CudaAllocator = Allocators::Cuda< Real >;
+   using CudaHostAllocator = Allocators::CudaHost< Real >;
+   using CudaManagedAllocator = Allocators::CudaManaged< Real >;
+
+   double datasetSize = (double) size * sizeof(Real) / oneGB;
+   benchmark.setOperation( "triad", 3 * datasetSize );
+
+   const Real scalar = 3.1415926535;
+
+   // pageable
+   {
+      using HostArray = Containers::Array< Real, Devices::Host, Index, HostAllocator >;
+      using CudaArray = Containers::Array< Real, Devices::Cuda, Index, CudaAllocator >;
+
+      HostArray a_h, b_h, c_h;
+      CudaArray a_d, b_d, c_d;
+      a_h.setSize( size );
+      b_h.setSize( size );
+      c_h.setSize( size );
+      a_d.setSize( size );
+      b_d.setSize( size );
+      c_d.setSize( size );
+
+      auto reset = [&]()
+      {
+         a_h.setValue( 1.0 );
+         b_h.setValue( 1.0 );
+         c_h.setValue( 1.0 );
+         a_d.setValue( 0.0 );
+         b_d.setValue( 0.0 );
+         c_d.setValue( 0.0 );
+      };
+
+      auto triad = [&]()
+      {
+         b_d = b_h;
+         c_d = c_h;
+
+         auto a_v = a_d.getView();
+         const auto b_v = b_d.getConstView();
+         const auto c_v = c_d.getConstView();
+         auto kernel = [=] __cuda_callable__ ( Index i ) mutable
+         {
+            a_v[i] = b_v[i] + scalar * c_v[i];
+         };
+         ParallelFor< Devices::Cuda >::exec( (long) 0, size, kernel );
+
+         a_h = a_d;
+      };
+
+      benchmark.time< Devices::Cuda >( reset, "pageable", triad );
+   }
+
+   // pinned
+   {
+      using HostArray = Containers::Array< Real, Devices::Host, Index, CudaHostAllocator >;
+      using CudaArray = Containers::Array< Real, Devices::Cuda, Index, CudaAllocator >;
+
+      HostArray a_h, b_h, c_h;
+      CudaArray a_d, b_d, c_d;
+      a_h.setSize( size );
+      b_h.setSize( size );
+      c_h.setSize( size );
+      a_d.setSize( size );
+      b_d.setSize( size );
+      c_d.setSize( size );
+
+      auto reset = [&]()
+      {
+         a_h.setValue( 1.0 );
+         b_h.setValue( 1.0 );
+         c_h.setValue( 1.0 );
+         a_d.setValue( 0.0 );
+         b_d.setValue( 0.0 );
+         c_d.setValue( 0.0 );
+      };
+
+      auto triad = [&]()
+      {
+         b_d = b_h;
+         c_d = c_h;
+
+         auto a_v = a_d.getView();
+         const auto b_v = b_d.getConstView();
+         const auto c_v = c_d.getConstView();
+         auto kernel = [=] __cuda_callable__ ( Index i ) mutable
+         {
+            a_v[i] = b_v[i] + scalar * c_v[i];
+         };
+         ParallelFor< Devices::Cuda >::exec( (long) 0, size, kernel );
+
+         a_h = a_d;
+      };
+
+      benchmark.time< Devices::Cuda >( reset, "pinned", triad );
+   }
+
+   // zero-copy
+   {
+      using HostArray = Containers::Array< Real, Devices::Host, Index, CudaHostAllocator >;
+
+      HostArray a_h, b_h, c_h;
+      a_h.setSize( size );
+      b_h.setSize( size );
+      c_h.setSize( size );
+
+      auto reset = [&]()
+      {
+         a_h.setValue( 1.0 );
+         b_h.setValue( 1.0 );
+         c_h.setValue( 1.0 );
+      };
+
+      auto a_v = a_h.getView();
+      const auto b_v = b_h.getConstView();
+      const auto c_v = c_h.getConstView();
+      auto kernel = [=] __cuda_callable__ ( Index i ) mutable
+      {
+         a_v[i] = b_v[i] + scalar * c_v[i];
+      };
+      auto triad = [&]()
+      {
+         ParallelFor< Devices::Cuda >::exec( (long) 0, size, kernel );
+      };
+
+      benchmark.time< Devices::Cuda >( reset, "zero-copy", triad );
+   }
+
+   // unified memory
+   {
+      using Array = Containers::Array< Real, Devices::Host, Index, CudaManagedAllocator >;
+
+      Array a, b, c;
+      a.setSize( size );
+      b.setSize( size );
+      c.setSize( size );
+
+      auto reset = [&]()
+      {
+         a.setValue( 1.0 );
+         b.setValue( 1.0 );
+         c.setValue( 1.0 );
+      };
+
+      auto a_v = a.getView();
+      const auto b_v = b.getConstView();
+      const auto c_v = c.getConstView();
+      auto kernel = [=] __cuda_callable__ ( Index i ) mutable
+      {
+         a_v[i] = b_v[i] + scalar * c_v[i];
+      };
+      auto triad = [&]()
+      {
+         ParallelFor< Devices::Cuda >::exec( (long) 0, size, kernel );
+      };
+
+      benchmark.time< Devices::Cuda >( reset, "unified memory", triad );
+   }
+
+   // TODO: unified memory with AccessedBy hint and/or prefetching - see https://github.com/cwpearson/triad-gpu-bandwidth
+}
+
+} // namespace Benchmarks
+} // namespace TNL
diff --git a/src/Benchmarks/BLAS/vector-operations.h b/src/Benchmarks/BLAS/vector-operations.h
index 6818ac9571f349ba50afe36beb5e9cec0b9f095b..219cbc33477be7d3cc697d3ed340ca7eae53b604 100644
--- a/src/Benchmarks/BLAS/vector-operations.h
+++ b/src/Benchmarks/BLAS/vector-operations.h
@@ -32,7 +32,7 @@ namespace Benchmarks {
 
 template< typename Real = double,
           typename Index = int >
-bool
+void
 benchmarkVectorOperations( Benchmark & benchmark,
                            const long & size )
 {
@@ -608,8 +608,6 @@ benchmarkVectorOperations( Benchmark & benchmark,
 #ifdef HAVE_CUDA
    cublasDestroy( cublasHandle );
 #endif
-
-   return true;
 }
 
 } // namespace Benchmarks
diff --git a/src/Benchmarks/FunctionTimer.h b/src/Benchmarks/FunctionTimer.h
index 6cef44aaf673e99459851509ca1318d904d8ecf4..a76ebd5589d38aac5d53687f6c7e7f48e732f8ff 100644
--- a/src/Benchmarks/FunctionTimer.h
+++ b/src/Benchmarks/FunctionTimer.h
@@ -20,8 +20,7 @@
 #include <TNL/Solvers/IterativeSolverMonitor.h>
 
 namespace TNL {
-   namespace Benchmarks {
-
+namespace Benchmarks {
 
 template< typename Device >
 class FunctionTimer
@@ -88,7 +87,7 @@ class FunctionTimer
                reset();
 
                // Explicit synchronization of the CUDA device
-#ifdef HAVE_CUDA      
+#ifdef HAVE_CUDA
                if( std::is_same< Device, Devices::Cuda >::value )
                   cudaDeviceSynchronize();
 #endif
@@ -127,9 +126,10 @@ class FunctionTimer
       {
          return this->loops;
       }
-      protected:
-         int loops;
+
+   protected:
+      int loops;
 };
 
-   } // namespace Benchmarks
+} // namespace Benchmarks
 } // namespace TNL
diff --git a/src/TNL/Allocators/Cuda.h b/src/TNL/Allocators/Cuda.h
new file mode 100644
index 0000000000000000000000000000000000000000..74ebb840432136d9033a17a86684607098a80d86
--- /dev/null
+++ b/src/TNL/Allocators/Cuda.h
@@ -0,0 +1,99 @@
+/***************************************************************************
+                          Cuda.h  -  description
+                             -------------------
+    begin                : Apr 8, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+// Implemented by: Jakub Klinkovsky
+
+#pragma once
+
+#include <TNL/Devices/Cuda.h>
+
+namespace TNL {
+namespace Allocators {
+
+/**
+ * \brief Allocator for the CUDA device memory space.
+ *
+ * The allocation is done using the `cudaMalloc` function and the deallocation
+ * is done using the `cudaFree` function.
+ */
+template< class T >
+struct Cuda
+{
+   using value_type = T;
+   using size_type = std::size_t;
+   using difference_type = std::ptrdiff_t;
+
+   Cuda() = default;
+   Cuda( const Cuda& ) = default;
+   Cuda( Cuda&& ) = default;
+
+   Cuda& operator=( const Cuda& ) = default;
+   Cuda& operator=( Cuda&& ) = default;
+
+   template< class U >
+   Cuda( const Cuda< U >& )
+   {}
+
+   template< class U >
+   Cuda( Cuda< U >&& )
+   {}
+
+   template< class U >
+   Cuda& operator=( const Cuda< U >& )
+   {
+      return *this;
+   }
+
+   template< class U >
+   Cuda& operator=( Cuda< U >&& )
+   {
+      return *this;
+   }
+
+   value_type* allocate( size_type n )
+   {
+#ifdef HAVE_CUDA
+      TNL_CHECK_CUDA_DEVICE;
+      value_type* result = nullptr;
+      if( cudaMalloc( (void**) &result, n * sizeof(value_type) ) != cudaSuccess )
+         throw Exceptions::CudaBadAlloc();
+      TNL_CHECK_CUDA_DEVICE;
+      return result;
+#else
+      throw Exceptions::CudaSupportMissing();
+#endif
+   }
+
+   void deallocate(value_type* ptr, size_type)
+   {
+#ifdef HAVE_CUDA
+      TNL_CHECK_CUDA_DEVICE;
+      cudaFree( ptr );
+      TNL_CHECK_CUDA_DEVICE;
+#else
+      throw Exceptions::CudaSupportMissing();
+#endif
+   }
+};
+
+template<class T1, class T2>
+bool operator==(const Cuda<T1>&, const Cuda<T2>&)
+{
+   return true;
+}
+
+template<class T1, class T2>
+bool operator!=(const Cuda<T1>& lhs, const Cuda<T2>& rhs)
+{
+   return !(lhs == rhs);
+}
+
+} // namespace Allocators
+} // namespace TNL
diff --git a/src/TNL/Allocators/CudaHost.h b/src/TNL/Allocators/CudaHost.h
new file mode 100644
index 0000000000000000000000000000000000000000..284c91fe9b8dbc7abe8e3d4685ef1d7551d19a89
--- /dev/null
+++ b/src/TNL/Allocators/CudaHost.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+                          CudaHost.h  -  description
+                             -------------------
+    begin                : Apr 8, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+// Implemented by: Jakub Klinkovsky
+
+#pragma once
+
+#include <TNL/Devices/Cuda.h>
+
+namespace TNL {
+namespace Allocators {
+
+/**
+ * \brief Allocator for page-locked memory on the host.
+ *
+ * The allocation is done using the `cudaMallocHost` function and the
+ * deallocation is done using the `cudaFreeHost` function.
+ */
+template< class T >
+struct CudaHost
+{
+   using value_type = T;
+   using size_type = std::size_t;
+   using difference_type = std::ptrdiff_t;
+
+   CudaHost() = default;
+   CudaHost( const CudaHost& ) = default;
+   CudaHost( CudaHost&& ) = default;
+
+   CudaHost& operator=( const CudaHost& ) = default;
+   CudaHost& operator=( CudaHost&& ) = default;
+
+   template< class U >
+   CudaHost( const CudaHost< U >& )
+   {}
+
+   template< class U >
+   CudaHost( CudaHost< U >&& )
+   {}
+
+   template< class U >
+   CudaHost& operator=( const CudaHost< U >& )
+   {
+      return *this;
+   }
+
+   template< class U >
+   CudaHost& operator=( CudaHost< U >&& )
+   {
+      return *this;
+   }
+
+   value_type* allocate( size_type n )
+   {
+#ifdef HAVE_CUDA
+      TNL_CHECK_CUDA_DEVICE;
+      value_type* result = nullptr;
+      // cudaHostAllocPortable - The memory returned by this call will be considered as pinned memory by all
+      //                       CUDA contexts, not just the one that performed the allocation.
+      // cudaHostAllocMapped - Maps the allocation into the CUDA address space.
+      // Also note that we assume that the cudaDevAttrCanUseHostPointerForRegisteredMem attribute is non-zero
+      // on all devices visible to the application, in which case the pointer returned by cudaMallocHost can
+      // be used directly by all devices without having to call cudaHostGetDevicePointer. See the reference:
+      // https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__MEMORY.html#group__CUDART__MEMORY_1gc00502b44e5f1bdc0b424487ebb08db0
+      if( cudaMallocHost( (void**) &result, n * sizeof(value_type), cudaHostAllocPortable | cudaHostAllocMapped ) != cudaSuccess )
+         throw Exceptions::CudaBadAlloc();
+      TNL_CHECK_CUDA_DEVICE;
+      return result;
+#else
+      throw Exceptions::CudaSupportMissing();
+#endif
+   }
+
+   void deallocate(value_type* ptr, size_type)
+   {
+#ifdef HAVE_CUDA
+      TNL_CHECK_CUDA_DEVICE;
+      cudaFreeHost( ptr );
+      TNL_CHECK_CUDA_DEVICE;
+#else
+      throw Exceptions::CudaSupportMissing();
+#endif
+   }
+};
+
+template<class T1, class T2>
+bool operator==(const CudaHost<T1>&, const CudaHost<T2>&)
+{
+   return true;
+}
+
+template<class T1, class T2>
+bool operator!=(const CudaHost<T1>& lhs, const CudaHost<T2>& rhs)
+{
+   return !(lhs == rhs);
+}
+
+} // namespace Allocators
+} // namespace TNL
diff --git a/src/TNL/Allocators/CudaManaged.h b/src/TNL/Allocators/CudaManaged.h
new file mode 100644
index 0000000000000000000000000000000000000000..db29f86cb618bf79e4f1c0fa0ac1ad2750d476bc
--- /dev/null
+++ b/src/TNL/Allocators/CudaManaged.h
@@ -0,0 +1,101 @@
+/***************************************************************************
+                          CudaManaged.h  -  description
+                             -------------------
+    begin                : Apr 8, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+// Implemented by: Jakub Klinkovsky
+
+#pragma once
+
+#include <TNL/Devices/Cuda.h>
+
+namespace TNL {
+namespace Allocators {
+
+/**
+ * \brief Allocator for the CUDA Unified Memory system.
+ *
+ * The memory allocated by this allocator will be automatically managed by the
+ * CUDA Unified Memory system. The allocation is done using the
+ * `cudaMallocManaged` function and the deallocation is done using the
+ * `cudaFree` function.
+ */
+template< class T >
+struct CudaManaged
+{
+   using value_type = T;
+   using size_type = std::size_t;
+   using difference_type = std::ptrdiff_t;
+
+   CudaManaged() = default;
+   CudaManaged( const CudaManaged& ) = default;
+   CudaManaged( CudaManaged&& ) = default;
+
+   CudaManaged& operator=( const CudaManaged& ) = default;
+   CudaManaged& operator=( CudaManaged&& ) = default;
+
+   template< class U >
+   CudaManaged( const CudaManaged< U >& )
+   {}
+
+   template< class U >
+   CudaManaged( CudaManaged< U >&& )
+   {}
+
+   template< class U >
+   CudaManaged& operator=( const CudaManaged< U >& )
+   {
+      return *this;
+   }
+
+   template< class U >
+   CudaManaged& operator=( CudaManaged< U >&& )
+   {
+      return *this;
+   }
+
+   value_type* allocate( size_type n )
+   {
+#ifdef HAVE_CUDA
+      TNL_CHECK_CUDA_DEVICE;
+      value_type* result = nullptr;
+      if( cudaMallocManaged( &result, n * sizeof(value_type) ) != cudaSuccess )
+         throw Exceptions::CudaBadAlloc();
+      TNL_CHECK_CUDA_DEVICE;
+      return result;
+#else
+      throw Exceptions::CudaSupportMissing();
+#endif
+   }
+
+   void deallocate(value_type* ptr, size_type)
+   {
+#ifdef HAVE_CUDA
+      TNL_CHECK_CUDA_DEVICE;
+      cudaFree( ptr );
+      TNL_CHECK_CUDA_DEVICE;
+#else
+      throw Exceptions::CudaSupportMissing();
+#endif
+   }
+};
+
+template<class T1, class T2>
+bool operator==(const CudaManaged<T1>&, const CudaManaged<T2>&)
+{
+   return true;
+}
+
+template<class T1, class T2>
+bool operator!=(const CudaManaged<T1>& lhs, const CudaManaged<T2>& rhs)
+{
+   return !(lhs == rhs);
+}
+
+} // namespace Allocators
+} // namespace TNL
diff --git a/src/TNL/Allocators/Default.h b/src/TNL/Allocators/Default.h
new file mode 100644
index 0000000000000000000000000000000000000000..6906a905c3a82d3e2400c4ba6a767848bf1be061
--- /dev/null
+++ b/src/TNL/Allocators/Default.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+                          Default.h  -  description
+                             -------------------
+    begin                : Jul 2, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+// Implemented by: Jakub Klinkovsky
+
+#pragma once
+
+#include <TNL/Allocators/Host.h>
+#include <TNL/Allocators/Cuda.h>
+#include <TNL/Allocators/MIC.h>
+#include <TNL/Devices/Host.h>
+#include <TNL/Devices/Cuda.h>
+#include <TNL/Devices/MIC.h>
+
+namespace TNL {
+namespace Allocators {
+
+/**
+ * \brief A trait-like class used for the selection of a default allocators for
+ * given device.
+ */
+template< typename Device >
+struct Default;
+
+//! Sets \ref Allocators::Host as the default allocator for \ref Devices::Host.
+template<>
+struct Default< Devices::Host >
+{
+   template< typename T >
+   using Allocator = Allocators::Host< T >;
+};
+
+//! Sets \ref Allocators::Cuda as the default allocator for \ref Devices::Cuda.
+template<>
+struct Default< Devices::Cuda >
+{
+   template< typename T >
+   using Allocator = Allocators::Cuda< T >;
+};
+
+//! Sets \ref Allocators::MIC as the default allocator for \ref Devices::MIC.
+template<>
+struct Default< Devices::MIC >
+{
+   template< typename T >
+   using Allocator = Allocators::MIC< T >;
+};
+
+} // namespace Allocators
+} // namespace TNL
diff --git a/src/TNL/Allocators/Host.h b/src/TNL/Allocators/Host.h
new file mode 100644
index 0000000000000000000000000000000000000000..65c0b18c11c11eb97bbb91de9619ecaa6d976b18
--- /dev/null
+++ b/src/TNL/Allocators/Host.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+                          Host.h  -  description
+                             -------------------
+    begin                : Apr 8, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+// Implemented by: Jakub Klinkovsky
+
+#pragma once
+
+#include <memory>
+
+namespace TNL {
+
+/**
+ * \brief Namespace for TNL allocators.
+ *
+ * All TNL allocators must satisfy the requirements imposed by the
+ * [Allocator concept](https://en.cppreference.com/w/cpp/named_req/Allocator)
+ * from STL.
+ */
+namespace Allocators {
+
+/**
+ * \brief Allocator for the host memory space -- alias for \ref std::allocator.
+ */
+template< class T >
+using Host = std::allocator< T >;
+
+} // namespace Allocators
+} // namespace TNL
diff --git a/src/TNL/Allocators/MIC.h b/src/TNL/Allocators/MIC.h
new file mode 100644
index 0000000000000000000000000000000000000000..c3599f449cd85f9f83c0ef0e5974bb015d04a6ef
--- /dev/null
+++ b/src/TNL/Allocators/MIC.h
@@ -0,0 +1,100 @@
+/***************************************************************************
+                          MIC.h  -  description
+                             -------------------
+    begin                : Jul 2, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+// Implemented by: Jakub Klinkovsky
+
+#pragma once
+
+#include <TNL/Devices/MIC.h>
+#include <TNL/Exceptions/MICSupportMissing.h>
+
+namespace TNL {
+namespace Allocators {
+
+/**
+ * \brief Allocator for the MIC device memory space.
+ */
+template< class T >
+struct MIC
+{
+   using value_type = T;
+   using size_type = std::size_t;
+   using difference_type = std::ptrdiff_t;
+
+   MIC() = default;
+   MIC( const MIC& ) = default;
+   MIC( MIC&& ) = default;
+
+   MIC& operator=( const MIC& ) = default;
+   MIC& operator=( MIC&& ) = default;
+
+   template< class U >
+   MIC( const MIC< U >& )
+   {}
+
+   template< class U >
+   MIC( MIC< U >&& )
+   {}
+
+   template< class U >
+   MIC& operator=( const MIC< U >& )
+   {
+      return *this;
+   }
+
+   template< class U >
+   MIC& operator=( MIC< U >&& )
+   {
+      return *this;
+   }
+
+   value_type* allocate( size_type size )
+   {
+#ifdef HAVE_MIC
+      Devices::MICHider<void> hide_ptr;
+      #pragma offload target(mic) out(hide_ptr) in(size)
+      {
+         hide_ptr.pointer = malloc(size * sizeof(value_type));
+      }
+      return hide_ptr.pointer;
+#else
+      throw Exceptions::MICSupportMissing();
+#endif
+   }
+
+   void deallocate(value_type* ptr, size_type)
+   {
+#ifdef HAVE_MIC
+      Devices::MICHider<void> hide_ptr;
+      hide_ptr.pointer=ptr;
+      #pragma offload target(mic) in(hide_ptr)
+      {
+         free(hide_ptr.pointer);
+      }
+#else
+      throw Exceptions::MICSupportMissing();
+#endif
+   }
+};
+
+template<class T1, class T2>
+bool operator==(const MIC<T1>&, const MIC<T2>&)
+{
+   return true;
+}
+
+template<class T1, class T2>
+bool operator!=(const MIC<T1>& lhs, const MIC<T2>& rhs)
+{
+   return !(lhs == rhs);
+}
+
+} // namespace Allocators
+} // namespace TNL
diff --git a/src/TNL/Containers/Algorithms/ArrayAssignment.h b/src/TNL/Containers/Algorithms/ArrayAssignment.h
index dbf0f82b95cc380d343755167ab4b268403b353b..5d45bbbceb86b1468da9efeccdec15e3a4b37de8 100644
--- a/src/TNL/Containers/Algorithms/ArrayAssignment.h
+++ b/src/TNL/Containers/Algorithms/ArrayAssignment.h
@@ -40,7 +40,7 @@ public:
 template< typename Array,
           typename T,
           bool hasGetArrayData = detail::HasGetArrayData< T >::value >
-struct ArrayAssignment{};
+struct ArrayAssignment;
 
 /**
  * \brief Specialization for array-array assignment with containers implementing
@@ -60,7 +60,7 @@ struct ArrayAssignment< Array, T, true >
       TNL_ASSERT_EQ( a.getSize(), t.getSize(), "The sizes of the arrays must be equal." );
       if( t.getSize() > 0 ) // we allow even assignment of empty arrays
          ArrayOperations< typename Array::DeviceType, typename T::DeviceType >::template
-            copyMemory< typename Array::ValueType, typename T::ValueType, typename Array::IndexType >
+            copy< typename Array::ValueType, typename T::ValueType, typename Array::IndexType >
             ( a.getArrayData(), t.getArrayData(), t.getSize() );
    }
 };
@@ -81,7 +81,7 @@ struct ArrayAssignment< Array, T, false >
    {
       TNL_ASSERT_FALSE( a.empty(), "Cannot assign value to empty array." );
       ArrayOperations< typename Array::DeviceType >::template
-         setMemory< typename Array::ValueType, typename Array::IndexType >
+         set< typename Array::ValueType, typename Array::IndexType >
          ( a.getArrayData(), ( typename Array::ValueType ) t, a.getSize() );
    }
 };
diff --git a/src/TNL/Containers/Algorithms/ArrayOperations.h b/src/TNL/Containers/Algorithms/ArrayOperations.h
index a6acc816edc4e20a73949c49df42164e365475b9..7977b6b728f1b9827b569d2520ef322d2f49b432 100644
--- a/src/TNL/Containers/Algorithms/ArrayOperations.h
+++ b/src/TNL/Containers/Algorithms/ArrayOperations.h
@@ -10,7 +10,6 @@
 
 #pragma once
 
-#include <list>
 #include <TNL/Devices/Host.h>
 #include <TNL/Devices/Cuda.h>
 #include <TNL/Devices/MIC.h>
@@ -21,255 +20,231 @@ namespace Algorithms {
 
 template< typename DestinationDevice,
           typename SourceDevice = DestinationDevice >
-class ArrayOperations{};
+struct ArrayOperations;
 
 template<>
-class ArrayOperations< Devices::Host >
+struct ArrayOperations< Devices::Host >
 {
-   public:
-
-      template< typename Element, typename Index >
-      static void allocateMemory( Element*& data,
-                                  const Index size );
-
-      template< typename Element >
-      static void freeMemory( Element* data );
-
-      template< typename Element >
-      static void setMemoryElement( Element* data,
-                                    const Element& value );
-
-      template< typename Element >
-      static Element getMemoryElement( const Element* data );
-
-      template< typename Element, typename Index >
-      static void setMemory( Element* data,
-                             const Element& value,
-                             const Index size );
-
-      template< typename DestinationElement,
-                typename SourceElement,
-                typename Index >
-      static void copyMemory( DestinationElement* destination,
-                              const SourceElement* source,
-                              const Index size );
-
-      template< typename DestinationElement,
-                typename SourceElement >
-      static void copySTLList( DestinationElement* destination,
-                               const std::list< SourceElement >& source );
-
-      template< typename Element1,
-                typename Element2,
-                typename Index >
-      static bool compareMemory( const Element1* destination,
-                                 const Element2* source,
-                                 const Index size );
-
-      template< typename Element,
-                typename Index >
-      static bool containsValue( const Element* data,
-                                 const Index size,
-                                 const Element& value );
-
-      template< typename Element,
-                typename Index >
-      static bool containsOnlyValue( const Element* data,
-                                     const Index size,
-                                     const Element& value );
+   template< typename Element >
+   static void setElement( Element* data,
+                           const Element& value );
+
+   template< typename Element >
+   static Element getElement( const Element* data );
+
+   template< typename Element, typename Index >
+   static void set( Element* data,
+                    const Element& value,
+                    const Index size );
+
+   template< typename DestinationElement,
+             typename SourceElement,
+             typename Index >
+   static void copy( DestinationElement* destination,
+                     const SourceElement* source,
+                     const Index size );
+
+   template< typename DestinationElement,
+             typename Index,
+             typename SourceIterator >
+   static void copyFromIterator( DestinationElement* destination,
+                                 Index destinationSize,
+                                 SourceIterator first,
+                                 SourceIterator last );
+
+   template< typename Element1,
+             typename Element2,
+             typename Index >
+   static bool compare( const Element1* destination,
+                        const Element2* source,
+                        const Index size );
+
+   template< typename Element,
+             typename Index >
+   static bool containsValue( const Element* data,
+                              const Index size,
+                              const Element& value );
+
+   template< typename Element,
+             typename Index >
+   static bool containsOnlyValue( const Element* data,
+                                  const Index size,
+                                  const Element& value );
 };
 
 template<>
-class ArrayOperations< Devices::Cuda >
+struct ArrayOperations< Devices::Cuda >
 {
-   public:
-
-      template< typename Element, typename Index >
-      static void allocateMemory( Element*& data,
-                                  const Index size );
-
-      template< typename Element >
-      static void freeMemory( Element* data );
-
-      template< typename Element >
-      static void setMemoryElement( Element* data,
-                                    const Element& value );
-
-      template< typename Element >
-      static Element getMemoryElement( const Element* data );
-
-      template< typename Element, typename Index >
-      static void setMemory( Element* data,
-                             const Element& value,
-                             const Index size );
-
-      template< typename DestinationElement,
-                typename SourceElement,
-                typename Index >
-      static void copyMemory( DestinationElement* destination,
-                              const SourceElement* source,
-                              const Index size );
-
-      template< typename DestinationElement,
-                typename SourceElement >
-      static void copySTLList( DestinationElement* destination,
-                               const std::list< SourceElement >& source );
-
-      template< typename Element1,
-                typename Element2,
-                typename Index >
-      static bool compareMemory( const Element1* destination,
-                                 const Element2* source,
-                                 const Index size );
-
-      template< typename Element,
-                typename Index >
-      static bool containsValue( const Element* data,
-                                 const Index size,
-                                 const Element& value );
-
-      template< typename Element,
-                typename Index >
-      static bool containsOnlyValue( const Element* data,
-                                     const Index size,
-                                     const Element& value );
+   template< typename Element >
+   static void setElement( Element* data,
+                           const Element& value );
+
+   template< typename Element >
+   static Element getElement( const Element* data );
+
+   template< typename Element, typename Index >
+   static void set( Element* data,
+                    const Element& value,
+                    const Index size );
+
+   template< typename DestinationElement,
+             typename SourceElement,
+             typename Index >
+   static void copy( DestinationElement* destination,
+                     const SourceElement* source,
+                     const Index size );
+
+   template< typename DestinationElement,
+             typename Index,
+             typename SourceIterator >
+   static void copyFromIterator( DestinationElement* destination,
+                                 Index destinationSize,
+                                 SourceIterator first,
+                                 SourceIterator last );
+
+   template< typename Element1,
+             typename Element2,
+             typename Index >
+   static bool compare( const Element1* destination,
+                        const Element2* source,
+                        const Index size );
+
+   template< typename Element,
+             typename Index >
+   static bool containsValue( const Element* data,
+                              const Index size,
+                              const Element& value );
+
+   template< typename Element,
+             typename Index >
+   static bool containsOnlyValue( const Element* data,
+                                  const Index size,
+                                  const Element& value );
 };
 
 template<>
-class ArrayOperations< Devices::Cuda, Devices::Host >
+struct ArrayOperations< Devices::Cuda, Devices::Host >
 {
-   public:
-
-      template< typename DestinationElement,
-                typename SourceElement,
-                typename Index >
-      static void copyMemory( DestinationElement* destination,
-                              const SourceElement* source,
-                              const Index size );
-
-      template< typename DestinationElement,
-                typename SourceElement,
-                typename Index >
-      static bool compareMemory( const DestinationElement* destination,
-                                 const SourceElement* source,
-                                 const Index size );
+   template< typename DestinationElement,
+             typename SourceElement,
+             typename Index >
+   static void copy( DestinationElement* destination,
+                     const SourceElement* source,
+                     const Index size );
+
+   template< typename DestinationElement,
+             typename SourceElement,
+             typename Index >
+   static bool compare( const DestinationElement* destination,
+                        const SourceElement* source,
+                        const Index size );
 };
 
 template<>
-class ArrayOperations< Devices::Host, Devices::Cuda >
+struct ArrayOperations< Devices::Host, Devices::Cuda >
 {
-   public:
-
-      template< typename DestinationElement,
-                typename SourceElement,
-                typename Index >
-      static void copyMemory( DestinationElement* destination,
-                              const SourceElement* source,
-                              const Index size );
-
-      template< typename Element1,
-                typename Element2,
-                typename Index >
-      static bool compareMemory( const Element1* destination,
-                                 const Element2* source,
-                                 const Index size );
+   template< typename DestinationElement,
+             typename SourceElement,
+             typename Index >
+   static void copy( DestinationElement* destination,
+                     const SourceElement* source,
+                     const Index size );
+
+   template< typename Element1,
+             typename Element2,
+             typename Index >
+   static bool compare( const Element1* destination,
+                        const Element2* source,
+                        const Index size );
 };
 
 
 template<>
-class ArrayOperations< Devices::MIC >
+struct ArrayOperations< Devices::MIC >
 {
-   public:
-
-      template< typename Element, typename Index >
-      static void allocateMemory( Element*& data,
-                                  const Index size );
-
-      template< typename Element >
-      static void freeMemory( Element* data );
-
-      template< typename Element >
-      static void setMemoryElement( Element* data,
-                                    const Element& value );
-
-      template< typename Element >
-      static Element getMemoryElement( const Element* data );
-
-      template< typename Element, typename Index >
-      static void setMemory( Element* data,
-                             const Element& value,
-                             const Index size );
-
-      template< typename DestinationElement,
-                typename SourceElement,
-                typename Index >
-      static void copyMemory( DestinationElement* destination,
-                              const SourceElement* source,
-                              const Index size );
-
-      template< typename DestinationElement,
-                typename SourceElement >
-      static void copySTLList( DestinationElement* destination,
-                               const std::list< SourceElement >& source );
-
-      template< typename Element1,
-                typename Element2,
-                typename Index >
-      static bool compareMemory( const Element1* destination,
-                                 const Element2* source,
-                                 const Index size );
-
-      template< typename Element,
-                typename Index >
-      static bool containsValue( const Element* data,
-                                 const Index size,
-                                 const Element& value );
-
-      template< typename Element,
-                typename Index >
-      static bool containsOnlyValue( const Element* data,
-                                     const Index size,
-                                     const Element& value );
+   template< typename Element >
+   static void setElement( Element* data,
+                           const Element& value );
+
+   template< typename Element >
+   static Element getElement( const Element* data );
+
+   template< typename Element, typename Index >
+   static void set( Element* data,
+                    const Element& value,
+                    const Index size );
+
+   template< typename DestinationElement,
+             typename SourceElement,
+             typename Index >
+   static void copy( DestinationElement* destination,
+                     const SourceElement* source,
+                     const Index size );
+
+   template< typename DestinationElement,
+             typename Index,
+             typename SourceIterator >
+   static void copyFromIterator( DestinationElement* destination,
+                                 Index destinationSize,
+                                 SourceIterator first,
+                                 SourceIterator last );
+
+   template< typename Element1,
+             typename Element2,
+             typename Index >
+   static bool compare( const Element1* destination,
+                        const Element2* source,
+                        const Index size );
+
+   template< typename Element,
+             typename Index >
+   static bool containsValue( const Element* data,
+                              const Index size,
+                              const Element& value );
+
+   template< typename Element,
+             typename Index >
+   static bool containsOnlyValue( const Element* data,
+                                  const Index size,
+                                  const Element& value );
 };
 
 template<>
-class ArrayOperations< Devices::MIC, Devices::Host >
+struct ArrayOperations< Devices::MIC, Devices::Host >
 {
    public:
 
       template< typename DestinationElement,
                 typename SourceElement,
                 typename Index >
-      static void copyMemory( DestinationElement* destination,
-                              const SourceElement* source,
-                              const Index size );
+      static void copy( DestinationElement* destination,
+                        const SourceElement* source,
+                        const Index size );
 
       template< typename DestinationElement,
                 typename SourceElement,
                 typename Index >
-      static bool compareMemory( const DestinationElement* destination,
-                                 const SourceElement* source,
-                                 const Index size );
+      static bool compare( const DestinationElement* destination,
+                           const SourceElement* source,
+                           const Index size );
 };
 
 template<>
-class ArrayOperations< Devices::Host, Devices::MIC >
+struct ArrayOperations< Devices::Host, Devices::MIC >
 {
-   public:
-
-      template< typename DestinationElement,
-                typename SourceElement,
-                typename Index >
-      static void copyMemory( DestinationElement* destination,
-                              const SourceElement* source,
-                              const Index size );
-
-      template< typename DestinationElement,
-                typename SourceElement,
-                typename Index >
-      static bool compareMemory( const DestinationElement* destination,
-                                 const SourceElement* source,
-                                 const Index size );
+   template< typename DestinationElement,
+             typename SourceElement,
+             typename Index >
+   static void copy( DestinationElement* destination,
+                     const SourceElement* source,
+                     const Index size );
+
+   template< typename DestinationElement,
+             typename SourceElement,
+             typename Index >
+   static bool compare( const DestinationElement* destination,
+                        const SourceElement* source,
+                        const Index size );
 };
 
 } // namespace Algorithms
diff --git a/src/TNL/Containers/Algorithms/ArrayOperationsCuda.hpp b/src/TNL/Containers/Algorithms/ArrayOperationsCuda.hpp
index 3e696672c9ef1d4f817db36253dc3e28ecb47146..e916be6aa8cc6959414b9011f2314c0ed2921595 100644
--- a/src/TNL/Containers/Algorithms/ArrayOperationsCuda.hpp
+++ b/src/TNL/Containers/Algorithms/ArrayOperationsCuda.hpp
@@ -12,11 +12,11 @@
 
 #include <iostream>
 #include <memory>
+#include <stdexcept>
 
 #include <TNL/Math.h>
 #include <TNL/ParallelFor.h>
 #include <TNL/Exceptions/CudaSupportMissing.h>
-#include <TNL/Exceptions/CudaBadAlloc.h>
 #include <TNL/Containers/Algorithms/ArrayOperations.h>
 #include <TNL/Containers/Algorithms/Reduction.h>
 #include <TNL/Containers/Algorithms/ReductionOperations.h>
@@ -25,68 +25,33 @@ namespace TNL {
 namespace Containers {
 namespace Algorithms {
 
-template< typename Element, typename Index >
-void
-ArrayOperations< Devices::Cuda >::
-allocateMemory( Element*& data,
-                const Index size )
-{
-#ifdef HAVE_CUDA
-   TNL_CHECK_CUDA_DEVICE;
-   if( cudaMalloc( ( void** ) &data,
-                   ( std::size_t ) size * sizeof( Element ) ) != cudaSuccess )
-   {
-      data = 0;
-      throw Exceptions::CudaBadAlloc();
-   }
-   TNL_CHECK_CUDA_DEVICE;
-#else
-   throw Exceptions::CudaSupportMissing();
-#endif
-}
-
 template< typename Element >
 void
 ArrayOperations< Devices::Cuda >::
-freeMemory( Element* data )
-{
-   TNL_ASSERT_TRUE( data, "Attempted to free a nullptr." );
-#ifdef HAVE_CUDA
-   TNL_CHECK_CUDA_DEVICE;
-   cudaFree( data );
-   TNL_CHECK_CUDA_DEVICE;
-#else
-   throw Exceptions::CudaSupportMissing();
-#endif
-}
-
-template< typename Element >
-void
-ArrayOperations< Devices::Cuda >::
-setMemoryElement( Element* data,
-                  const Element& value )
+setElement( Element* data,
+            const Element& value )
 {
    TNL_ASSERT_TRUE( data, "Attempted to set data through a nullptr." );
-   ArrayOperations< Devices::Cuda >::setMemory( data, value, 1 );
+   ArrayOperations< Devices::Cuda >::set( data, value, 1 );
 }
 
 template< typename Element >
 Element
 ArrayOperations< Devices::Cuda >::
-getMemoryElement( const Element* data )
+getElement( const Element* data )
 {
    TNL_ASSERT_TRUE( data, "Attempted to get data through a nullptr." );
    Element result;
-   ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory< Element, Element, int >( &result, data, 1 );
+   ArrayOperations< Devices::Host, Devices::Cuda >::copy< Element, Element, int >( &result, data, 1 );
    return result;
 }
 
 template< typename Element, typename Index >
 void
 ArrayOperations< Devices::Cuda >::
-setMemory( Element* data,
-           const Element& value,
-           const Index size )
+set( Element* data,
+     const Element& value,
+     const Index size )
 {
    TNL_ASSERT_TRUE( data, "Attempted to set data through a nullptr." );
    auto kernel = [data, value] __cuda_callable__ ( Index i )
@@ -101,9 +66,9 @@ template< typename DestinationElement,
           typename Index >
 void
 ArrayOperations< Devices::Cuda >::
-copyMemory( DestinationElement* destination,
-            const SourceElement* source,
-            const Index size )
+copy( DestinationElement* destination,
+      const SourceElement* source,
+      const Index size )
 {
    TNL_ASSERT_TRUE( destination, "Attempted to copy data to a nullptr." );
    TNL_ASSERT_TRUE( source, "Attempted to copy data from a nullptr." );
@@ -130,35 +95,37 @@ copyMemory( DestinationElement* destination,
 }
 
 template< typename DestinationElement,
-          typename SourceElement >
+          typename Index,
+          typename SourceIterator >
 void
 ArrayOperations< Devices::Cuda >::
-copySTLList( DestinationElement* destination,
-             const std::list< SourceElement >& source )
+copyFromIterator( DestinationElement* destination,
+                  Index destinationSize,
+                  SourceIterator first,
+                  SourceIterator last )
 {
-   const auto size = source.size();
-   const std::size_t copy_buffer_size = std::min( Devices::Cuda::TransferBufferSize / (std::size_t) sizeof( DestinationElement ), ( std::size_t ) size );
    using BaseType = typename std::remove_cv< DestinationElement >::type;
-   std::unique_ptr< BaseType[] > copy_buffer{ new BaseType[ copy_buffer_size ] };
-   std::size_t copiedElements = 0;
-   auto it = source.begin();
-   while( copiedElements < size )
-   {
-      const auto copySize = std::min( size - copiedElements, copy_buffer_size );
-      for( std::size_t i = 0; i < copySize; i++ )
-         copy_buffer[ i ] = static_cast< DestinationElement >( * it ++ );
-      ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory( &destination[ copiedElements ], &copy_buffer[ 0 ], copySize );
-      copiedElements += copySize;
+   std::unique_ptr< BaseType[] > buffer{ new BaseType[ Devices::Cuda::getGPUTransferBufferSize() ] };
+   Index copiedElements = 0;
+   while( copiedElements < destinationSize && first != last ) {
+      Index i = 0;
+      while( i < Devices::Cuda::getGPUTransferBufferSize() && first != last )
+         buffer[ i++ ] = *first++;
+      ArrayOperations< Devices::Cuda, Devices::Host >::copy( &destination[ copiedElements ], buffer.get(), i );
+      copiedElements += i;
    }
+   if( first != last )
+      throw std::length_error( "Source iterator is larger than the destination array." );
 }
+
 template< typename Element1,
           typename Element2,
           typename Index >
 bool
 ArrayOperations< Devices::Cuda >::
-compareMemory( const Element1* destination,
-               const Element2* source,
-               const Index size )
+compare( const Element1* destination,
+         const Element2* source,
+         const Index size )
 {
    TNL_ASSERT_TRUE( destination, "Attempted to compare data through a nullptr." );
    TNL_ASSERT_TRUE( source, "Attempted to compare data through a nullptr." );
@@ -215,9 +182,9 @@ template< typename DestinationElement,
           typename Index >
 void
 ArrayOperations< Devices::Host, Devices::Cuda >::
-copyMemory( DestinationElement* destination,
-            const SourceElement* source,
-            const Index size )
+copy( DestinationElement* destination,
+      const SourceElement* source,
+      const Index size )
 {
    TNL_ASSERT_TRUE( destination, "Attempted to copy data to a nullptr." );
    TNL_ASSERT_TRUE( source, "Attempted to copy data from a nullptr." );
@@ -264,9 +231,9 @@ template< typename Element1,
           typename Index >
 bool
 ArrayOperations< Devices::Host, Devices::Cuda >::
-compareMemory( const Element1* destination,
-               const Element2* source,
-               const Index size )
+compare( const Element1* destination,
+         const Element2* source,
+         const Index size )
 {
    /***
     * Here, destination is on host and source is on CUDA device.
@@ -286,7 +253,7 @@ compareMemory( const Element1* destination,
                       cudaMemcpyDeviceToHost ) != cudaSuccess )
          std::cerr << "Transfer of data from CUDA device to host failed." << std::endl;
       TNL_CHECK_CUDA_DEVICE;
-      if( ! ArrayOperations< Devices::Host >::compareMemory( &destination[ compared ], host_buffer.get(), transfer ) )
+      if( ! ArrayOperations< Devices::Host >::compare( &destination[ compared ], host_buffer.get(), transfer ) )
          return false;
       compared += transfer;
    }
@@ -304,9 +271,9 @@ template< typename DestinationElement,
           typename Index >
 void
 ArrayOperations< Devices::Cuda, Devices::Host >::
-copyMemory( DestinationElement* destination,
-            const SourceElement* source,
-            const Index size )
+copy( DestinationElement* destination,
+      const SourceElement* source,
+      const Index size )
 {
    TNL_ASSERT_TRUE( destination, "Attempted to copy data to a nullptr." );
    TNL_ASSERT_TRUE( source, "Attempted to copy data from a nullptr." );
@@ -352,14 +319,14 @@ template< typename Element1,
           typename Index >
 bool
 ArrayOperations< Devices::Cuda, Devices::Host >::
-compareMemory( const Element1* hostData,
-               const Element2* deviceData,
-               const Index size )
+compare( const Element1* hostData,
+         const Element2* deviceData,
+         const Index size )
 {
    TNL_ASSERT_TRUE( hostData, "Attempted to compare data through a nullptr." );
    TNL_ASSERT_TRUE( deviceData, "Attempted to compare data through a nullptr." );
    TNL_ASSERT_GE( size, (Index) 0, "Array size must be non-negative." );
-   return ArrayOperations< Devices::Host, Devices::Cuda >::compareMemory( deviceData, hostData, size );
+   return ArrayOperations< Devices::Host, Devices::Cuda >::compare( deviceData, hostData, size );
 }
 
 } // namespace Algorithms
diff --git a/src/TNL/Containers/Algorithms/ArrayOperationsHost.hpp b/src/TNL/Containers/Algorithms/ArrayOperationsHost.hpp
index 390b9120754ee6d16f9f551cbab691f45fc102cc..4cfe789ecad8307875b25a7e0e61b49dc44a3ca0 100644
--- a/src/TNL/Containers/Algorithms/ArrayOperationsHost.hpp
+++ b/src/TNL/Containers/Algorithms/ArrayOperationsHost.hpp
@@ -11,6 +11,7 @@
 #pragma once
 
 #include <type_traits>
+#include <stdexcept>
 #include <string.h>
 
 #include <TNL/ParallelFor.h>
@@ -22,33 +23,11 @@ namespace TNL {
 namespace Containers {
 namespace Algorithms {
 
-template< typename Element, typename Index >
-void
-ArrayOperations< Devices::Host >::
-allocateMemory( Element*& data,
-                const Index size )
-{
-   data = new Element[ size ];
-   // According to the standard, new either throws, or returns non-nullptr.
-   // Some (old) compilers don't comply:
-   // https://stackoverflow.com/questions/550451/will-new-return-null-in-any-case
-   TNL_ASSERT_TRUE( data, "Operator 'new' returned a nullptr. This should never happen - there is "
-                          "either a bug or the compiler does not comply to the standard." );
-}
-
-template< typename Element >
-void
-ArrayOperations< Devices::Host >::
-freeMemory( Element* data )
-{
-   delete[] data;
-}
-
 template< typename Element >
 void
 ArrayOperations< Devices::Host >::
-setMemoryElement( Element* data,
-                  const Element& value )
+setElement( Element* data,
+            const Element& value )
 {
    TNL_ASSERT_TRUE( data, "Attempted to set data through a nullptr." );
    *data = value;
@@ -57,7 +36,7 @@ setMemoryElement( Element* data,
 template< typename Element >
 Element
 ArrayOperations< Devices::Host >::
-getMemoryElement( const Element* data )
+getElement( const Element* data )
 {
    TNL_ASSERT_TRUE( data, "Attempted to get data through a nullptr." );
    return *data;
@@ -66,9 +45,9 @@ getMemoryElement( const Element* data )
 template< typename Element, typename Index >
 void
 ArrayOperations< Devices::Host >::
-setMemory( Element* data,
-           const Element& value,
-           const Index size )
+set( Element* data,
+     const Element& value,
+     const Index size )
 {
    TNL_ASSERT_TRUE( data, "Attempted to set data through a nullptr." );
    auto kernel = [data, value]( Index i )
@@ -83,9 +62,9 @@ template< typename DestinationElement,
           typename Index >
 void
 ArrayOperations< Devices::Host >::
-copyMemory( DestinationElement* destination,
-            const SourceElement* source,
-            const Index size )
+copy( DestinationElement* destination,
+      const SourceElement* source,
+      const Index size )
 {
    if( std::is_same< DestinationElement, SourceElement >::value &&
        ( std::is_fundamental< DestinationElement >::value ||
@@ -113,15 +92,20 @@ copyMemory( DestinationElement* destination,
 }
 
 template< typename DestinationElement,
-          typename SourceElement >
+          typename Index,
+          typename SourceIterator >
 void
 ArrayOperations< Devices::Host >::
-copySTLList( DestinationElement* destination,
-             const std::list< SourceElement >& source )
+copyFromIterator( DestinationElement* destination,
+                  Index destinationSize,
+                  SourceIterator first,
+                  SourceIterator last )
 {
-   std::size_t i = 0;
-   for( const SourceElement& e : source )
-      destination[ i++ ] = e;
+   Index i = 0;
+   while( i < destinationSize && first != last )
+      destination[ i++ ] = *first++;
+   if( first != last )
+      throw std::length_error( "Source iterator is larger than the destination array." );
 }
 
 
@@ -130,9 +114,9 @@ template< typename DestinationElement,
           typename Index >
 bool
 ArrayOperations< Devices::Host >::
-compareMemory( const DestinationElement* destination,
-               const SourceElement* source,
-               const Index size )
+compare( const DestinationElement* destination,
+         const SourceElement* source,
+         const Index size )
 {
    TNL_ASSERT_TRUE( destination, "Attempted to compare data through a nullptr." );
    TNL_ASSERT_TRUE( source, "Attempted to compare data through a nullptr." );
diff --git a/src/TNL/Containers/Algorithms/ArrayOperationsMIC.hpp b/src/TNL/Containers/Algorithms/ArrayOperationsMIC.hpp
index b0f09fb026fcdb2f0124cba6657b24c269c8c96a..5bf04dbaf5374cf564932f93b64aabdc5dba4a6a 100644
--- a/src/TNL/Containers/Algorithms/ArrayOperationsMIC.hpp
+++ b/src/TNL/Containers/Algorithms/ArrayOperationsMIC.hpp
@@ -16,7 +16,6 @@
 
 #include <TNL/Math.h>
 #include <TNL/Exceptions/MICSupportMissing.h>
-#include <TNL/Exceptions/MICBadAlloc.h>
 #include <TNL/Containers/Algorithms/ArrayOperations.h>
 #include <TNL/Containers/Algorithms/Reduction.h>
 #include <TNL/Containers/Algorithms/ReductionOperations.h>
@@ -28,61 +27,33 @@ namespace Algorithms {
 
 static constexpr std::size_t MIC_STACK_VAR_LIM = 5*1024*1024;
 
-template< typename Element, typename Index >
-void
-ArrayOperations< Devices::MIC >::
-allocateMemory( Element*& data,
-                const Index size )
-{
-#ifdef HAVE_MIC
-   data = (Element*) Devices::MIC::AllocMIC( size * sizeof(Element) );
-   if( ! data )
-      throw Exceptions::MICBadAlloc();
-#else
-   throw Exceptions::MICSupportMissing();
-#endif
-}
-
-template< typename Element >
-void
-ArrayOperations< Devices::MIC >::
-freeMemory( Element* data )
-{
-   TNL_ASSERT( data, );
-#ifdef HAVE_MIC
-   Devices::MIC::FreeMIC( data );
-#else
-   throw Exceptions::MICSupportMissing();
-#endif
-}
-
 template< typename Element >
 void
 ArrayOperations< Devices::MIC >::
-setMemoryElement( Element* data,
-                  const Element& value )
+setElement( Element* data,
+            const Element& value )
 {
    TNL_ASSERT( data, );
-   ArrayOperations< Devices::MIC >::setMemory( data, value, 1 );
+   ArrayOperations< Devices::MIC >::set( data, value, 1 );
 }
 
 template< typename Element >
 Element
 ArrayOperations< Devices::MIC >::
-getMemoryElement( const Element* data )
+getElement( const Element* data )
 {
    TNL_ASSERT( data, );
    Element result;
-   ArrayOperations< Devices::Host, Devices::MIC >::copyMemory< Element, Element, int >( &result, data, 1 );
+   ArrayOperations< Devices::Host, Devices::MIC >::copy< Element, Element, int >( &result, data, 1 );
    return result;
 }
 
 template< typename Element, typename Index >
 void
 ArrayOperations< Devices::MIC >::
-setMemory( Element* data,
-           const Element& value,
-           const Index size )
+set( Element* data,
+     const Element& value,
+     const Index size )
 {
    TNL_ASSERT( data, );
 #ifdef HAVE_MIC
@@ -105,9 +76,9 @@ template< typename DestinationElement,
           typename Index >
 void
 ArrayOperations< Devices::MIC >::
-copyMemory( DestinationElement* destination,
-            const SourceElement* source,
-            const Index size )
+copy( DestinationElement* destination,
+      const SourceElement* source,
+      const Index size )
 {
    TNL_ASSERT( destination, );
    TNL_ASSERT( source, );
@@ -141,11 +112,14 @@ copyMemory( DestinationElement* destination,
 }
 
 template< typename DestinationElement,
-          typename SourceElement >
+          typename Index,
+          typename SourceIterator >
 void
 ArrayOperations< Devices::MIC >::
-copySTLList( DestinationElement* destination,
-                  const std::list< SourceElement >& source )
+copyFromIterator( DestinationElement* destination,
+                  Index destinationSize,
+                  SourceIterator first,
+                  SourceIterator last )
 {
    throw Exceptions::NotImplementedError();
 }
@@ -155,9 +129,9 @@ template< typename Element1,
           typename Index >
 bool
 ArrayOperations< Devices::MIC >::
-compareMemory( const Element1* destination,
-               const Element2* source,
-               const Index size )
+compare( const Element1* destination,
+         const Element2* source,
+         const Index size )
 {
    TNL_ASSERT( destination, );
    TNL_ASSERT( source, );
@@ -247,9 +221,9 @@ template< typename DestinationElement,
           typename Index >
 void
 ArrayOperations< Devices::Host, Devices::MIC >::
-copyMemory( DestinationElement* destination,
-            const SourceElement* source,
-            const Index size )
+copy( DestinationElement* destination,
+      const SourceElement* source,
+      const Index size )
 {
    TNL_ASSERT( destination, );
    TNL_ASSERT( source, );
@@ -322,9 +296,9 @@ template< typename Element1,
           typename Index >
 bool
 ArrayOperations< Devices::Host, Devices::MIC >::
-compareMemory( const Element1* destination,
-               const Element2* source,
-               const Index size )
+compare( const Element1* destination,
+         const Element2* source,
+         const Index size )
 {
    /***
     * Here, destination is on host and source is on MIC device.
@@ -348,7 +322,7 @@ compareMemory( const Element1* destination,
      {
          memcpy((void*)&host_buffer,(void*)src_ptr.pointer,transfer*sizeof(Element2));
      }
-     if( ! ArrayOperations< Devices::Host >::compareMemory( &destination[ compared ], (Element2*)&host_buffer, transfer ) )
+     if( ! ArrayOperations< Devices::Host >::compare( &destination[ compared ], (Element2*)&host_buffer, transfer ) )
      {
         return false;
      }
@@ -368,9 +342,9 @@ template< typename DestinationElement,
           typename Index >
 void
 ArrayOperations< Devices::MIC, Devices::Host >::
-copyMemory( DestinationElement* destination,
-            const SourceElement* source,
-            const Index size )
+copy( DestinationElement* destination,
+      const SourceElement* source,
+      const Index size )
 {
    TNL_ASSERT( destination, );
    TNL_ASSERT( source, );
@@ -441,14 +415,14 @@ template< typename Element1,
           typename Index >
 bool
 ArrayOperations< Devices::MIC, Devices::Host >::
-compareMemory( const Element1* hostData,
-               const Element2* deviceData,
-               const Index size )
+compare( const Element1* hostData,
+         const Element2* deviceData,
+         const Index size )
 {
    TNL_ASSERT( hostData, );
    TNL_ASSERT( deviceData, );
    TNL_ASSERT( size >= 0, std::cerr << "size = " << size );
-   return ArrayOperations< Devices::Host, Devices::MIC >::compareMemory( deviceData, hostData, size );
+   return ArrayOperations< Devices::Host, Devices::MIC >::compare( deviceData, hostData, size );
 }
 
 } // namespace Algorithms
diff --git a/src/TNL/Containers/Algorithms/CudaReductionKernel.h b/src/TNL/Containers/Algorithms/CudaReductionKernel.h
index 21613c497864e26cc7562061fcc85cc4ef38266c..5973747fbfb15cff3df93c072c16dfef4aa344f2 100644
--- a/src/TNL/Containers/Algorithms/CudaReductionKernel.h
+++ b/src/TNL/Containers/Algorithms/CudaReductionKernel.h
@@ -402,7 +402,7 @@ struct CudaReductionKernelLauncher
       ////
       // Copy result on CPU
       ResultType result;
-      ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( &result, output, 1 );
+      ArrayOperations< Devices::Host, Devices::Cuda >::copy( &result, output, 1 );
       return result;
    }
 
@@ -438,8 +438,8 @@ struct CudaReductionKernelLauncher
       ////
       // Copy result on CPU
       ResultType result;
-      ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( &result, output, 1 );
-      ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( &argument, idxOutput, 1 );
+      ArrayOperations< Devices::Host, Devices::Cuda >::copy( &result, output, 1 );
+      ArrayOperations< Devices::Host, Devices::Cuda >::copy( &argument, idxOutput, 1 );
       return result;
    }
 
diff --git a/src/TNL/Containers/Algorithms/Multireduction_impl.h b/src/TNL/Containers/Algorithms/Multireduction_impl.h
index a4c5ff26e49df3b289ab3c4e15e86225901ed99c..ebd0ad2562a4795fcea6abeb9287b5063b92c408 100644
--- a/src/TNL/Containers/Algorithms/Multireduction_impl.h
+++ b/src/TNL/Containers/Algorithms/Multireduction_impl.h
@@ -76,11 +76,11 @@ reduce( Operation& operation,
     */
    if( n * ldInput1 < Multireduction_minGpuDataSize ) {
       DataType1 hostArray1[ Multireduction_minGpuDataSize ];
-      ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( hostArray1, deviceInput1, n * ldInput1 );
+      ArrayOperations< Devices::Host, Devices::Cuda >::copy( hostArray1, deviceInput1, n * ldInput1 );
       if( deviceInput2 ) {
          using _DT2 = typename std::conditional< std::is_same< DataType2, void >::value, DataType1, DataType2 >::type;
          _DT2 hostArray2[ Multireduction_minGpuDataSize ];
-         ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( hostArray2, (_DT2*) deviceInput2, size );
+         ArrayOperations< Devices::Host, Devices::Cuda >::copy( hostArray2, (_DT2*) deviceInput2, size );
          Multireduction< Devices::Host >::reduce( operation, n, size, hostArray1, ldInput1, hostArray2, hostResult );
       }
       else {
@@ -117,7 +117,7 @@ reduce( Operation& operation,
     * Transfer the reduced data from device to host.
     */
    ResultType resultArray[ n * reducedSize ];
-   ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( resultArray, deviceAux1, n * reducedSize );
+   ArrayOperations< Devices::Host, Devices::Cuda >::copy( resultArray, deviceAux1, n * reducedSize );
 
    #ifdef CUDA_REDUCTION_PROFILING
       timer.stop();
diff --git a/src/TNL/Containers/Algorithms/Reduction.hpp b/src/TNL/Containers/Algorithms/Reduction.hpp
index 21aaf015474032e80cca3b8616de7cb11c37d4e0..818fe963f836617a332188a0c34952ec129ca9f9 100644
--- a/src/TNL/Containers/Algorithms/Reduction.hpp
+++ b/src/TNL/Containers/Algorithms/Reduction.hpp
@@ -326,7 +326,7 @@ Reduction< Devices::Cuda >::
        * Transfer the reduced data from device to host.
        */
       std::unique_ptr< ResultType[] > resultArray{ new ResultType[ reducedSize ] };
-      ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( resultArray.get(), deviceAux1, reducedSize );
+      ArrayOperations< Devices::Host, Devices::Cuda >::copy( resultArray.get(), deviceAux1, reducedSize );
 
       #ifdef CUDA_REDUCTION_PROFILING
          timer.stop();
@@ -427,8 +427,8 @@ reduceWithArgument( const Index size,
        */
       std::unique_ptr< ResultType[] > resultArray{ new ResultType[ reducedSize ] };
       std::unique_ptr< IndexType[] > indexArray{ new IndexType[ reducedSize ] };
-      ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( resultArray.get(), deviceAux1, reducedSize );
-      ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( indexArray.get(), deviceIndexes, reducedSize );
+      ArrayOperations< Devices::Host, Devices::Cuda >::copy( resultArray.get(), deviceAux1, reducedSize );
+      ArrayOperations< Devices::Host, Devices::Cuda >::copy( indexArray.get(), deviceIndexes, reducedSize );
 
       #ifdef CUDA_REDUCTION_PROFILING
          timer.stop();
diff --git a/src/TNL/Containers/Array.h b/src/TNL/Containers/Array.h
index 06cae8787ffeec6097070a69f013de29c22eea32..7f4d898e9a4fe4e620331090a57baa3240804bb0 100644
--- a/src/TNL/Containers/Array.h
+++ b/src/TNL/Containers/Array.h
@@ -15,6 +15,7 @@
 
 #include <TNL/File.h>
 #include <TNL/TypeTraits.h>
+#include <TNL/Allocators/Default.h>
 #include <TNL/Containers/ArrayView.h>
 
 namespace TNL {
@@ -30,10 +31,13 @@ template< int, typename > class StaticArray;
  * elements, and general array operations.
  *
  * \tparam Value  The type of array elements.
- * \tparam Device The device where the array is to be allocated. This ensures
- *                the compile-time checks of correct pointers manipulation. It
- *                can be either \ref Devices::Host or \ref Devices::Cuda.
+ * \tparam Device The device to be used for the execution of array operations.
+ *                It can be either \ref Devices::Host or \ref Devices::Cuda.
  * \tparam Index  The indexing type.
+ * \tparam Allocator The type of the allocator used for the allocation and
+ *                   deallocation of memory used by the array. By default,
+ *                   an appropriate allocator for the specified \e Device
+ *                   is selected with \ref Allocators::Default.
  *
  * Memory management handled by constructors and destructors according to the
  * [RAII](https://en.wikipedia.org/wiki/RAII) principle and by methods
@@ -64,7 +68,8 @@ template< int, typename > class StaticArray;
  */
 template< typename Value,
           typename Device = Devices::Host,
-          typename Index = int >
+          typename Index = int,
+          typename Allocator = typename Allocators::Default< Device >::template Allocator< Value > >
 class Array
 {
    public:
@@ -72,6 +77,7 @@ class Array
       using ValueType = Value;
       using DeviceType = Device;
       using IndexType = Index;
+      using AllocatorType = Allocator;
       using HostType = Containers::Array< Value, Devices::Host, Index >;
       using CudaType = Containers::Array< Value, Devices::Cuda, Index >;
       using ViewType = ArrayView< Value, Device, Index >;
@@ -80,14 +86,22 @@ class Array
       /**
        * \brief Constructs an empty array with zero size.
        */
-      Array();
+      Array() = default;
+
+      /**
+       * \brief Constructs an empty array and sets the provided allocator.
+       *
+       * \param allocator The allocator to be associated with this array.
+       */
+      explicit Array( const AllocatorType& allocator );
 
       /**
        * \brief Constructs an array with given size.
        *
        * \param size The number of array elements to be allocated.
+       * \param allocator The allocator to be associated with this array.
        */
-      Array( const IndexType& size );
+      explicit Array( const IndexType& size, const AllocatorType& allocator = AllocatorType() );
 
       /**
        * \brief Constructs an array with given size and copies data from given
@@ -95,9 +109,11 @@ class Array
        *
        * \param data The pointer to the data to be copied to the array.
        * \param size The number of array elements to be copied to the array.
+       * \param allocator The allocator to be associated with this array.
        */
       Array( Value* data,
-             const IndexType& size );
+             const IndexType& size,
+             const AllocatorType& allocator = AllocatorType() );
 
       /**
        * \brief Copy constructor.
@@ -106,16 +122,26 @@ class Array
        */
       explicit Array( const Array& array );
 
+      /**
+       * \brief Copy constructor with a specific allocator.
+       *
+       * \param array The array to be copied.
+       * \param allocator The allocator to be associated with this array.
+       */
+      explicit Array( const Array& array, const AllocatorType& allocator );
+
       /**
        * \brief Copy constructor.
        *
        * \param array The array to be copied.
        * \param begin The first index which should be copied.
        * \param size The number of elements that should be copied.
+       * \param allocator The allocator to be associated with this array.
        */
       Array( const Array& array,
              IndexType begin,
-             IndexType size = 0 );
+             IndexType size = 0,
+             const AllocatorType& allocator = AllocatorType() );
 
       /**
        * \brief Move constructor for initialization from \e rvalues.
@@ -129,27 +155,40 @@ class Array
        * \ref std::initializer_list, e.g. `{...}`.
        *
        * \param list The initializer list containing elements to be copied.
+       * \param allocator The allocator to be associated with this array.
        */
       template< typename InValue >
-      Array( const std::initializer_list< InValue >& list );
+      Array( const std::initializer_list< InValue >& list,
+             const AllocatorType& allocator = AllocatorType() );
 
       /**
        * \brief Constructor which initializes the array by copying elements from
        * \ref std::list.
        *
        * \param list The STL list containing elements to be copied.
+       * \param allocator The allocator to be associated with this array.
        */
       template< typename InValue >
-      Array( const std::list< InValue >& list );
+      Array( const std::list< InValue >& list,
+             const AllocatorType& allocator = AllocatorType() );
+
 
       /**
        * \brief Constructor which initializes the array by copying elements from
        * \ref std::vector.
        *
        * \param vector The STL vector containing elements to be copied.
+       * \param allocator The allocator to be associated with this array.
        */
       template< typename InValue >
-      Array( const std::vector< InValue >& vector );
+      Array( const std::vector< InValue >& vector,
+             const AllocatorType& allocator = AllocatorType() );
+
+
+      /**
+       * \brief Returns the allocator associated with the array.
+       */
+      AllocatorType getAllocator() const;
 
       /**
        * \brief Returns a \ref String representation of the array type in C++ style.
@@ -259,9 +298,9 @@ class Array
       /**
        * \brief Returns a modifiable view of the array.
        *
-       * If \e begin or \e end is set to a non-zero value, a view for the
-       * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-       * array is returned.
+       * By default, a view for the whole array is returned. If \e begin or
+       * \e end is set to a non-zero value, a view only for the sub-interval
+       * `[begin, end)` is returned.
        *
        * \param begin The beginning of the array sub-interval. It is 0 by
        *              default.
@@ -273,9 +312,9 @@ class Array
       /**
        * \brief Returns a non-modifiable view of the array.
        *
-       * If \e begin or \e end is set to a non-zero value, a view for the
-       * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-       * array is returned.
+       * By default, a view for the whole array is returned. If \e begin or
+       * \e end is set to a non-zero value, a view only for the sub-interval
+       * `[begin, end)` is returned.
        *
        * \param begin The beginning of the array sub-interval. It is 0 by
        *              default.
@@ -287,9 +326,9 @@ class Array
       /**
        * \brief Returns a non-modifiable view of the array.
        *
-       * If \e begin or \e end is set to a non-zero value, a view for the
-       * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-       * array is returned.
+       * By default, a view for the whole array is returned. If \e begin or
+       * \e end is set to a non-zero value, a view only for the sub-interval
+       * `[begin, end)` is returned.
        *
        * \param begin The beginning of the array sub-interval. It is 0 by
        *              default.
@@ -586,7 +625,7 @@ class Array
    protected:
 
       /** \brief Method for releasing (deallocating) array data. */
-      void releaseData() const;
+      void releaseData();
 
       /** \brief Number of elements in the array. */
       mutable Index size = 0;
@@ -612,28 +651,33 @@ class Array
        * more arrays. This is to avoid unnecessary dynamic memory allocation.
        */
       mutable int* referenceCounter = nullptr;
+
+      /**
+       * \brief The internal allocator instance.
+       */
+      Allocator allocator;
 };
 
-template< typename Value, typename Device, typename Index >
-std::ostream& operator<<( std::ostream& str, const Array< Value, Device, Index >& array );
+template< typename Value, typename Device, typename Index, typename Allocator >
+std::ostream& operator<<( std::ostream& str, const Array< Value, Device, Index, Allocator >& array );
 
 /**
  * \brief Serialization of arrays into binary files.
  */
-template< typename Value, typename Device, typename Index >
-File& operator<<( File& file, const Array< Value, Device, Index >& array );
+template< typename Value, typename Device, typename Index, typename Allocator >
+File& operator<<( File& file, const Array< Value, Device, Index, Allocator >& array );
 
-template< typename Value, typename Device, typename Index >
-File& operator<<( File&& file, const Array< Value, Device, Index >& array );
+template< typename Value, typename Device, typename Index, typename Allocator >
+File& operator<<( File&& file, const Array< Value, Device, Index, Allocator >& array );
 
 /**
  * \brief Deserialization of arrays from binary files.
  */
-template< typename Value, typename Device, typename Index >
-File& operator>>( File& file, Array< Value, Device, Index >& array );
+template< typename Value, typename Device, typename Index, typename Allocator >
+File& operator>>( File& file, Array< Value, Device, Index, Allocator >& array );
 
-template< typename Value, typename Device, typename Index >
-File& operator>>( File&& file, Array< Value, Device, Index >& array );
+template< typename Value, typename Device, typename Index, typename Allocator >
+File& operator>>( File&& file, Array< Value, Device, Index, Allocator >& array );
 
 } // namespace Containers
 
diff --git a/src/TNL/Containers/Array.hpp b/src/TNL/Containers/Array.hpp
index 7b4f17f2a38565cd841216ff767e6220d4536664..76ce6384439c7ecb4f7dcc62a76d183ad4fd7e91 100644
--- a/src/TNL/Containers/Array.hpp
+++ b/src/TNL/Containers/Array.hpp
@@ -27,69 +27,73 @@ namespace Containers {
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >::
-Array()
-: size( 0 ),
-  data( 0 ),
-  allocationPointer( 0 ),
-  referenceCounter( 0 )
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >::
+Array( const Allocator& allocator )
+: allocator( allocator )
 {
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >::
-Array( const IndexType& size )
-: size( 0 ),
-  data( 0 ),
-  allocationPointer( 0 ),
-  referenceCounter( 0 )
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >::
+Array( const IndexType& size, const AllocatorType& allocator )
+: allocator( allocator )
 {
    this->setSize( size );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >::
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >::
 Array( Value* data,
-       const IndexType& size )
-: size( 0 ),
-  data( nullptr ),
-  allocationPointer( nullptr ),
-  referenceCounter( 0 )
+       const IndexType& size,
+       const AllocatorType& allocator )
+: allocator( allocator )
 {
    this->setSize( size );
-   Algorithms::ArrayOperations< Device >::copyMemory( this->getData(), data, size );
+   Algorithms::ArrayOperations< Device >::copy( this->getData(), data, size );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >::
-Array( const Array< Value, Device, Index >& array )
-: size( 0 ),
-  data( nullptr ),
-  allocationPointer( nullptr ),
-  referenceCounter( 0 )
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >::
+Array( const Array< Value, Device, Index, Allocator >& array )
 {
    this->setSize( array.getSize() );
-   Algorithms::ArrayOperations< Device >::copyMemory( this->getData(), array.getData(), array.getSize() );
+   Algorithms::ArrayOperations< Device >::copy( this->getData(), array.getData(), array.getSize() );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >::
-Array( const Array< Value, Device, Index >& array,
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >::
+Array( const Array< Value, Device, Index, Allocator >& array,
+       const AllocatorType& allocator )
+: allocator( allocator )
+{
+   this->setSize( array.getSize() );
+   Algorithms::ArrayOperations< Device >::copy( this->getData(), array.getData(), array.getSize() );
+}
+
+template< typename Value,
+          typename Device,
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >::
+Array( const Array< Value, Device, Index, Allocator >& array,
        IndexType begin,
-       IndexType size )
-: size( size ),
-  data( nullptr ),
-  allocationPointer( nullptr ),
-  referenceCounter( 0 )
+       IndexType size,
+       const AllocatorType& allocator )
+: allocator( allocator )
 {
    if( size == 0 )
       size = array.getSize() - begin;
@@ -97,62 +101,71 @@ Array( const Array< Value, Device, Index >& array,
    TNL_ASSERT_LE( begin + size, array.getSize(), "End of array is out of bounds." );
 
    this->setSize( size );
-   Algorithms::ArrayOperations< Device >::copyMemory( this->getData(), &array.getData()[ begin ], size );
+   Algorithms::ArrayOperations< Device >::copy( this->getData(), &array.getData()[ begin ], size );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename InValue >
-Array< Value, Device, Index >::
-Array( const std::initializer_list< InValue >& list )
-: size( 0 ),
-  data( 0 ),
-  allocationPointer( 0 ),
-  referenceCounter( 0 )
+Array< Value, Device, Index, Allocator >::
+Array( const std::initializer_list< InValue >& list,
+       const AllocatorType& allocator )
+: allocator( allocator )
 {
    this->setSize( list.size() );
    // Here we assume that the underlying array for std::initializer_list is
    // const T[N] as noted here:
    // https://en.cppreference.com/w/cpp/utility/initializer_list
-   Algorithms::ArrayOperations< Device, Devices::Host >::copyMemory( this->getData(), &( *list.begin() ), list.size() );
+   Algorithms::ArrayOperations< Device, Devices::Host >::copy( this->getData(), &( *list.begin() ), list.size() );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename InValue >
-Array< Value, Device, Index >::
-Array( const std::list< InValue >& list )
-: size( 0 ),
-  data( 0 ),
-  allocationPointer( 0 ),
-  referenceCounter( 0 )
+Array< Value, Device, Index, Allocator >::
+Array( const std::list< InValue >& list,
+       const AllocatorType& allocator )
+: allocator( allocator )
 {
    this->setSize( list.size() );
-   Algorithms::ArrayOperations< Device >::copySTLList( this->getData(), list );
+   Algorithms::ArrayOperations< Device >::copyFromIterator( this->getData(), this->getSize(), list.cbegin(), list.cend() );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename InValue >
-Array< Value, Device, Index >::
-Array( const std::vector< InValue >& vector )
-: size( 0 ),
-  data( 0 ),
-  allocationPointer( 0 ),
-  referenceCounter( 0 )
+Array< Value, Device, Index, Allocator >::
+Array( const std::vector< InValue >& vector,
+       const AllocatorType& allocator )
+: allocator( allocator )
 {
    this->setSize( vector.size() );
-   Algorithms::ArrayOperations< Device, Devices::Host >::copyMemory( this->getData(), vector.data(), vector.size() );
+   Algorithms::ArrayOperations< Device, Devices::Host >::copy( this->getData(), vector.data(), vector.size() );
+}
+
+template< typename Value,
+          typename Device,
+          typename Index,
+          typename Allocator >
+Allocator
+Array< Value, Device, Index, Allocator >::
+getAllocator() const
+{
+   return allocator;
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 String
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getType()
 {
    return String( "Containers::Array< " ) +
@@ -163,9 +176,10 @@ getType()
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 String
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getTypeVirtual() const
 {
    return this->getType();
@@ -173,9 +187,10 @@ getTypeVirtual() const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 String
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getSerializationType()
 {
    return Algorithms::ArrayIO< Value, Device, Index >::getSerializationType();
@@ -183,9 +198,10 @@ getSerializationType()
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 String
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getSerializationTypeVirtual() const
 {
    return this->getSerializationType();
@@ -193,23 +209,24 @@ getSerializationTypeVirtual() const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Array< Value, Device, Index >::
-releaseData() const
+Array< Value, Device, Index, Allocator >::
+releaseData()
 {
    if( this->referenceCounter )
    {
       if( --*this->referenceCounter == 0 )
       {
-         Algorithms::ArrayOperations< Device >::freeMemory( this->allocationPointer );
+         allocator.deallocate( this->allocationPointer, this->size );
          delete this->referenceCounter;
          //std::cerr << "Deallocating reference counter " << this->referenceCounter << std::endl;
       }
    }
    else
       if( allocationPointer )
-         Algorithms::ArrayOperations< Device >::freeMemory( this->allocationPointer );
+         allocator.deallocate( this->allocationPointer, this->size );
    this->allocationPointer = 0;
    this->data = 0;
    this->size = 0;
@@ -218,9 +235,10 @@ releaseData() const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 setSize( Index size )
 {
    TNL_ASSERT_GE( size, (Index) 0, "Array size must be non-negative." );
@@ -232,7 +250,7 @@ setSize( Index size )
    // Allocating zero bytes is useless. Moreover, the allocators don't behave the same way:
    // "operator new" returns some non-zero address, the latter returns a null pointer.
    if( size > 0 ) {
-      Algorithms::ArrayOperations< Device >::allocateMemory( this->allocationPointer, size );
+      this->allocationPointer = allocator.allocate( size );
       this->data = this->allocationPointer;
       this->size = size;
       TNL_ASSERT_TRUE( this->allocationPointer,
@@ -242,10 +260,11 @@ setSize( Index size )
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 __cuda_callable__
 Index
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getSize() const
 {
    return this->size;
@@ -253,10 +272,11 @@ getSize() const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename ArrayT >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 setLike( const ArrayT& array )
 {
    setSize( array.getSize() );
@@ -264,9 +284,10 @@ setLike( const ArrayT& array )
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 bind( Value* data,
       const Index size )
 {
@@ -278,10 +299,11 @@ bind( Value* data,
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename ArrayT >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 bind( const ArrayT& array,
       const IndexType& begin,
       const IndexType& size )
@@ -318,10 +340,11 @@ bind( const ArrayT& array,
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< int Size >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 bind( StaticArray< Size, Value >& array )
 {
    this->releaseData();
@@ -331,9 +354,10 @@ bind( StaticArray< Size, Value >& array )
 
 template< typename Value,
           typename Device,
-          typename Index >
-typename Array< Value, Device, Index >::ViewType
-Array< Value, Device, Index >::
+          typename Index,
+          typename Allocator >
+typename Array< Value, Device, Index, Allocator >::ViewType
+Array< Value, Device, Index, Allocator >::
 getView( IndexType begin, IndexType end )
 {
    if( end == 0 )
@@ -343,9 +367,10 @@ getView( IndexType begin, IndexType end )
 
 template< typename Value,
           typename Device,
-          typename Index >
-typename Array< Value, Device, Index >::ConstViewType
-Array< Value, Device, Index >::
+          typename Index,
+          typename Allocator >
+typename Array< Value, Device, Index, Allocator >::ConstViewType
+Array< Value, Device, Index, Allocator >::
 getView( IndexType begin, IndexType end ) const
 {
    if( end == 0 )
@@ -355,9 +380,10 @@ getView( IndexType begin, IndexType end ) const
 
 template< typename Value,
           typename Device,
-          typename Index >
-typename Array< Value, Device, Index >::ConstViewType
-Array< Value, Device, Index >::
+          typename Index,
+          typename Allocator >
+typename Array< Value, Device, Index, Allocator >::ConstViewType
+Array< Value, Device, Index, Allocator >::
 getConstView( IndexType begin, IndexType end ) const
 {
    if( end == 0 )
@@ -367,8 +393,9 @@ getConstView( IndexType begin, IndexType end ) const
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >::
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >::
 operator ViewType()
 {
    return getView();
@@ -376,8 +403,9 @@ operator ViewType()
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >::
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >::
 operator ConstViewType() const
 {
    return getConstView();
@@ -385,10 +413,11 @@ operator ConstViewType() const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Array< Value, Device, Index >::
-swap( Array< Value, Device, Index >& array )
+Array< Value, Device, Index, Allocator >::
+swap( Array< Value, Device, Index, Allocator >& array )
 {
    TNL::swap( this->size, array.size );
    TNL::swap( this->data, array.data );
@@ -398,9 +427,10 @@ swap( Array< Value, Device, Index >& array )
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 reset()
 {
    this->releaseData();
@@ -408,10 +438,11 @@ reset()
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 __cuda_callable__
 const Value*
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getData() const
 {
    return this->data;
@@ -419,10 +450,11 @@ getData() const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 __cuda_callable__
 Value*
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getData()
 {
    return this->data;
@@ -430,10 +462,11 @@ getData()
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 __cuda_callable__
 const Value*
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getArrayData() const
 {
    return this->data;
@@ -441,10 +474,11 @@ getArrayData() const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 __cuda_callable__
 Value*
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getArrayData()
 {
    return this->data;
@@ -452,34 +486,37 @@ getArrayData()
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 setElement( const Index& i, const Value& x )
 {
    TNL_ASSERT_GE( i, (Index) 0, "Element index must be non-negative." );
    TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." );
-   return Algorithms::ArrayOperations< Device >::setMemoryElement( &( this->data[ i ] ), x );
+   return Algorithms::ArrayOperations< Device >::setElement( &( this->data[ i ] ), x );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 Value
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 getElement( const Index& i ) const
 {
    TNL_ASSERT_GE( i, (Index) 0, "Element index must be non-negative." );
    TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." );
-   return Algorithms::ArrayOperations< Device >::getMemoryElement( & ( this->data[ i ] ) );
+   return Algorithms::ArrayOperations< Device >::getElement( & ( this->data[ i ] ) );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 __cuda_callable__
 inline Value&
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 operator[]( const Index& i )
 {
    TNL_ASSERT_GE( i, (Index) 0, "Element index must be non-negative." );
@@ -489,10 +526,11 @@ operator[]( const Index& i )
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 __cuda_callable__
 inline const Value&
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 operator[]( const Index& i ) const
 {
    TNL_ASSERT_GE( i, (Index) 0, "Element index must be non-negative." );
@@ -502,17 +540,18 @@ operator[]( const Index& i ) const
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >&
-Array< Value, Device, Index >::
-operator=( const Array< Value, Device, Index >& array )
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >&
+Array< Value, Device, Index, Allocator >::
+operator=( const Array< Value, Device, Index, Allocator >& array )
 {
    //TNL_ASSERT_EQ( array.getSize(), this->getSize(), "Array sizes must be the same." );
    if( this->getSize() != array.getSize() )
       this->setLike( array );
    if( this->getSize() > 0 )
       Algorithms::ArrayOperations< Device >::
-         copyMemory( this->getData(),
+         copy( this->getData(),
                      array.getData(),
                      array.getSize() );
    return *this;
@@ -520,10 +559,11 @@ operator=( const Array< Value, Device, Index >& array )
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >&
-Array< Value, Device, Index >::
-operator=( Array< Value, Device, Index >&& array )
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >&
+Array< Value, Device, Index, Allocator >::
+operator=( Array< Value, Device, Index, Allocator >&& array )
 {
    reset();
 
@@ -542,10 +582,11 @@ operator=( Array< Value, Device, Index >&& array )
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename T >
-Array< Value, Device, Index >&
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >&
+Array< Value, Device, Index, Allocator >::
 operator=( const T& data )
 {
    Algorithms::ArrayAssignment< Array, T >::resize( *this, data );
@@ -555,37 +596,40 @@ operator=( const T& data )
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename InValue >
-Array< Value, Device, Index >&
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >&
+Array< Value, Device, Index, Allocator >::
 operator=( const std::list< InValue >& list )
 {
    this->setSize( list.size() );
-   Algorithms::ArrayOperations< Device >::copySTLList( this->getData(), list );
+   Algorithms::ArrayOperations< Device >::copyFromIterator( this->getData(), this->getSize(), list.cbegin(), list.cend() );
    return *this;
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename InValue >
-Array< Value, Device, Index >&
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >&
+Array< Value, Device, Index, Allocator >::
 operator=( const std::vector< InValue >& vector )
 {
    if( this->getSize() != vector.size() )
       this->setSize( vector.size() );
-   Algorithms::ArrayOperations< Device, Devices::Host >::copyMemory( this->getData(), vector.data(), vector.size() );
+   Algorithms::ArrayOperations< Device, Devices::Host >::copy( this->getData(), vector.data(), vector.size() );
    return *this;
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename ArrayT >
 bool
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 operator==( const ArrayT& array ) const
 {
    if( array.getSize() != this->getSize() )
@@ -593,17 +637,18 @@ operator==( const ArrayT& array ) const
    if( this->getSize() == 0 )
       return true;
    return Algorithms::ArrayOperations< Device, typename ArrayT::DeviceType >::
-            compareMemory( this->getData(),
+            compare( this->getData(),
                            array.getData(),
                            array.getSize() );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename ArrayT >
 bool
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 operator!=( const ArrayT& array ) const
 {
    return ! ( *this == array );
@@ -611,9 +656,10 @@ operator!=( const ArrayT& array ) const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 setValue( const ValueType& v,
           IndexType begin,
           IndexType end )
@@ -621,15 +667,16 @@ setValue( const ValueType& v,
    TNL_ASSERT_TRUE( this->getData(), "Attempted to set a value of an empty array." );
    if( end == 0 )
       end = this->getSize();
-   Algorithms::ArrayOperations< Device >::setMemory( &this->getData()[ begin ], v, end - begin );
+   Algorithms::ArrayOperations< Device >::set( &this->getData()[ begin ], v, end - begin );
 }
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename Function >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 evaluate( const Function& f,
           IndexType begin,
           IndexType end )
@@ -640,9 +687,10 @@ evaluate( const Function& f,
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 bool
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 containsValue( const ValueType& v,
                IndexType begin,
                IndexType end ) const
@@ -656,9 +704,10 @@ containsValue( const ValueType& v,
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 bool
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 containsOnlyValue( const ValueType& v,
                    IndexType begin,
                    IndexType end ) const
@@ -672,10 +721,11 @@ containsOnlyValue( const ValueType& v,
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 bool
 __cuda_callable__
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 empty() const
 {
    return ( data == nullptr );
@@ -683,9 +733,10 @@ empty() const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 save( const String& fileName ) const
 {
    File( fileName, std::ios_base::out ) << *this;
@@ -693,9 +744,10 @@ save( const String& fileName ) const
 
 template< typename Value,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Array< Value, Device, Index >::
+Array< Value, Device, Index, Allocator >::
 load( const String& fileName )
 {
    File( fileName, std::ios_base::in ) >> *this;
@@ -703,15 +755,16 @@ load( const String& fileName )
 
 template< typename Value,
           typename Device,
-          typename Index >
-Array< Value, Device, Index >::
+          typename Index,
+          typename Allocator >
+Array< Value, Device, Index, Allocator >::
 ~Array()
 {
    this->releaseData();
 }
 
-template< typename Value, typename Device, typename Index >
-std::ostream& operator<<( std::ostream& str, const Array< Value, Device, Index >& array )
+template< typename Value, typename Device, typename Index, typename Allocator >
+std::ostream& operator<<( std::ostream& str, const Array< Value, Device, Index, Allocator >& array )
 {
    str << "[ ";
    if( array.getSize() > 0 )
@@ -725,8 +778,8 @@ std::ostream& operator<<( std::ostream& str, const Array< Value, Device, Index >
 }
 
 // Serialization of arrays into binary files.
-template< typename Value, typename Device, typename Index >
-File& operator<<( File& file, const Array< Value, Device, Index >& array )
+template< typename Value, typename Device, typename Index, typename Allocator >
+File& operator<<( File& file, const Array< Value, Device, Index, Allocator >& array )
 {
    using IO = Algorithms::ArrayIO< Value, Device, Index >;
    saveObjectType( file, IO::getSerializationType() );
@@ -736,16 +789,16 @@ File& operator<<( File& file, const Array< Value, Device, Index >& array )
    return file;
 }
 
-template< typename Value, typename Device, typename Index >
-File& operator<<( File&& file, const Array< Value, Device, Index >& array )
+template< typename Value, typename Device, typename Index, typename Allocator >
+File& operator<<( File&& file, const Array< Value, Device, Index, Allocator >& array )
 {
    File& f = file;
    return f << array;
 }
 
 // Deserialization of arrays from binary files.
-template< typename Value, typename Device, typename Index >
-File& operator>>( File& file, Array< Value, Device, Index >& array )
+template< typename Value, typename Device, typename Index, typename Allocator >
+File& operator>>( File& file, Array< Value, Device, Index, Allocator >& array )
 {
    using IO = Algorithms::ArrayIO< Value, Device, Index >;
    const String type = getObjectType( file );
@@ -760,8 +813,8 @@ File& operator>>( File& file, Array< Value, Device, Index >& array )
    return file;
 }
 
-template< typename Value, typename Device, typename Index >
-File& operator>>( File&& file, Array< Value, Device, Index >& array )
+template< typename Value, typename Device, typename Index, typename Allocator >
+File& operator>>( File&& file, Array< Value, Device, Index, Allocator >& array )
 {
    File& f = file;
    return f >> array;
diff --git a/src/TNL/Containers/ArrayView.h b/src/TNL/Containers/ArrayView.h
index 5361b879924503914623b427aec14303f1b61232..3584efd217a2463e8dd5e622ecc82ebb032edaac 100644
--- a/src/TNL/Containers/ArrayView.h
+++ b/src/TNL/Containers/ArrayView.h
@@ -157,9 +157,9 @@ public:
    /**
     * \brief Returns a modifiable view of the array view.
     *
-    * If \e begin or \e end is set to a non-zero value, a view for the
-    * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-    * array view is returned.
+    * By default, a view for the whole array is returned. If \e begin or
+    * \e end is set to a non-zero value, a view only for the sub-interval
+    * `[begin, end)` is returned.
     *
     * \param begin The beginning of the array view sub-interval. It is 0 by
     *              default.
@@ -172,9 +172,9 @@ public:
    /**
     * \brief Returns a non-modifiable view of the array view.
     *
-    * If \e begin or \e end is set to a non-zero value, a view for the
-    * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-    * array view is returned.
+    * By default, a view for the whole array is returned. If \e begin or
+    * \e end is set to a non-zero value, a view only for the sub-interval
+    * `[begin, end)` is returned.
     *
     * \param begin The beginning of the array view sub-interval. It is 0 by
     *              default.
@@ -183,13 +183,13 @@ public:
     */
    __cuda_callable__
    ConstViewType getView( const IndexType begin = 0, IndexType end = 0 ) const;
-   
+
    /**
     * \brief Returns a non-modifiable view of the array view.
     *
-    * If \e begin or \e end is set to a non-zero value, a view for the
-    * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-    * array view is returned.
+    * By default, a view for the whole array is returned. If \e begin or
+    * \e end is set to a non-zero value, a view only for the sub-interval
+    * `[begin, end)` is returned.
     *
     * \param begin The beginning of the array view sub-interval. It is 0 by
     *              default.
diff --git a/src/TNL/Containers/ArrayView.hpp b/src/TNL/Containers/ArrayView.hpp
index 199704a5a5a9095d56cbd8bde46eeefbfeab05b4..8c70b5c0548c38d2c473edcff4bd877ed2de9409 100644
--- a/src/TNL/Containers/ArrayView.hpp
+++ b/src/TNL/Containers/ArrayView.hpp
@@ -125,7 +125,7 @@ operator=( const ArrayView& view )
 {
    TNL_ASSERT_EQ( getSize(), view.getSize(), "The sizes of the array views must be equal, views are not resizable." );
    if( getSize() > 0 )
-      Algorithms::ArrayOperations< Device >::copyMemory( getData(), view.getData(), getSize() );
+      Algorithms::ArrayOperations< Device >::copy( getData(), view.getData(), getSize() );
    return *this;
 }
 
@@ -229,7 +229,7 @@ setElement( Index i, Value value )
 {
    TNL_ASSERT_GE( i, 0, "Element index must be non-negative." );
    TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." );
-   return Algorithms::ArrayOperations< Device >::setMemoryElement( &data[ i ], value );
+   return Algorithms::ArrayOperations< Device >::setElement( &data[ i ], value );
 }
 
 template< typename Value,
@@ -241,7 +241,7 @@ getElement( Index i ) const
 {
    TNL_ASSERT_GE( i, 0, "Element index must be non-negative." );
    TNL_ASSERT_LT( i, this->getSize(), "Element index is out of bounds." );
-   return Algorithms::ArrayOperations< Device >::getMemoryElement( &data[ i ] );
+   return Algorithms::ArrayOperations< Device >::getElement( &data[ i ] );
 }
 
 template< typename Value,
@@ -282,7 +282,7 @@ operator==( const ArrayT& array ) const
    if( this->getSize() == 0 )
       return true;
    return Algorithms::ArrayOperations< DeviceType, typename ArrayT::DeviceType >::
-            compareMemory( this->getData(),
+            compare( this->getData(),
                            array.getData(),
                            array.getSize() );
 }
@@ -308,7 +308,7 @@ setValue( Value value, const Index begin, Index end )
    TNL_ASSERT_GT( size, 0, "Attempted to set value to an empty array view." );
    if( end == 0 )
       end = this->getSize();
-   Algorithms::ArrayOperations< Device >::setMemory( &getData()[ begin ], value, end - begin );
+   Algorithms::ArrayOperations< Device >::set( &getData()[ begin ], value, end - begin );
 }
 
 template< typename Value,
diff --git a/src/TNL/Containers/Expressions/Comparison.h b/src/TNL/Containers/Expressions/Comparison.h
index be68f9e18fc899de4b071219e8a95dce97951309..8f60702185081bfe6c8399602f803025fd002b64 100644
--- a/src/TNL/Containers/Expressions/Comparison.h
+++ b/src/TNL/Containers/Expressions/Comparison.h
@@ -45,7 +45,7 @@ struct VectorComparison< T1, T2, true >
 
    static bool EQ( const T1& a, const T2& b )
    {
-      return Algorithms::ArrayOperations< typename T1::DeviceType, typename T2::DeviceType >::compareMemory( a.getData(), b.getData(), a.getSize() );
+      return Algorithms::ArrayOperations< typename T1::DeviceType, typename T2::DeviceType >::compare( a.getData(), b.getData(), a.getSize() );
    }
 };
 
diff --git a/src/TNL/Containers/Expressions/ExpressionTemplates.h b/src/TNL/Containers/Expressions/ExpressionTemplates.h
index cb38585d93ebf870063d5f764d274ebcf9b290a1..b82035c0af04299652ce483c5dad2ccdf1d5011b 100644
--- a/src/TNL/Containers/Expressions/ExpressionTemplates.h
+++ b/src/TNL/Containers/Expressions/ExpressionTemplates.h
@@ -15,10 +15,11 @@
 #include <TNL/Containers/Expressions/ExpressionVariableType.h>
 #include <TNL/Containers/Expressions/Comparison.h>
 #include <TNL/Containers/Expressions/IsStatic.h>
+#include <TNL/Containers/Expressions/IsNumericExpression.h>
 
 namespace TNL {
-   namespace Containers {
-      namespace Expressions {
+namespace Containers {
+namespace Expressions {
 
 ////
 // Non-static unary expression template
@@ -30,6 +31,14 @@ struct UnaryExpressionTemplate
 {
 };
 
+template< typename T1,
+          template< typename > class Operation,
+          typename Parameter,
+          ExpressionVariableType T1Type >
+struct IsNumericExpression< UnaryExpressionTemplate< T1, Operation, Parameter, T1Type > >
+: std::true_type
+{};
+
 ////
 // Non-static binary expression template
 template< typename T1,
@@ -41,6 +50,15 @@ struct BinaryExpressionTemplate
 {
 };
 
+template< typename T1,
+          typename T2,
+          template< typename, typename > class Operation,
+          ExpressionVariableType T1Type,
+          ExpressionVariableType T2Type >
+struct IsNumericExpression< BinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > >
+: std::true_type
+{};
+
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
@@ -275,79 +293,79 @@ template< typename L1,
           typename R1,
           typename R2,
           template< typename, typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-   Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-   Containers::Expressions::Addition >
-operator + ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< L1, L2, LOperation >,
+   BinaryExpressionTemplate< R1, R2, ROperation >,
+   Addition >
+operator + ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-      Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-      Containers::Expressions::Addition >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< L1, L2, LOperation >,
+      BinaryExpressionTemplate< R1, R2, ROperation >,
+      Addition >( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-   typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-   Containers::Expressions::Addition >
-operator + ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< T1, T2, Operation >,
+   typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+   Addition >
+operator + ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+             const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-      typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-      Containers::Expressions::Addition >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< T1, T2, Operation >,
+      typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+      Addition >( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-   Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-   Containers::Expressions::Addition >
-operator + ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-             const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+const BinaryExpressionTemplate<
+   typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+   BinaryExpressionTemplate< T1, T2, Operation >,
+   Addition >
+operator + ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+             const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-      Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-      Containers::Expressions::Addition >( a, b );
+   return BinaryExpressionTemplate<
+      typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+      BinaryExpressionTemplate< T1, T2, Operation >,
+      Addition >( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-   typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-   Containers::Expressions::Addition >
-operator + ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< T1, Operation >,
+   typename UnaryExpressionTemplate< T1, Operation >::RealType,
+   Addition >
+operator + ( const UnaryExpressionTemplate< T1, Operation >& a,
+             const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-      typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-      Containers::Expressions::Addition >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< T1, Operation >,
+      typename UnaryExpressionTemplate< T1, Operation >::RealType,
+      Addition >( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-   Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-   Containers::Expressions::Addition >
-operator + ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a,
-             const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b )
+const BinaryExpressionTemplate<
+   typename UnaryExpressionTemplate< T1, Operation >::RealType,
+   UnaryExpressionTemplate< T1, Operation >,
+   Addition >
+operator + ( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
+             const UnaryExpressionTemplate< T1, Operation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-      Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-      Containers::Expressions::Addition >( a, b );
+   return BinaryExpressionTemplate<
+      typename UnaryExpressionTemplate< T1, Operation >::RealType,
+      UnaryExpressionTemplate< T1, Operation >,
+      Addition >( a, b );
 }
 
 template< typename L1,
@@ -355,17 +373,17 @@ template< typename L1,
           typename R1,
           typename R2,
           template< typename, typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-   Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-   Containers::Expressions::Addition >
-operator + ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< L1, LOperation >,
+   BinaryExpressionTemplate< R1, R2, ROperation >,
+   Addition >
+operator + ( const UnaryExpressionTemplate< L1, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-      Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-      Containers::Expressions::Addition >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< L1, LOperation >,
+      BinaryExpressionTemplate< R1, R2, ROperation >,
+      Addition >( a, b );
 }
 
 template< typename L1,
@@ -373,34 +391,34 @@ template< typename L1,
           template< typename, typename > class LOperation,
           typename R1,
           template< typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-   Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-   Containers::Expressions::Addition >
-operator + ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< L1, L2, LOperation >,
+   UnaryExpressionTemplate< R1, ROperation >,
+   Addition >
+operator + ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-      Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-      Containers::Expressions::Addition >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< L1, L2, LOperation >,
+      UnaryExpressionTemplate< R1, ROperation >,
+      Addition >( a, b );
 }
 
 template< typename L1,
           template< typename > class LOperation,
           typename R1,
           template< typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-   Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-   Containers::Expressions::Addition >
-operator + ( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a,
-             const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< L1, LOperation >,
+   UnaryExpressionTemplate< R1, ROperation >,
+   Addition >
+operator + ( const UnaryExpressionTemplate< L1,LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-      Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-      Containers::Expressions::Addition >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< L1, LOperation >,
+      UnaryExpressionTemplate< R1, ROperation >,
+      Addition >( a, b );
 }
 
 ////
@@ -411,79 +429,79 @@ template< typename L1,
           typename R1,
           typename R2,
           template< typename, typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-   Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-   Containers::Expressions::Subtraction >
-operator - ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< L1, L2, LOperation >,
+   BinaryExpressionTemplate< R1, R2, ROperation >,
+   Subtraction >
+operator - ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-      Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-      Containers::Expressions::Subtraction >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< L1, L2, LOperation >,
+      BinaryExpressionTemplate< R1, R2, ROperation >,
+      Subtraction >( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-   typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-   Containers::Expressions::Subtraction >
-operator - ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< T1, T2, Operation >,
+   typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+   Subtraction >
+operator - ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+             const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-      typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-      Containers::Expressions::Subtraction >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< T1, T2, Operation >,
+      typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+      Subtraction >( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-   Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-   Containers::Expressions::Subtraction >
-operator - ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-             const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+const BinaryExpressionTemplate<
+   typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+   BinaryExpressionTemplate< T1, T2, Operation >,
+   Subtraction >
+operator - ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+             const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-      Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-      Containers::Expressions::Subtraction >( a, b );
+   return BinaryExpressionTemplate<
+      typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+      BinaryExpressionTemplate< T1, T2, Operation >,
+      Subtraction >( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-   typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-   Containers::Expressions::Subtraction >
-operator - ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< T1, Operation >,
+   typename UnaryExpressionTemplate< T1, Operation >::RealType,
+   Subtraction >
+operator - ( const UnaryExpressionTemplate< T1, Operation >& a,
+             const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-      typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-      Containers::Expressions::Subtraction >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< T1, Operation >,
+      typename UnaryExpressionTemplate< T1, Operation >::RealType,
+      Subtraction >( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-   Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-   Containers::Expressions::Subtraction >
-operator - ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a,
-             const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b )
+const BinaryExpressionTemplate<
+   typename UnaryExpressionTemplate< T1, Operation >::RealType,
+   UnaryExpressionTemplate< T1, Operation >,
+   Subtraction >
+operator - ( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
+             const UnaryExpressionTemplate< T1, Operation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-      Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-      Containers::Expressions::Subtraction >( a, b );
+   return BinaryExpressionTemplate<
+      typename UnaryExpressionTemplate< T1, Operation >::RealType,
+      UnaryExpressionTemplate< T1, Operation >,
+      Subtraction >( a, b );
 }
 
 template< typename L1,
@@ -491,17 +509,17 @@ template< typename L1,
           typename R1,
           typename R2,
           template< typename, typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-   Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-   Containers::Expressions::Subtraction >
-operator - ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< L1, LOperation >,
+   BinaryExpressionTemplate< R1, R2, ROperation >,
+   Subtraction >
+operator - ( const UnaryExpressionTemplate< L1, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-      Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-      Containers::Expressions::Subtraction >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< L1, LOperation >,
+      BinaryExpressionTemplate< R1, R2, ROperation >,
+      Subtraction >( a, b );
 }
 
 template< typename L1,
@@ -509,34 +527,34 @@ template< typename L1,
           template< typename, typename > class LOperation,
           typename R1,
           template< typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-   Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-   Containers::Expressions::Subtraction >
-operator - ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< L1, L2, LOperation >,
+   UnaryExpressionTemplate< R1, ROperation >,
+   Subtraction >
+operator - ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-      Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-      Containers::Expressions::Subtraction >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< L1, L2, LOperation >,
+      UnaryExpressionTemplate< R1, ROperation >,
+      Subtraction >( a, b );
 }
 
 template< typename L1,
           template< typename > class LOperation,
           typename R1,
           template< typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-   Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-   Containers::Expressions::Subtraction >
-operator - ( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a,
-             const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< L1, LOperation >,
+   UnaryExpressionTemplate< R1, ROperation >,
+   Subtraction >
+operator - ( const UnaryExpressionTemplate< L1,LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-      Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-      Containers::Expressions::Subtraction >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< L1, LOperation >,
+      UnaryExpressionTemplate< R1, ROperation >,
+      Subtraction >( a, b );
 }
 
 ////
@@ -547,79 +565,79 @@ template< typename L1,
           typename R1,
           typename R2,
           template< typename, typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-   Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-   Containers::Expressions::Multiplication >
-operator * ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< L1, L2, LOperation >,
+   BinaryExpressionTemplate< R1, R2, ROperation >,
+   Multiplication >
+operator * ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-      Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-      Containers::Expressions::Multiplication >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< L1, L2, LOperation >,
+      BinaryExpressionTemplate< R1, R2, ROperation >,
+      Multiplication >( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-   typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-   Containers::Expressions::Multiplication >
-operator * ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< T1, T2, Operation >,
+   typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+   Multiplication >
+operator * ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+             const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-      typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-      Containers::Expressions::Multiplication >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< T1, T2, Operation >,
+      typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+      Multiplication >( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-   Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-   Containers::Expressions::Multiplication >
-operator * ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-             const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+const BinaryExpressionTemplate<
+   typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+   BinaryExpressionTemplate< T1, T2, Operation >,
+   Multiplication >
+operator * ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+             const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-      Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-      Containers::Expressions::Multiplication >( a, b );
+   return BinaryExpressionTemplate<
+      typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+      BinaryExpressionTemplate< T1, T2, Operation >,
+      Multiplication >( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-   typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-   Containers::Expressions::Multiplication >
-operator * ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< T1, Operation >,
+   typename UnaryExpressionTemplate< T1, Operation >::RealType,
+   Multiplication >
+operator * ( const UnaryExpressionTemplate< T1, Operation >& a,
+             const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-      typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-      Containers::Expressions::Multiplication >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< T1, Operation >,
+      typename UnaryExpressionTemplate< T1, Operation >::RealType,
+      Multiplication >( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-   Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-   Containers::Expressions::Multiplication >
-operator * ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a,
-             const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b )
+const BinaryExpressionTemplate<
+   typename UnaryExpressionTemplate< T1, Operation >::RealType,
+   UnaryExpressionTemplate< T1, Operation >,
+   Multiplication >
+operator * ( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
+             const UnaryExpressionTemplate< T1, Operation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-      Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-      Containers::Expressions::Multiplication >( a, b );
+   return BinaryExpressionTemplate<
+      typename UnaryExpressionTemplate< T1, Operation >::RealType,
+      UnaryExpressionTemplate< T1, Operation >,
+      Multiplication >( a, b );
 }
 
 template< typename L1,
@@ -627,17 +645,17 @@ template< typename L1,
           typename R1,
           typename R2,
           template< typename, typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-   Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-   Containers::Expressions::Multiplication >
-operator * ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< L1, LOperation >,
+   BinaryExpressionTemplate< R1, R2, ROperation >,
+   Multiplication >
+operator * ( const UnaryExpressionTemplate< L1, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-      Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-      Containers::Expressions::Multiplication >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< L1, LOperation >,
+      BinaryExpressionTemplate< R1, R2, ROperation >,
+      Multiplication >( a, b );
 }
 
 template< typename L1,
@@ -645,34 +663,34 @@ template< typename L1,
           template< typename, typename > class LOperation,
           typename R1,
           template< typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-   Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-   Containers::Expressions::Multiplication >
-operator * ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< L1, L2, LOperation >,
+   UnaryExpressionTemplate< R1, ROperation >,
+   Multiplication >
+operator * ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const UnaryExpressionTemplate< R1, ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-      Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-      Containers::Expressions::Multiplication >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< L1, L2, LOperation >,
+      UnaryExpressionTemplate< R1, ROperation >,
+      Multiplication >( a, b );
 }
 
 template< typename L1,
           template< typename > class LOperation,
           typename R1,
           template< typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-   Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-   Containers::Expressions::Multiplication >
-operator * ( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a,
-             const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< L1, LOperation >,
+   UnaryExpressionTemplate< R1, ROperation >,
+   Multiplication >
+operator * ( const UnaryExpressionTemplate< L1,LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-      Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-      Containers::Expressions::Multiplication >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< L1, LOperation >,
+      UnaryExpressionTemplate< R1, ROperation >,
+      Multiplication >( a, b );
 }
 
 ////
@@ -683,79 +701,79 @@ template< typename L1,
           typename R1,
           typename R2,
           template< typename, typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-   Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-   Containers::Expressions::Division >
-operator / ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< L1, L2, LOperation >,
+   BinaryExpressionTemplate< R1, R2, ROperation >,
+   Division >
+operator / ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-      Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-      Containers::Expressions::Division >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< L1, L2, LOperation >,
+      BinaryExpressionTemplate< R1, R2, ROperation >,
+      Division >( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-   typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-   Containers::Expressions::Division >
-operator / ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< T1, T2, Operation >,
+   typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+   Division >
+operator / ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+             const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-      typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-      Containers::Expressions::Division >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< T1, T2, Operation >,
+      typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+      Division >( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-   Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-   Containers::Expressions::Division >
-operator + ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-             const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+const BinaryExpressionTemplate<
+   typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+   BinaryExpressionTemplate< T1, T2, Operation >,
+   Division >
+operator + ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+             const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType,
-      Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >,
-      Containers::Expressions::Division >( a, b );
+   return BinaryExpressionTemplate<
+      typename BinaryExpressionTemplate< T1, T2, Operation >::RealType,
+      BinaryExpressionTemplate< T1, T2, Operation >,
+      Division >( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-   typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-   Containers::Expressions::Division >
-operator / ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< T1, Operation >,
+   typename UnaryExpressionTemplate< T1, Operation >::RealType,
+   Division >
+operator / ( const UnaryExpressionTemplate< T1, Operation >& a,
+             const typename UnaryExpressionTemplate< T1, Operation >::RealType& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-      typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-      Containers::Expressions::Division >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< T1, Operation >,
+      typename UnaryExpressionTemplate< T1, Operation >::RealType,
+      Division >( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-   Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-   Containers::Expressions::Division >
-operator / ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a,
-             const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b )
+const BinaryExpressionTemplate<
+   typename UnaryExpressionTemplate< T1, Operation >::RealType,
+   UnaryExpressionTemplate< T1, Operation >,
+   Division >
+operator / ( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a,
+             const UnaryExpressionTemplate< T1, Operation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType,
-      Containers::Expressions::UnaryExpressionTemplate< T1, Operation >,
-      Containers::Expressions::Division >( a, b );
+   return BinaryExpressionTemplate<
+      typename UnaryExpressionTemplate< T1, Operation >::RealType,
+      UnaryExpressionTemplate< T1, Operation >,
+      Division >( a, b );
 }
 
 template< typename L1,
@@ -763,17 +781,17 @@ template< typename L1,
           typename R1,
           typename R2,
           template< typename, typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-   Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-   Containers::Expressions::Division >
-operator / ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-             const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< L1, LOperation >,
+   BinaryExpressionTemplate< R1, R2, ROperation >,
+   Division >
+operator / ( const UnaryExpressionTemplate< L1, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-      Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >,
-      Containers::Expressions::Division >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< L1, LOperation >,
+      BinaryExpressionTemplate< R1, R2, ROperation >,
+      Division >( a, b );
 }
 
 template< typename L1,
@@ -781,34 +799,34 @@ template< typename L1,
           template< typename, typename > class LOperation,
           typename R1,
           template< typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-   Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-   Containers::Expressions::Division >
-operator / ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
+const BinaryExpressionTemplate<
+   BinaryExpressionTemplate< L1, L2, LOperation >,
+   UnaryExpressionTemplate< R1, ROperation >,
+   Division >
+operator / ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-      Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-      Containers::Expressions::Division >( a, b );
+   return BinaryExpressionTemplate<
+      BinaryExpressionTemplate< L1, L2, LOperation >,
+      UnaryExpressionTemplate< R1, ROperation >,
+      Division >( a, b );
 }
 
 template< typename L1,
           template< typename > class LOperation,
           typename R1,
           template< typename > class ROperation >
-const Containers::Expressions::BinaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-   Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-   Containers::Expressions::Division >
-operator / ( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a,
-             const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
+const BinaryExpressionTemplate<
+   UnaryExpressionTemplate< L1, LOperation >,
+   UnaryExpressionTemplate< R1, ROperation >,
+   Division >
+operator / ( const UnaryExpressionTemplate< L1,LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-      Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >,
-      Containers::Expressions::Division >( a, b );
+   return BinaryExpressionTemplate<
+      UnaryExpressionTemplate< L1, LOperation >,
+      UnaryExpressionTemplate< R1, ROperation >,
+      Division >( a, b );
 }
 
 ////
@@ -820,60 +838,60 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator == ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator == ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::EQ( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::EQ( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator == ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-              const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator == ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+              const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   using Right = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::EQ( a, b );
+   using Left = BinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Comparison< Left, Right >::EQ( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator == ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& a,
-              const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
+operator == ( const UnaryExpressionTemplate< T1, Operation, Parameter >& a,
+              const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   using Right = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::EQ( a, b );
+   using Left = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   return Comparison< Left, Right >::EQ( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator == ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-              const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+operator == ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+              const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   using Left = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   return Containers::Expressions::Comparison< Left, Right >::EQ( a, b );
+   using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = BinaryExpressionTemplate< T1, T2, Operation >;
+   return Comparison< Left, Right >::EQ( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator == ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
-              const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& b )
+operator == ( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
+              const UnaryExpressionTemplate< T1, Operation, Parameter >& b )
 {
-   using Left = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   return Containers::Expressions::Comparison< Left, Right >::EQ( a, b );
+   using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   using Right = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   return Comparison< Left, Right >::EQ( a, b );
 }
 
 template< typename L1,
@@ -883,12 +901,12 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator == ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
-              const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator == ( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
+              const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::EQ( a, b );
+   using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::EQ( a, b );
 }
 
 template< typename L1,
@@ -898,12 +916,12 @@ template< typename L1,
           template< typename > class ROperation,
           typename RParameter >
 bool
-operator == ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
+operator == ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >;
-   return Containers::Expressions::Comparison< Left, Right >::EQ( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >;
+   return Comparison< Left, Right >::EQ( a, b );
 }
 
 ////
@@ -915,24 +933,24 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator != ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-              const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator != ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+              const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::NE( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::NE( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator != ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-              const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator != ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+              const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   using Right = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::NE( a, b );
+   using Left = BinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Comparison< Left, Right >::NE( a, b );
 }
 
 template< typename L1,
@@ -942,48 +960,48 @@ template< typename L1,
           template< typename > class ROperation,
           typename RParameter >
 bool
-operator != ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
-              const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >& b )
+operator != ( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
+              const UnaryExpressionTemplate< R1, ROperation, RParameter >& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >;
-   return Containers::Expressions::Comparison< Left, Right >::NE( a, b );
+   using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >;
+   using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >;
+   return Comparison< Left, Right >::NE( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator != ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& a,
-              const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
+operator != ( const UnaryExpressionTemplate< T1, Operation, Parameter >& a,
+              const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   using Right = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::NE( a, b );
+   using Left = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   return Comparison< Left, Right >::NE( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator != ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-              const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+operator != ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+              const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   using Left = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   return Containers::Expressions::Comparison< Left, Right >::NE( a, b );
+   using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = BinaryExpressionTemplate< T1, T2, Operation >;
+   return Comparison< Left, Right >::NE( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator != ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
-              const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& b )
+operator != ( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
+              const UnaryExpressionTemplate< T1, Operation, Parameter >& b )
 {
-   using Left = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   return Containers::Expressions::Comparison< Left, Right >::NE( a, b );
+   using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   using Right = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   return Comparison< Left, Right >::NE( a, b );
 }
 
 template< typename L1,
@@ -993,12 +1011,12 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator != ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
-              const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator != ( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
+              const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::NE( a, b );
+   using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::NE( a, b );
 }
 
 template< typename L1,
@@ -1008,12 +1026,12 @@ template< typename L1,
           template< typename > class ROperation,
           typename RParameter >
 bool
-operator != ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-              const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
+operator != ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+              const UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >;
-   return Containers::Expressions::Comparison< Left, Right >::NE( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >;
+   return Comparison< Left, Right >::NE( a, b );
 }
 
 ////
@@ -1025,24 +1043,24 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator < ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator < ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::LT( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::LT( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator < ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator < ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+             const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   using Right = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::LT( a, b );
+   using Left = BinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Comparison< Left, Right >::LT( a, b );
 }
 
 template< typename L1,
@@ -1052,48 +1070,48 @@ template< typename L1,
           template< typename > class ROperation,
           typename RParameter >
 bool
-operator < ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
-              const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >& b )
+operator < ( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
+              const UnaryExpressionTemplate< R1, ROperation, RParameter >& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >;
-   return Containers::Expressions::Comparison< Left, Right >::LT( a, b );
+   using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >;
+   using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >;
+   return Comparison< Left, Right >::LT( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator < ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
+operator < ( const UnaryExpressionTemplate< T1, Operation, Parameter >& a,
+             const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   using Right = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::LT( a, b );
+   using Left = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   return Comparison< Left, Right >::LT( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator < ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-             const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+operator < ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+             const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   using Left = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   return Containers::Expressions::Comparison< Left, Right >::LT( a, b );
+   using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = BinaryExpressionTemplate< T1, T2, Operation >;
+   return Comparison< Left, Right >::LT( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator < ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
-             const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& b )
+operator < ( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
+             const UnaryExpressionTemplate< T1, Operation, Parameter >& b )
 {
-   using Left = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   return Containers::Expressions::Comparison< Left, Right >::LT( a, b );
+   using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   using Right = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   return Comparison< Left, Right >::LT( a, b );
 }
 
 template< typename L1,
@@ -1103,12 +1121,12 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator < ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator < ( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::LT( a, b );
+   using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::LT( a, b );
 }
 
 template< typename L1,
@@ -1118,12 +1136,12 @@ template< typename L1,
           template< typename > class ROperation,
           typename RParameter >
 bool
-operator < ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
+operator < ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >;
-   return Containers::Expressions::Comparison< Left, Right >::LT( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >;
+   return Comparison< Left, Right >::LT( a, b );
 }
 
 ////
@@ -1135,24 +1153,24 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator <= ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-              const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator <= ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+              const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::LE( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::LE( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator <= ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-              const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator <= ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+              const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   using Right = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::LE( a, b );
+   using Left = BinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Comparison< Left, Right >::LE( a, b );
 }
 
 template< typename L1,
@@ -1162,48 +1180,48 @@ template< typename L1,
           template< typename > class ROperation,
           typename RParameter >
 bool
-operator <= ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
-              const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >& b )
+operator <= ( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
+              const UnaryExpressionTemplate< R1, ROperation, RParameter >& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >;
-   return Containers::Expressions::Comparison< Left, Right >::LE( a, b );
+   using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >;
+   using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >;
+   return Comparison< Left, Right >::LE( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator <= ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& a,
-              const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
+operator <= ( const UnaryExpressionTemplate< T1, Operation, Parameter >& a,
+              const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   using Right = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::LE( a, b );
+   using Left = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   return Comparison< Left, Right >::LE( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator <= ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-              const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+operator <= ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+              const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   using Left = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   return Containers::Expressions::Comparison< Left, Right >::LE( a, b );
+   using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = BinaryExpressionTemplate< T1, T2, Operation >;
+   return Comparison< Left, Right >::LE( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator <= ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
-              const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& b )
+operator <= ( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
+              const UnaryExpressionTemplate< T1, Operation, Parameter >& b )
 {
-   using Left = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   return Containers::Expressions::Comparison< Left, Right >::LE( a, b );
+   using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   using Right = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   return Comparison< Left, Right >::LE( a, b );
 }
 
 template< typename L1,
@@ -1213,12 +1231,12 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator <= ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
-              const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator <= ( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
+              const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::LE( a, b );
+   using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::LE( a, b );
 }
 
 template< typename L1,
@@ -1228,12 +1246,12 @@ template< typename L1,
           template< typename > class ROperation,
           typename RParameter >
 bool
-operator <= ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
+operator <= ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >;
-   return Containers::Expressions::Comparison< Left, Right >::LE( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >;
+   return Comparison< Left, Right >::LE( a, b );
 }
 
 ////
@@ -1245,60 +1263,60 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator > ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator > ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::GT( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::GT( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator > ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator > ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+             const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   using Right = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::GT( a, b );
+   using Left = BinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Comparison< Left, Right >::GT( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator > ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
+operator > ( const UnaryExpressionTemplate< T1, Operation, Parameter >& a,
+             const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   using Right = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::GT( a, b );
+   using Left = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   return Comparison< Left, Right >::GT( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator > ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-             const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+operator > ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+             const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   using Left = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   return Containers::Expressions::Comparison< Left, Right >::GT( a, b );
+   using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = BinaryExpressionTemplate< T1, T2, Operation >;
+   return Comparison< Left, Right >::GT( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator > ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
-             const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& b )
+operator > ( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
+             const UnaryExpressionTemplate< T1, Operation, Parameter >& b )
 {
-   using Left = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   return Containers::Expressions::Comparison< Left, Right >::GT( a, b );
+   using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   using Right = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   return Comparison< Left, Right >::GT( a, b );
 }
 
 template< typename L1,
@@ -1308,12 +1326,12 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator > ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
-             const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator > ( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
+             const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::GT( a, b );
+   using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::GT( a, b );
 }
 
 template< typename L1,
@@ -1323,12 +1341,12 @@ template< typename L1,
           template< typename > class ROperation,
           typename RParameter >
 bool
-operator > ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
+operator > ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >;
-   return Containers::Expressions::Comparison< Left, Right >::GT( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >;
+   return Comparison< Left, Right >::GT( a, b );
 }
 
 ////
@@ -1340,60 +1358,60 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator >= ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-              const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator >= ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+              const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::GE( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::GE( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator >= ( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-              const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator >= ( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+              const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   using Right = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::GE( a, b );
+   using Left = BinaryExpressionTemplate< T1, T2, Operation >;
+   using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   return Comparison< Left, Right >::GE( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator >= ( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& a,
-              const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
+operator >= ( const UnaryExpressionTemplate< T1, Operation, Parameter >& a,
+              const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   using Right = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   return Containers::Expressions::Comparison< Left, Right >::GE( a, b );
+   using Left = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   return Comparison< Left, Right >::GE( a, b );
 }
 
 template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 bool
-operator >= ( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
-              const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b )
+operator >= ( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a,
+              const BinaryExpressionTemplate< T1, T2, Operation >& b )
 {
-   using Left = typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >;
-   return Containers::Expressions::Comparison< Left, Right >::GE( a, b );
+   using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType;
+   using Right = BinaryExpressionTemplate< T1, T2, Operation >;
+   return Comparison< Left, Right >::GE( a, b );
 }
 
 template< typename T1,
           template< typename > class Operation,
           typename Parameter >
 bool
-operator >= ( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
-              const Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >& b )
+operator >= ( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a,
+              const UnaryExpressionTemplate< T1, Operation, Parameter >& b )
 {
-   using Left = typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< T1, Operation, Parameter >;
-   return Containers::Expressions::Comparison< Left, Right >::GE( a, b );
+   using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType;
+   using Right = UnaryExpressionTemplate< T1, Operation, Parameter >;
+   return Comparison< Left, Right >::GE( a, b );
 }
 
 template< typename L1,
@@ -1403,12 +1421,12 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 bool
-operator >= ( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
-              const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator >= ( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a,
+              const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 {
-   using Left = Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, LParameter >;
-   using Right = Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >;
-   return Containers::Expressions::Comparison< Left, Right >::GE( a, b );
+   using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >;
+   using Right = BinaryExpressionTemplate< R1, R2, ROperation >;
+   return Comparison< Left, Right >::GE( a, b );
 }
 
 template< typename L1,
@@ -1418,12 +1436,12 @@ template< typename L1,
           template< typename > class ROperation,
           typename RParameter >
 bool
-operator >= ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-             const typename Containers::Expressions::UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
+operator >= ( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+             const UnaryExpressionTemplate< R1,ROperation, RParameter >& b )
 {
-   using Left = Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >;
-   using Right = Containers::Expressions::UnaryExpressionTemplate< R1, ROperation, RParameter >;
-   return Containers::Expressions::Comparison< Left, Right >::GE( a, b );
+   using Left = BinaryExpressionTemplate< L1, L2, LOperation >;
+   using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >;
+   return Comparison< Left, Right >::GE( a, b );
 }
 
 ////
@@ -1434,26 +1452,26 @@ operator >= ( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, L
 template< typename L1,
           typename L2,
           template< typename, typename > class LOperation >
-const Containers::Expressions::UnaryExpressionTemplate<
-   Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-   Containers::Expressions::Minus >
-operator -( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a )
+const UnaryExpressionTemplate<
+   BinaryExpressionTemplate< L1, L2, LOperation >,
+   Minus >
+operator -( const BinaryExpressionTemplate< L1, L2, LOperation >& a )
 {
-   return Containers::Expressions::UnaryExpressionTemplate<
-      Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >,
-      Containers::Expressions::Minus >( a );
+   return UnaryExpressionTemplate<
+      BinaryExpressionTemplate< L1, L2, LOperation >,
+      Minus >( a );
 }
 
 template< typename L1,
           template< typename > class LOperation >
-const Containers::Expressions::UnaryExpressionTemplate<
-   Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-   Containers::Expressions::Abs >
-operator -( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a )
+const UnaryExpressionTemplate<
+   UnaryExpressionTemplate< L1, LOperation >,
+   Abs >
+operator -( const UnaryExpressionTemplate< L1, LOperation >& a )
 {
-   return Containers::Expressions::UnaryExpressionTemplate<
-      Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >,
-      Containers::Expressions::Minus >( a );
+   return UnaryExpressionTemplate<
+      UnaryExpressionTemplate< L1, LOperation >,
+      Minus >( a );
 }
 
 ////
@@ -1465,8 +1483,8 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 auto
-operator,( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator,( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 -> decltype( TNL::sum( a * b ) )
 {
    return TNL::sum( a * b );
@@ -1476,8 +1494,8 @@ template< typename T1,
           typename T2,
           template< typename, typename > class Operation >
 auto
-operator,( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a,
-           const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
+operator,( const BinaryExpressionTemplate< T1, T2, Operation >& a,
+           const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b )
 -> decltype( TNL::sum( a * b ) )
 {
    return TNL::sum( a * b );
@@ -1489,8 +1507,8 @@ template< typename L1,
           typename R2,
           template< typename, typename > class ROperation >
 auto
-operator,( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a,
-           const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b )
+operator,( const UnaryExpressionTemplate< L1, LOperation >& a,
+           const BinaryExpressionTemplate< R1, R2, ROperation >& b )
 -> decltype( TNL::sum( a * b ) )
 {
    return TNL::sum( a * b );
@@ -1502,15 +1520,15 @@ template< typename L1,
           typename R1,
           template< typename > class ROperation >
 auto
-operator,( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a,
-           const typename Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b )
+operator,( const BinaryExpressionTemplate< L1, L2, LOperation >& a,
+           const UnaryExpressionTemplate< R1,ROperation >& b )
 -> decltype( TNL::sum( a * b ) )
 {
    return TNL::sum( a * b );
 }
 
-      }// namspace Expressions
-   } //namespace Containers
+} // namspace Expressions
+} //namespace Containers
 
 ////
 // All operations are supposed to be in namespace TNL
diff --git a/src/TNL/Containers/Expressions/ExpressionVariableType.h b/src/TNL/Containers/Expressions/ExpressionVariableType.h
index 1572de69120b0b8c0ca9b1e248089f9b79669e6a..0a9bbf0681c104284ebf54fd69cdd14e04a81df8 100644
--- a/src/TNL/Containers/Expressions/ExpressionVariableType.h
+++ b/src/TNL/Containers/Expressions/ExpressionVariableType.h
@@ -13,7 +13,7 @@
 #include <type_traits>
 
 namespace TNL {
-   namespace Containers {
+namespace Containers {
 
 template< int Size, typename Real >
 class StaticVector;
@@ -21,7 +21,7 @@ class StaticVector;
 template< typename Real, typename Device, typename Index >
 class VectorView;
 
-template< typename Real, typename Device, typename Index >
+template< typename Real, typename Device, typename Index, typename Allocator >
 class Vector;
 
 template< typename Real, typename Device, typename Index, typename Communicator >
@@ -36,7 +36,7 @@ class StaticArray;
 template< typename Real, typename Device, typename Index >
 class ArrayView;
 
-template< typename Real, typename Device, typename Index >
+template< typename Real, typename Device, typename Index, typename Allocator >
 class Array;
 
 template< typename Real, typename Device, typename Index, typename Communicator >
@@ -46,7 +46,7 @@ template< typename Real, typename Device, typename Index, typename Communicator
 class DistributedArray;
 
 
-      namespace Expressions {
+namespace Expressions {
 
 enum ExpressionVariableType { ArithmeticVariable, VectorVariable, VectorExpressionVariable, OtherVariable };
 
@@ -91,8 +91,9 @@ struct IsVectorType< VectorView< Real, Device, Index > >
 
 template< typename Real,
           typename Device,
-          typename Index >
-struct IsVectorType< Vector< Real, Device, Index > >
+          typename Index,
+          typename Allocator >
+struct IsVectorType< Vector< Real, Device, Index, Allocator > >
 {
    static constexpr bool value = true;
 };
@@ -123,8 +124,9 @@ struct IsVectorType< ArrayView< Real, Device, Index > >
 
 template< typename Real,
           typename Device,
-          typename Index >
-struct IsVectorType< Array< Real, Device, Index > >
+          typename Index,
+          typename Allocator >
+struct IsVectorType< Array< Real, Device, Index, Allocator > >
 {
    static constexpr bool value = true;
 };
@@ -184,6 +186,6 @@ struct OperandType< T, Devices::Host >
    using type = typename std::add_const< typename std::add_lvalue_reference< T >::type >::type;
 };
 
-      } //namespace Expressions
-   } //namespace Containers
+} //namespace Expressions
+} //namespace Containers
 } //namespace TNL
diff --git a/src/TNL/Containers/Expressions/IsNumericExpression.h b/src/TNL/Containers/Expressions/IsNumericExpression.h
new file mode 100644
index 0000000000000000000000000000000000000000..a710574692140f69b519f58b624a527a46c7695a
--- /dev/null
+++ b/src/TNL/Containers/Expressions/IsNumericExpression.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+                          IsNumericExpression.h  -  description
+                             -------------------
+    begin                : Jul 26, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#include <type_traits>
+
+namespace TNL {
+namespace Containers {
+namespace Expressions {
+
+template< typename T >
+struct IsNumericExpression : std::is_arithmetic< T >
+{};
+
+} //namespace Expressions
+} //namespace Containers
+} //namespace TNL
diff --git a/src/TNL/Containers/Vector.h b/src/TNL/Containers/Vector.h
index 0f9a5e8eaee8de4b165516aa452d14cab19f5e6a..e25098a58b26c2e6d6abaa735c4e43ef0bca8739 100644
--- a/src/TNL/Containers/Vector.h
+++ b/src/TNL/Containers/Vector.h
@@ -18,25 +18,35 @@ namespace TNL {
 namespace Containers {
 
 /**
- * \brief This class extends TNL::Array with algebraic operations.
+ * \brief \e Vector extends \ref Array with algebraic operations.
  *
- * \tparam Real is numeric type usually float or double.
- * \tparam Device is device where the array is going to be allocated - some of \ref Devices::Host and \ref Devices::Cuda.
- * \tparam Index is indexing type.
+ * The template parameters have the same meaning as in \ref Array, with \e Real
+ * corresponding to \e Array's \e Value parameter.
+ *
+ * \tparam Real   A numeric type for the vector values, e.g. \ref float or
+ *                \ref double.
+ * \tparam Device The device to be used for the execution of vector operations.
+ * \tparam Index  The indexing type.
+ * \tparam Allocator The type of the allocator used for the allocation and
+ *                   deallocation of memory used by the array. By default,
+ *                   an appropriate allocator for the specified \e Device
+ *                   is selected with \ref Allocators::Default.
  *
  * \par Example
  * \include VectorExample.cpp
  */
 template< typename Real = double,
           typename Device = Devices::Host,
-          typename Index = int >
+          typename Index = int,
+          typename Allocator = typename Allocators::Default< Device >::template Allocator< Real > >
 class Vector
-: public Array< Real, Device, Index >
+: public Array< Real, Device, Index, Allocator >
 {
 public:
    using RealType = Real;
    using DeviceType = Device;
    using IndexType = Index;
+   using AllocatorType = Allocator;
    using HostType = Vector< Real, TNL::Devices::Host, Index >;
    using CudaType = Vector< Real, TNL::Devices::Cuda, Index >;
    using ViewType = VectorView< Real, Device, Index >;
@@ -46,6 +56,8 @@ public:
    Vector() = default;
    //! \brief Default copy constructor.
    explicit Vector( const Vector& ) = default;
+   //! \brief Copy constructor with a specific allocator.
+   explicit Vector( const Vector& vector, const AllocatorType& allocator );
    //! \brief Default move constructor.
    Vector( Vector&& ) = default;
    //! \brief Default copy-assignment operator.
@@ -54,8 +66,8 @@ public:
    Vector& operator=( Vector&& ) = default;
 
    //! Constructors and assignment operators are inherited from the class \ref Array.
-   using Array< Real, Device, Index >::Array;
-   using Array< Real, Device, Index >::operator=;
+   using Array< Real, Device, Index, Allocator >::Array;
+   using Array< Real, Device, Index, Allocator >::operator=;
 
    /** \brief Returns type of vector Real value, Device type and the type of Index. */
    static String getType();
@@ -66,9 +78,9 @@ public:
    /**
     * \brief Returns a modifiable view of the vector.
     *
-    * If \e begin or \e end is set to a non-zero value, a view for the
-    * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-    * vector is returned.
+    * By default, a view for the whole vector is returned. If \e begin or
+    * \e end is set to a non-zero value, a view only for the sub-interval
+    * `[begin, end)` is returned.
     *
     * \param begin The beginning of the vector sub-interval. It is 0 by
     *              default.
@@ -80,9 +92,9 @@ public:
    /**
     * \brief Returns a non-modifiable view of the vector.
     *
-    * If \e begin or \e end is set to a non-zero value, a view for the
-    * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-    * vector is returned.
+    * By default, a view for the whole vector is returned. If \e begin or
+    * \e end is set to a non-zero value, a view only for the sub-interval
+    * `[begin, end)` is returned.
     *
     * \param begin The beginning of the vector sub-interval. It is 0 by
     *              default.
@@ -94,9 +106,9 @@ public:
    /**
     * \brief Returns a non-modifiable view of the vector.
     *
-    * If \e begin or \e end is set to a non-zero value, a view for the
-    * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-    * vector is returned.
+    * By default, a view for the whole vector is returned. If \e begin or
+    * \e end is set to a non-zero value, a view only for the sub-interval
+    * `[begin, end)` is returned.
     *
     * \param begin The beginning of the vector sub-interval. It is 0 by
     *              default.
@@ -134,8 +146,8 @@ public:
                     const RealType& value,
                     const Scalar thisElementMultiplicator );
 
-   template< typename Real_, typename Device_, typename Index_ >
-   Vector& operator=( const Vector< Real_, Device_, Index_ >& v );
+   template< typename Real_, typename Device_, typename Index_, typename Allocator_ >
+   Vector& operator=( const Vector< Real_, Device_, Index_, Allocator_ >& v );
 
    template< typename Real_, typename Device_, typename Index_ >
    Vector& operator=( const VectorView< Real_, Device_, Index_ >& v );
diff --git a/src/TNL/Containers/Vector.hpp b/src/TNL/Containers/Vector.hpp
index fb859610a4e0ee9e7d650c2bdb2e356ee4900c0c..c692e0921882aa6344dc1e930f3fa64798f164ea 100644
--- a/src/TNL/Containers/Vector.hpp
+++ b/src/TNL/Containers/Vector.hpp
@@ -18,9 +18,21 @@ namespace Containers {
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
+Vector< Real, Device, Index, Allocator >::
+Vector( const Vector& vector,
+        const AllocatorType& allocator )
+: Array< Real, Device, Index, Allocator >( vector, allocator )
+{
+}
+
+template< typename Real,
+          typename Device,
+          typename Index,
+          typename Allocator >
 String
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 getType()
 {
    return String( "Containers::Vector< " ) +
@@ -31,9 +43,10 @@ getType()
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 String
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 getTypeVirtual() const
 {
    return this->getType();
@@ -41,9 +54,10 @@ getTypeVirtual() const
 
 template< typename Real,
           typename Device,
-          typename Index >
-typename Vector< Real, Device, Index >::ViewType
-Vector< Real, Device, Index >::
+          typename Index,
+          typename Allocator >
+typename Vector< Real, Device, Index, Allocator >::ViewType
+Vector< Real, Device, Index, Allocator >::
 getView( IndexType begin, IndexType end )
 {
    if( end == 0 )
@@ -53,9 +67,10 @@ getView( IndexType begin, IndexType end )
 
 template< typename Real,
           typename Device,
-          typename Index >
-typename Vector< Real, Device, Index >::ConstViewType
-Vector< Real, Device, Index >::
+          typename Index,
+          typename Allocator >
+typename Vector< Real, Device, Index, Allocator >::ConstViewType
+Vector< Real, Device, Index, Allocator >::
 getView( IndexType begin, IndexType end ) const
 {
    if( end == 0 )
@@ -65,9 +80,10 @@ getView( IndexType begin, IndexType end ) const
 
 template< typename Real,
           typename Device,
-          typename Index >
-typename Vector< Real, Device, Index >::ConstViewType
-Vector< Real, Device, Index >::
+          typename Index,
+          typename Allocator >
+typename Vector< Real, Device, Index, Allocator >::ConstViewType
+Vector< Real, Device, Index, Allocator >::
 getConstView( IndexType begin, IndexType end ) const
 {
    if( end == 0 )
@@ -77,8 +93,9 @@ getConstView( IndexType begin, IndexType end ) const
 
 template< typename Real,
           typename Device,
-          typename Index >
-Vector< Real, Device, Index >::
+          typename Index,
+          typename Allocator >
+Vector< Real, Device, Index, Allocator >::
 operator ViewType()
 {
    return getView();
@@ -86,8 +103,9 @@ operator ViewType()
 
 template< typename Real,
           typename Device,
-          typename Index >
-Vector< Real, Device, Index >::
+          typename Index,
+          typename Allocator >
+Vector< Real, Device, Index, Allocator >::
 operator ConstViewType() const
 {
    return getConstView();
@@ -95,9 +113,10 @@ operator ConstViewType() const
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
 void
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 addElement( const IndexType i,
             const RealType& value )
 {
@@ -106,10 +125,11 @@ addElement( const IndexType i,
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename Scalar >
 void
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 addElement( const IndexType i,
             const RealType& value,
             const Scalar thisElementMultiplicator )
@@ -119,10 +139,12 @@ addElement( const IndexType i,
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename VectorExpression >
-Vector< Real, Device, Index >&
-Vector< Real, Device, Index >::operator=( const VectorExpression& expression )
+Vector< Real, Device, Index, Allocator >&
+Vector< Real, Device, Index, Allocator >::
+operator=( const VectorExpression& expression )
 {
    Algorithms::VectorAssignment< Vector, VectorExpression >::assign( *this, expression );
    return *this;
@@ -130,32 +152,37 @@ Vector< Real, Device, Index >::operator=( const VectorExpression& expression )
 
 template< typename Real,
           typename Device,
-          typename Index >
-   template< typename Real_, typename Device_, typename Index_ >
-Vector< Real, Device, Index >&
-Vector< Real, Device, Index >::operator=( const Vector< Real_, Device_, Index_ >& vector )
+          typename Index,
+          typename Allocator >
+   template< typename Real_, typename Device_, typename Index_, typename Allocator_ >
+Vector< Real, Device, Index, Allocator >&
+Vector< Real, Device, Index, Allocator >::
+operator=( const Vector< Real_, Device_, Index_, Allocator_ >& vector )
 {
-   Array< Real, Device, Index >::operator=( vector );
+   Array< Real, Device, Index, Allocator >::operator=( vector );
    return *this;
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename Real_, typename Device_, typename Index_ >
-Vector< Real, Device, Index >&
-Vector< Real, Device, Index >::operator=( const VectorView< Real_, Device_, Index_ >& view )
+Vector< Real, Device, Index, Allocator >&
+Vector< Real, Device, Index, Allocator >::
+operator=( const VectorView< Real_, Device_, Index_ >& view )
 {
-   Array< Real, Device, Index >::operator=( view );
+   Array< Real, Device, Index, Allocator >::operator=( view );
    return *this;
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename VectorExpression >
-Vector< Real, Device, Index >&
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >&
+Vector< Real, Device, Index, Allocator >::
 operator-=( const VectorExpression& expression )
 {
    Algorithms::VectorSubtraction< Vector, VectorExpression >::subtraction( *this, expression );
@@ -164,10 +191,11 @@ operator-=( const VectorExpression& expression )
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename VectorExpression >
-Vector< Real, Device, Index >&
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >&
+Vector< Real, Device, Index, Allocator >::
 operator+=( const VectorExpression& expression )
 {
    Algorithms::VectorAddition< Vector, VectorExpression >::addition( *this, expression );
@@ -176,10 +204,11 @@ operator+=( const VectorExpression& expression )
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename VectorExpression >
-Vector< Real, Device, Index >&
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >&
+Vector< Real, Device, Index, Allocator >::
 operator*=( const VectorExpression& expression )
 {
    Algorithms::VectorMultiplication< Vector, VectorExpression >::multiplication( *this, expression );
@@ -188,10 +217,11 @@ operator*=( const VectorExpression& expression )
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename VectorExpression >
-Vector< Real, Device, Index >&
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >&
+Vector< Real, Device, Index, Allocator >::
 operator/=( const VectorExpression& expression )
 {
    Algorithms::VectorDivision< Vector, VectorExpression >::division( *this, expression );
@@ -200,28 +230,31 @@ operator/=( const VectorExpression& expression )
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename ResultType >
-ResultType Vector< Real, Device, Index >::sum() const
+ResultType Vector< Real, Device, Index, Allocator >::sum() const
 {
    return Algorithms::VectorOperations< Device >::template getVectorSum< Vector, ResultType >( *this );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename VectorT >
-Real Vector< Real, Device, Index >::scalarProduct( const VectorT& v ) const
+Real Vector< Real, Device, Index, Allocator >::scalarProduct( const VectorT& v ) const
 {
    return dot( this->getView(), v.getView() );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename VectorT, typename Scalar1, typename Scalar2 >
 void
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 addVector( const VectorT& x,
            const Scalar1 multiplicator,
            const Scalar2 thisMultiplicator )
@@ -231,10 +264,11 @@ addVector( const VectorT& x,
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2, typename Scalar3 >
 void
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 addVectors( const Vector1& v1,
             const Scalar1 multiplicator1,
             const Vector2& v2,
@@ -246,10 +280,11 @@ addVectors( const Vector1& v1,
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< Algorithms::PrefixSumType Type >
 void
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 prefixSum( IndexType begin, IndexType end )
 {
    if( end == 0 )
@@ -259,11 +294,12 @@ prefixSum( IndexType begin, IndexType end )
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< Algorithms::PrefixSumType Type,
              typename FlagsArray >
 void
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 segmentedPrefixSum( FlagsArray& flags, IndexType begin, IndexType end )
 {
    if( end == 0 )
@@ -273,11 +309,12 @@ segmentedPrefixSum( FlagsArray& flags, IndexType begin, IndexType end )
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< Algorithms::PrefixSumType Type,
              typename VectorExpression >
 void
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 prefixSum( const VectorExpression& expression, IndexType begin, IndexType end )
 {
    throw Exceptions::NotImplementedError( "Prefix sum with vector expressions is not implemented." );
@@ -285,12 +322,13 @@ prefixSum( const VectorExpression& expression, IndexType begin, IndexType end )
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index,
+          typename Allocator >
    template< Algorithms::PrefixSumType Type,
              typename VectorExpression,
              typename FlagsArray >
 void
-Vector< Real, Device, Index >::
+Vector< Real, Device, Index, Allocator >::
 segmentedPrefixSum( const VectorExpression& expression, FlagsArray& flags, IndexType begin, IndexType end )
 {
    throw Exceptions::NotImplementedError( "Prefix sum with vector expressions is not implemented." );
diff --git a/src/TNL/Containers/VectorExpressions.h b/src/TNL/Containers/VectorExpressions.h
index 749bc557a0179a0bf08377cad658a9af67d6879d..b0fce83b922fe848aded9fc3d38beea82021f450 100644
--- a/src/TNL/Containers/VectorExpressions.h
+++ b/src/TNL/Containers/VectorExpressions.h
@@ -16,749 +16,785 @@
 #include <TNL/Containers/Expressions/Comparison.h>
 #include <TNL/Containers/Expressions/VerticalOperations.h>
 
-#include "VectorView.h"
 #include "Vector.h"
 
 namespace TNL {
-   namespace Containers {
+namespace Containers {
 
 ////
 // Addition
-template< typename Real, typename Device, typename Index, typename ET >
-const Expressions::BinaryExpressionTemplate< 
-   typename VectorView< Real, Device, Index >::ConstViewType,
-   ET,
-   Expressions::Addition >
-operator+( const Vector< Real, Device, Index >& a, const ET& b )
+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 >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Addition >( a.getView(), 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 >
-const Expressions::BinaryExpressionTemplate< 
-   ET,
-   typename VectorView< Real, Device, Index >::ConstViewType,
-   Expressions::Addition >
-operator+( const ET& a, const Vector< Real, Device, Index >& 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 >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Addition >( a, b.getView() );
+   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 >
-const Expressions::BinaryExpressionTemplate< 
-   typename Vector< Real1, Device, Index >::ConstViewType,
-   typename VectorView< Real2, Device, Index >::ConstViewType,
-   Expressions::Addition >
-operator+( const Vector< Real1, Device, Index >& a, const Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getView(), b.getView() );
+   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 ET >
-const Expressions::BinaryExpressionTemplate< typename Vector< Real, Device, Index >::ConstViewType, ET, Expressions::Subtraction >
-operator-( const Vector< Real, Device, Index >& a, const ET& b )
+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 >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Subtraction >( a.getView(), 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 >
-const Expressions::BinaryExpressionTemplate< ET, typename Vector< Real, Device, Index >::ConstViewType, Expressions::Subtraction >
-operator-( const ET& a, const Vector< Real, Device, Index >& 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 >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Subtraction >( a, b.getView() );
+   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 >
-const Expressions::BinaryExpressionTemplate< 
-   typename Vector< Real1, Device, Index >::ConstViewType,
-   typename VectorView< Real2, Device, Index >::ConstViewType,
-   Expressions::Subtraction >
-operator-( const Vector< Real1, Device, Index >& a, const Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getView(), b.getView() );
+   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 ET >
-const Expressions::BinaryExpressionTemplate< typename Vector< Real, Device, Index >::ConstViewType, ET, Expressions::Multiplication >
-operator*( const Vector< Real, Device, Index >& a, const ET& b )
+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 >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Multiplication >( a.getView(), 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 >
-const Expressions::BinaryExpressionTemplate< ET, typename Vector< Real, Device, Index >::ConstViewType, Expressions::Multiplication >
-operator*( const ET& a, const Vector< Real, Device, Index >& 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 >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Multiplication >( a, b.getView() );
+   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 >
-const Expressions::BinaryExpressionTemplate< typename Vector< Real1, Device, Index >::ConstViewType, typename Vector< Real2, Device, Index >::ConstViewType, Expressions::Multiplication >
-operator*( const Vector< Real1, Device, Index >& a, const Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getView(), b.getView() );
+   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 ET >
-const Expressions::BinaryExpressionTemplate< typename Vector< Real, Device, Index >::ConstViewType, ET, Expressions::Division >
-operator/( const Vector< Real, Device, Index >& a, const ET& b )
+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 >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Division >( a.getView(), 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 >
-const Expressions::BinaryExpressionTemplate< ET, typename Vector< Real, Device, Index >::ConstViewType, Expressions::Division >
-operator/( const ET& a, const Vector< Real, Device, Index >& 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 >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Division >( a, b.getView() );
+   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 >
-const Expressions::BinaryExpressionTemplate< typename Vector< Real1, Device, Index >::ConstViewType, typename Vector< Real2, Device, Index >::ConstViewType, Expressions::Division >
-operator/( const Vector< Real1, Device, Index >& a, const Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
-   using ConstView2 = typename Vector< Real2, Device, Index >::ConstViewType;
-   return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getView(), b.getView() );
+   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 ET >
-bool operator==( const Vector< Real, Device, Index >& a, const ET& b )
+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.getView(), b );
+   return Expressions::Comparison< ConstView, ET >::EQ( a.getConstView(), b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator==( const ET& a, const Vector< Real, Device, Index >& 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.getView() );
+   return Expressions::Comparison< ET, ConstView >::EQ( a, b.getConstView() );
 }
 
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index >
-bool operator==( const Vector< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index >& b )
+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 )
 {
    if( a.getSize() != b.getSize() )
       return false;
    if( a.getSize() == 0 )
       return true;
    return Algorithms::ArrayOperations< Device1, Device2 >::
-            compareMemory( a.getData(),
-                           b.getData(),
-                           a.getSize() );
+            compare( a.getData(),
+                     b.getData(),
+                     a.getSize() );
 }
 
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index >
-bool operator==( const VectorView< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index >& 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 )
 {
    if( a.getSize() != b.getSize() )
       return false;
    if( a.getSize() == 0 )
       return true;
    return Algorithms::ArrayOperations< Device1, Device2 >::
-            compareMemory( a.getData(),
-                           b.getData(),
-                           a.getSize() );
+            compare( a.getData(),
+                     b.getData(),
+                     a.getSize() );
 }
 
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index >
-bool operator==( const Vector< Real1, Device1, Index >& a, const VectorView< Real2, Device2, Index >& 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 )
 {
    if( a.getSize() != b.getSize() )
       return false;
    if( a.getSize() == 0 )
       return true;
    return Algorithms::ArrayOperations< Device1, Device2 >::
-            compareMemory( a.getData(),
-                           b.getData(),
-                           a.getSize() );
+            compare( a.getData(),
+                     b.getData(),
+                     a.getSize() );
 }
 
 ////
 // Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename ET >
-bool operator!=( const Vector< Real, Device, Index >& a, const ET& b )
+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.getView(), b );
+   return Expressions::Comparison< ConstView, ET >::NE( a.getConstView(), b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator!=( const ET& a, const Vector< Real, Device, Index >& 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.getView() );
+   return Expressions::Comparison< ET, ConstView >::NE( a, b.getConstView() );
 }
 
-template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index >
-bool operator!=( const Vector< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index >& b )
+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 )
 {
    if( a.getSize() != b.getSize() )
       return false;
    if( a.getSize() == 0 )
       return true;
    return !Algorithms::ArrayOperations< Device1, Device2 >::
-            compareMemory( a.getData(),
-                           b.getData(),
-                           a.getSize() );
+            compare( a.getData(),
+                     b.getData(),
+                     a.getSize() );
 }
 
 ////
 // Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename ET >
-bool operator<( const Vector< Real, Device, Index >& a, const ET& b )
+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.getView(), b );
+   return Expressions::Comparison< ConstView, ET >::LT( a.getConstView(), b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator<( const ET& a, const Vector< Real, Device, Index >& 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.getView() );
+   return Expressions::Comparison< ET, ConstView >::LT( a, b.getConstView() );
 }
 
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool operator<( const Vector< Real1, Device, Index >& a, const Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
+   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
    using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getView(), b.getView() );
+   return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() );
 }
 
 ////
 // Comparison operations - operator <=
-template< typename Real, typename Device, typename Index, typename ET >
-bool operator<=( const Vector< Real, Device, Index >& a, const ET& b )
+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.getView(), b );
+   return Expressions::Comparison< ConstView, ET >::LE( a.getConstView(), b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator<=( const ET& a, const Vector< Real, Device, Index >& 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.getView() );
+   return Expressions::Comparison< ET, ConstView >::LE( a, b.getConstView() );
 }
 
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool operator<=( const Vector< Real1, Device, Index >& a, const Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
+   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
    using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getView(), b.getView() );
+   return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() );
 }
 
 ////
 // Comparison operations - operator >
-template< typename Real, typename Device, typename Index, typename ET >
-bool operator>( const Vector< Real, Device, Index >& a, const ET& b )
+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.getView(), b );
+   return Expressions::Comparison< ConstView, ET >::GT( a.getConstView(), b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator>( const ET& a, const Vector< Real, Device, Index >& 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.getView() );
+   return Expressions::Comparison< ET, ConstView >::GT( a, b.getConstView() );
 }
 
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool operator>( const Vector< Real1, Device, Index >& a, const Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
+   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
    using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getView(), b.getView() );
+   return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() );
 }
 
 ////
 // Comparison operations - operator >=
-template< typename Real, typename Device, typename Index, typename ET >
-bool operator>=( const Vector< Real, Device, Index >& a, const ET& b )
+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.getView(), b );
+   return Expressions::Comparison< ConstView, ET >::GE( a.getConstView(), b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator>=( const ET& a, const Vector< Real, Device, Index >& 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.getView() );
+   return Expressions::Comparison< ET, ConstView >::GE( a, b.getConstView() );
 }
 
-template< typename Real1, typename Real2, typename Device, typename Index >
-bool operator>=( const Vector< Real1, Device, Index >& a, const Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
+   using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType;
    using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType;
-   return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getView(), b.getView() );
+   return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() );
 }
 
 ////
 // Minus
-template< typename Real, typename Device, typename Index >
-const Expressions::UnaryExpressionTemplate< typename Vector< Real, Device, Index >::ConstViewType, Expressions::Minus >
-operator-( const Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Expressions::UnaryExpressionTemplate< ConstView, Expressions::Minus >( a.getView() );
+   using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Expressions::UnaryExpressionTemplate< ConstView, Expressions::Minus >( a.getConstView() );
 }
 
 ////
 // Scalar product
-template< typename Real, typename Device, typename Index, typename ET >
-Real operator,( const Vector< Real, Device, Index >& a, const ET& b )
+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 TNL::sum( a.getView() * b );
+   return TNL::sum( a.getConstView() * b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-Real operator,( const ET& a, const Vector< Real, Device, Index >& 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 TNL::sum( a * b.getView() );
+   return TNL::sum( a * b.getConstView() );
 }
 
-template< typename Real1, typename Real2, typename Device, typename Index >
-//auto 
-// TODO: auto+decltype does not work with NVCC 10.1
-Real1 operator,( const Vector< Real1, Device, Index >& a, const Vector< Real2, Device, Index >& b )
-//->decltype( TNL::sum( a.getView() * b.getView() ) )
+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 TNL::sum( a.getView() * b.getView() );
+   return TNL::sum( a.getConstView() * b.getConstView() );
 }
 
 } //namespace Containers
 
 ////
-// All operations are supposed to be in namespace TNL
+// All functions are supposed to be in namespace TNL
 
 ////
 // Min
-template< typename Real, typename Device, typename Index, typename ET >
-const Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, ET, Containers::Expressions::Min >
-min( const Containers::Vector< Real, Device, Index >& a, const ET& b )
+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 >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Min >( a.getView(), 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 >
-const Containers::Expressions::BinaryExpressionTemplate< ET, typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Min >
-min( const ET& a, const Containers::Vector< Real, Device, Index >& 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 >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Min >( a, b.getView() );
+   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 >
-const Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real1, Device, Index >::ConstViewType, typename Containers::Vector< Real2, Device, Index >::ConstViewType, Containers::Expressions::Min >
-min( const Containers::Vector< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getView(), b.getView() );
+   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 ET >
-const Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, ET, Containers::Expressions::Max >
-max( const Containers::Vector< Real, Device, Index >& a, const ET& b )
+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 >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Max >( a.getView(), 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 >
-const Containers::Expressions::BinaryExpressionTemplate< ET, typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Max >
-max( const ET& a, const Containers::Vector< Real, Device, Index >& 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 >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Max >( a, b.getView() );
+   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 >
-const Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real1, Device, Index >::ConstViewType, typename Containers::Vector< Real2, Device, Index >::ConstViewType, Containers::Expressions::Max >
-max( const Containers::Vector< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index >& b )
+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 >::ConstViewType;
-   using ConstView2 = typename Containers::Vector< Real2, Device, Index >::ConstViewType;
-   return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getView(), b.getView() );
+   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() );
 }
 
 
 ////
 // Abs
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Abs >
-abs( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Abs >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Abs >( a.getConstView() );
 }
 
 ////
 // Sine
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Sin >
-sin( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sin >( a.getView() );
+   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 >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Cos >
-cos( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cos >( a.getView() );
+   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 >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Tan >
-tan( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tan >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tan >( a.getConstView() );
 }
 
 ////
 // Sqrt
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Sqrt >
-sqrt( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sqrt >( a.getView() );
+   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 >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Cbrt >
-cbrt( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cbrt >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cbrt >( a.getConstView() );
 }
 
 ////
 // Power
-template< typename Real, typename Device, typename Index, typename ExpType >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Pow, ExpType >
-pow( const Containers::Vector< Real, Device, Index >& a, const ExpType& exp )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Pow, ExpType >( a.getView(), exp );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Pow, ExpType >( a.getConstView(), exp );
 }
 
 ////
 // Floor
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Floor >
-floor( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Floor >( a.getView() );
+   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 >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Ceil >
-ceil( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Ceil >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Ceil >( a.getConstView() );
 }
 
 ////
 // Acos
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Acos >
-acos( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Acos >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Acos >( a.getConstView() );
 }
 
 ////
 // Asin
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Asin >
-asin( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Asin >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Asin >( a.getConstView() );
 }
 
 ////
 // Atan
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Atan >
-atan( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Atan >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Atan >( a.getConstView() );
 }
 
 ////
 // Cosh
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Cosh >
-cosh( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cosh >( a.getView() );
+   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 >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Tanh >
-tanh( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tanh >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tanh >( a.getConstView() );
 }
 
 ////
 // Log
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Log >
-log( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log >( a.getView() );
+   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 >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Log10 >
-log10( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log10 >( a.getView() );
+   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 >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Log2 >
-log2( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log2 >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log2 >( a.getConstView() );
 }
 
 ////
 // Exp
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Exp >
-exp( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Exp >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Exp >( a.getConstView() );
 }
 
 ////
 // Sign
-template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Sign >
-sign( const Containers::Vector< Real, Device, Index >& a )
+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 >::ConstViewType;
-   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sign >( a.getView() );
+   using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType;
+   return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sign >( a.getConstView() );
 }
 
 ////
 // Vertical operations - min
 template< typename Real,
           typename Device,
-          typename Index >
-typename Containers::VectorView< Real, Device, Index >::RealType
-min( const Containers::Vector< Real, Device, Index >& a )
+          typename Index, typename Allocator >
+Real
+min( const Containers::Vector< Real, Device, Index, Allocator >& a )
 {
-   return Containers::Expressions::ExpressionMin( a.getView() );
+   return Containers::Expressions::ExpressionMin( a.getConstView() );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
-typename Containers::VectorView< Real, Device, Index >::RealType
-argMin( const Containers::Vector< Real, Device, Index >& a, Index& arg )
+          typename Index, typename Allocator >
+Real
+argMin( const Containers::Vector< Real, Device, Index, Allocator >& a, Index& arg )
 {
-   return Containers::Expressions::ExpressionArgMin( a.getView(), arg );
+   return Containers::Expressions::ExpressionArgMin( a.getConstView(), arg );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
-typename Containers::VectorView< Real, Device, Index >::RealType
-max( const Containers::Vector< Real, Device, Index >& a )
+          typename Index, typename Allocator >
+Real
+max( const Containers::Vector< Real, Device, Index, Allocator >& a )
 {
-   return Containers::Expressions::ExpressionMax( a.getView() );
+   return Containers::Expressions::ExpressionMax( a.getConstView() );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
-typename Containers::VectorView< Real, Device, Index >::RealType
-argMax( const Containers::Vector< Real, Device, Index >& a, Index& arg )
+          typename Index, typename Allocator >
+Real
+argMax( const Containers::Vector< Real, Device, Index, Allocator >& a, Index& arg )
 {
-   return Containers::Expressions::ExpressionArgMax( a.getView(), arg );
+   return Containers::Expressions::ExpressionArgMax( a.getConstView(), arg );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index, typename Allocator >
 auto
-sum( const Containers::Vector< Real, Device, Index >& a ) -> decltype( Containers::Expressions::ExpressionSum( a.getView() ) )
+sum( const Containers::Vector< Real, Device, Index, Allocator >& a )
 {
-   return Containers::Expressions::ExpressionSum( a.getView() );
+   return Containers::Expressions::ExpressionSum( a.getConstView() );
 }
 
 template< typename Real,
           typename Device,
-          typename Index,
+          typename Index, typename Allocator,
           typename Real2 >
 auto
-lpNorm( const Containers::Vector< Real, Device, Index >& a, const Real2& p ) -> decltype( Containers::Expressions::ExpressionLpNorm( a.getView(), p ) )
+lpNorm( const Containers::Vector< Real, Device, Index, Allocator >& a, const Real2& p )
+-> decltype( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ) )
 {
    if( p == 1.0 )
-      return Containers::Expressions::ExpressionLpNorm( a.getView(), p );
+      return Containers::Expressions::ExpressionLpNorm( a.getConstView(), p );
    if( p == 2.0 )
-      return TNL::sqrt( Containers::Expressions::ExpressionLpNorm( a.getView(), p ) );
-   return TNL::pow( Containers::Expressions::ExpressionLpNorm( a.getView(), p ), 1.0 / p );
+      return TNL::sqrt( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ) );
+   return TNL::pow( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ), (Real2) (1.0 / p) );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index, typename Allocator >
 auto
-product( const Containers::Vector< Real, Device, Index >& a ) -> decltype( Containers::Expressions::ExpressionProduct( a.getView() ) )
+product( const Containers::Vector< Real, Device, Index, Allocator >& a )
 {
-   return Containers::Expressions::ExpressionProduct( a.getView() );
+   return Containers::Expressions::ExpressionProduct( a.getConstView() );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
-bool
-logicalOr( const Containers::Vector< Real, Device, Index >& a )
+          typename Index, typename Allocator >
+auto
+logicalOr( const Containers::Vector< Real, Device, Index, Allocator >& a )
 {
-   return Containers::Expressions::ExpressionLogicalOr( a.getView() );
+   return Containers::Expressions::ExpressionLogicalOr( a.getConstView() );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index, typename Allocator >
 auto
-binaryOr( const Containers::Vector< Real, Device, Index >& a ) -> decltype( Containers::Expressions::ExpressionBinaryOr( a.getView() ) )
+binaryOr( const Containers::Vector< Real, Device, Index, Allocator >& a )
 {
-   return Containers::Expressions::ExpressionBinaryOr( a.getView() );
+   return Containers::Expressions::ExpressionBinaryOr( a.getConstView() );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
-bool
-logicalAnd( const Containers::Vector< Real, Device, Index >& a )
+          typename Index, typename Allocator >
+auto
+logicalAnd( const Containers::Vector< Real, Device, Index, Allocator >& a )
 {
-   return Containers::Expressions::ExpressionLogicalAnd( a.getView() );
+   return Containers::Expressions::ExpressionLogicalAnd( a.getConstView() );
 }
 
 template< typename Real,
           typename Device,
-          typename Index >
+          typename Index, typename Allocator >
 auto
-binaryAnd( const Containers::Vector< Real, Device, Index >& a ) -> decltype( Containers::Expressions::ExpressionBinaryAnd( a.getView() ) )
+binaryAnd( const Containers::Vector< Real, Device, Index, Allocator >& a )
 {
-   return Containers::Expressions::ExpressionBinaryAnd( a.getView() );
+   return Containers::Expressions::ExpressionBinaryAnd( a.getConstView() );
 }
 
 ////
 // Dot product - the same as scalar product, just for convenience
-// TODO: auto+decltype does not work with NVCC 10.1
-template< typename Real, typename Device, typename Index, typename ET >
-//auto
-Real dot( const Containers::Vector< Real, Device, Index >& a, const ET& b )//->decltype( TNL::sum( a.getView() * b ) )
+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 TNL::sum( a.getView() * b );
+   return TNL::sum( a.getConstView() * b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-//auto
-Real dot( const ET& a, const Containers::Vector< Real, Device, Index >& b )//->decltype( TNL::sum( a * b.getView() ) )
+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 TNL::sum( a * b.getView() );
+   return TNL::sum( a * b.getConstView() );
 }
 
-template< typename Real1, typename Real2, typename Device, typename Index >
-//auto
-Real1 dot( const Containers::Vector< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index >& b )
-//->decltype( TNL::sum( a.getView() * b.getView() ) )
+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 TNL::sum( a.getView() * b.getView() );
+   return TNL::sum( a.getConstView() * b.getConstView() );
 }
 
 ////
 // TODO: Replace this with multiplication when its safe
-template< typename Real, typename Device, typename Index, typename ET >
+template< typename Real, typename Device, typename Index, typename Allocator, typename ET,
+          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
 Containers::VectorView< Real, Device, Index >
-Scale( const Containers::Vector< Real, Device, Index >& a, const ET& b )
+Scale( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b )
 {
-   Containers::VectorView< Real, Device, Index > result = Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real, Device, Index >::ConstViewType, ET, Containers::Expressions::Multiplication >( a.getView(), b );
+   Containers::VectorView< Real, Device, Index > result = Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType, ET, Containers::Expressions::Multiplication >( a.getConstView(), b );
    return result;
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-Containers::Expressions::BinaryExpressionTemplate< ET, typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Multiplication >
-Scale( const ET& a, const Containers::Vector< Real, Device, Index >& b )
+template< typename ET, typename Real, typename Device, typename Index, typename Allocator,
+          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
+Containers::Expressions::BinaryExpressionTemplate< ET, typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType, Containers::Expressions::Multiplication >
+Scale( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b )
 {
-   Containers::VectorView< Real, Device, Index > result =  Containers::Expressions::BinaryExpressionTemplate< ET, typename Containers::Vector< Real, Device, Index >::ConstViewType, Containers::Expressions::Multiplication >( a, b.getView() );
+   Containers::VectorView< Real, Device, Index > result =  Containers::Expressions::BinaryExpressionTemplate< ET, typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType, Containers::Expressions::Multiplication >( a, b.getConstView() );
    return result;
 }
 
-template< typename Real1, typename Real2, typename Device, typename Index >
-Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real1, Device, Index >::ConstViewType, typename Containers::Vector< Real2, Device, Index >::ConstViewType, Containers::Expressions::Multiplication >
-Scale( const Containers::Vector< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index >& b )
+template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator >
+Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType, typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType, Containers::Expressions::Multiplication >
+Scale( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b )
 {
-   Containers::VectorView< Real1, Device, Index > result =  Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real1, Device, Index >::ConstViewType, typename Containers::Vector< Real2, Device, Index >::ConstViewType, Containers::Expressions::Multiplication >( a.getView(), b.getView() );
+   Containers::VectorView< Real1, Device, Index > result =  Containers::Expressions::BinaryExpressionTemplate< typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType, typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType, Containers::Expressions::Multiplication >( a.getConstView(), b.getConstView() );
    return result;
 }
 
diff --git a/src/TNL/Containers/VectorView.h b/src/TNL/Containers/VectorView.h
index 71676dd7d822b59b0c84f85e83197768ab083251..81f6f50757ca99811e43105a5be17ee5a32c1dc3 100644
--- a/src/TNL/Containers/VectorView.h
+++ b/src/TNL/Containers/VectorView.h
@@ -19,12 +19,9 @@
 namespace TNL {
 namespace Containers {
 
-template< typename Real, typename Device, typename Index >
+template< typename Real, typename Device, typename Index, typename Allocator >
 class Vector;
 
-template< int Size, typename Real >
-class StaticVector;
-
 template< typename Real = double,
           typename Device = Devices::Host,
           typename Index = int >
@@ -72,9 +69,9 @@ public:
    /**
     * \brief Returns a modifiable view of the vector view.
     *
-    * If \e begin or \e end is set to a non-zero value, a view for the
-    * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-    * vector view is returned.
+    * By default, a view for the whole vector is returned. If \e begin or
+    * \e end is set to a non-zero value, a view only for the sub-interval
+    * `[begin, end)` is returned.
     *
     * \param begin The beginning of the vector view sub-interval. It is 0 by
     *              default.
@@ -87,9 +84,9 @@ public:
    /**
     * \brief Returns a non-modifiable view of the vector view.
     *
-    * If \e begin or \e end is set to a non-zero value, a view for the
-    * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-    * vector view is returned.
+    * By default, a view for the whole vector is returned. If \e begin or
+    * \e end is set to a non-zero value, a view only for the sub-interval
+    * `[begin, end)` is returned.
     *
     * \param begin The beginning of the vector view sub-interval. It is 0 by
     *              default.
@@ -102,9 +99,9 @@ public:
    /**
     * \brief Returns a non-modifiable view of the vector view.
     *
-    * If \e begin or \e end is set to a non-zero value, a view for the
-    * sub-interval `[begin, end)` is returned. Otherwise a view for whole
-    * vector view is returned.
+    * By default, a view for the whole vector is returned. If \e begin or
+    * \e end is set to a non-zero value, a view only for the sub-interval
+    * `[begin, end)` is returned.
     *
     * \param begin The beginning of the vector view sub-interval. It is 0 by
     *              default.
@@ -133,8 +130,8 @@ public:
    template< typename Real_, typename Device_, typename Index_ >
    VectorView& operator=( const VectorView< Real_, Device_, Index_ >& v );
 
-   template< typename Real_, typename Device_, typename Index_ >
-   VectorView& operator=( const Vector< Real_, Device_, Index_ >& v );
+   template< typename Real_, typename Device_, typename Index_, typename Allocator_ >
+   VectorView& operator=( const Vector< Real_, Device_, Index_, Allocator_ >& v );
 
    template< typename VectorExpression >
    VectorView& operator=( const VectorExpression& expression );
diff --git a/src/TNL/Containers/VectorView.hpp b/src/TNL/Containers/VectorView.hpp
index 5d7ba6dd75d6d0601405ebf5a2d0ba567a0feb9f..435e70a8646a6657f9f6898651c606846a7b740c 100644
--- a/src/TNL/Containers/VectorView.hpp
+++ b/src/TNL/Containers/VectorView.hpp
@@ -127,9 +127,9 @@ VectorView< Real, Device, Index >::operator=( const VectorView< Real_, Device_,
 template< typename Real,
           typename Device,
           typename Index >
-  template< typename Real_, typename Device_, typename Index_ >
+  template< typename Real_, typename Device_, typename Index_, typename Allocator_ >
 VectorView< Real, Device, Index >&
-VectorView< Real, Device, Index >::operator=( const Vector< Real_, Device_, Index_ >& v )
+VectorView< Real, Device, Index >::operator=( const Vector< Real_, Device_, Index_, Allocator_ >& v )
 {
    ArrayView< Real, Device, Index >::operator=( v );
    return *this;
diff --git a/src/TNL/Containers/VectorViewExpressions.h b/src/TNL/Containers/VectorViewExpressions.h
index fc1e7749da6a96e4d9f20deee02e6e62d2097f54..417948504874e30115c03ad069e9f5bc5ab58b39 100644
--- a/src/TNL/Containers/VectorViewExpressions.h
+++ b/src/TNL/Containers/VectorViewExpressions.h
@@ -16,297 +16,334 @@
 #include <TNL/Containers/Expressions/Comparison.h>
 #include <TNL/Containers/Expressions/VerticalOperations.h>
 
-namespace TNL {
-   namespace Containers {
-////
-// All operations are supposed to be in namespace TNL
+#include "VectorView.h"
 
+namespace TNL {
+namespace Containers {
 
 ////
 // Addition
-template< typename Real, typename Device, typename Index, typename ET >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Addition >
-operator+( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Addition >( a, b );
+   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Addition >( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-const Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Addition >
-operator+( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Addition >( a, b );
+   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Addition >( a, b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Addition >
-operator+( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
+auto
+operator+( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Addition >( a, 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 >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Subtraction >
-operator-( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Subtraction >( a, b );
+   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Subtraction >( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-const Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Subtraction >
-operator-( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Subtraction >( a, b );
+   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Subtraction >( a, b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Subtraction >
-operator-( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
+auto
+operator-( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Subtraction >( a, 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 >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Multiplication >
-operator*( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Multiplication >( a, b );
+   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Multiplication >( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-const Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Multiplication >
-operator*( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Multiplication >( a, b );
+   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Multiplication >( a, b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Multiplication >
-operator*( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
+auto
+operator*( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Multiplication >( a, 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 >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Division >
-operator/( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Division >( a, b );
+   return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Division >( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-const Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Division >
-operator/( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Division >( a, b );
+   return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Division >( a, b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Division >
-operator/( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
+auto
+operator/( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
 {
-   return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Division >( a, 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 >
-bool operator==( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::Comparison< Containers::VectorView< Real, Device, Index >, ET >::EQ( a, b );
+   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::EQ( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator==( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::Comparison< ET, Containers::VectorView< Real, Device, Index > >::EQ( a, 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 Containers::VectorView< Real1, Device1, Index >& a, const Containers::VectorView< Real2, Device2, Index >& b )
+bool
+operator==( const VectorView< Real1, Device1, Index >& a, const VectorView< Real2, Device2, Index >& b )
 {
    if( a.getSize() != b.getSize() )
       return false;
    if( a.getSize() == 0 )
       return true;
-   return Containers::Algorithms::ArrayOperations< Device1, Device2 >::
-            compareMemory( a.getData(),
-                           b.getData(),
-                           a.getSize() );
+   return Algorithms::ArrayOperations< Device1, Device2 >::
+            compare( a.getData(),
+                     b.getData(),
+                     a.getSize() );
 }
 
 ////
 // Comparison operations - operator !=
-template< typename Real, typename Device, typename Index, typename ET >
-bool operator!=( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::Comparison< Containers::VectorView< Real, Device, Index >, ET >::NE( a, b );
+   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::NE( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator!=( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::Comparison< ET, Containers::VectorView< Real, Device, Index > >::NE( a, 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 Containers::VectorView< Real1, Device1, Index >& a, const Containers::VectorView< Real2, Device2, Index >& b )
+bool
+operator!=( const VectorView< Real1, Device1, Index >& a, const VectorView< Real2, Device2, Index >& b )
 {
    if( a.getSize() != b.getSize() )
       return false;
    if( a.getSize() == 0 )
       return true;
-   return !Containers::Algorithms::ArrayOperations< Device1, Device2 >::
-            compareMemory( a.getData(),
-                           b.getData(),
-                           a.getSize() );
+   return !Algorithms::ArrayOperations< Device1, Device2 >::
+            compare( a.getData(),
+                     b.getData(),
+                     a.getSize() );
 }
 
 ////
 // Comparison operations - operator <
-template< typename Real, typename Device, typename Index, typename ET >
-bool operator<( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::Comparison< Containers::VectorView< Real, Device, Index >, ET >::LT( a, b );
+   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::LT( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator<( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::Comparison< ET, Containers::VectorView< Real, Device, Index > >::LT( a, b );
+   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::LT( a, b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index >
-bool operator<( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
+bool
+operator<( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
 {
-   return Containers::Expressions::Comparison< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index > >::LT( a, 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 >
-bool operator<=( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::Comparison< Containers::VectorView< Real, Device, Index >, ET >::LE( a, b );
+   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::LE( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator<=( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::Comparison< ET, Containers::VectorView< Real, Device, Index > >::LE( a, b );
+   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::LE( a, b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index >
-bool operator<=( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
+bool
+operator<=( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
 {
-   return Containers::Expressions::Comparison< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index > >::LE( a, 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 >
-bool operator>( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::Comparison< Containers::VectorView< Real, Device, Index >, ET >::GT( a, b );
+   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::GT( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator>( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::Comparison< ET, Containers::VectorView< Real, Device, Index > >::GT( a, b );
+   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::GT( a, b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index >
-bool operator>( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
+bool
+operator>( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
 {
-   return Containers::Expressions::Comparison< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index > >::GT( a, 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 >
-bool operator>=( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
+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 Containers::Expressions::Comparison< Containers::VectorView< Real, Device, Index >, ET >::GE( a, b );
+   return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::GE( a, b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-bool operator>=( const ET& a, const Containers::VectorView< Real, Device, Index >& 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 Containers::Expressions::Comparison< ET, Containers::VectorView< Real, Device, Index > >::GE( a, b );
+   return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::GE( a, b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index >
-bool operator>=( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
+bool
+operator>=( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
 {
-   return Containers::Expressions::Comparison< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index > >::GE( a, b );
+   return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::GE( a, b );
 }
 
 ////
 // Minus
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Minus >
-operator-( const Containers::VectorView< Real, Device, Index >& a )
+auto
+operator-( const VectorView< Real, Device, Index >& a )
 {
-   return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Minus >( a );
+   return Expressions::UnaryExpressionTemplate< VectorView< Real, Device, Index >, Expressions::Minus >( a );
 }
 
 ////
 // Scalar product
-template< typename Real, typename Device, typename Index, typename ET >
-//Real 
+template< typename Real, typename Device, typename Index, typename ET,
+          typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > >
 auto
-operator,( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
-->decltype( TNL::sum( a * b ) )
+operator,( const VectorView< Real, Device, Index >& a, const ET& b )
 {
    return TNL::sum( a * b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
-//Real
+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 Containers::VectorView< Real, Device, Index >& b )
-->decltype( TNL::sum( a * b ) )
+operator,( const ET& a, const VectorView< Real, Device, Index >& b )
 {
    return TNL::sum( a * b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index >
-auto operator,( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b )
-->decltype( TNL::sum( a * b ) )
+auto
+operator,( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b )
 {
    return TNL::sum( a * b );
 }
 
-} //namespace Containers
+} // namespace Containers
 
 ////
 // All functions are supposed to be in namespace TNL
 
 ////
 // Min
-template< typename Real, typename Device, typename Index, typename ET >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::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 >
-const Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Min >
+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 >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Min >
+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 );
@@ -314,22 +351,24 @@ min( const Containers::VectorView< Real1, Device, Index >& a, const Containers::
 
 ////
 // Max
-template< typename Real, typename Device, typename Index, typename ET >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::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 >
-const Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Max >
+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 >
-const Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Max >
+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 );
@@ -338,7 +377,7 @@ max( const Containers::VectorView< Real1, Device, Index >& a, const Containers::
 ////
 // Abs
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Abs >
+auto
 abs( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Abs >( a );
@@ -347,7 +386,7 @@ abs( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Sine
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sin >
+auto
 sin( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sin >( a );
@@ -356,7 +395,7 @@ sin( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Cosine
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cos >
+auto
 cos( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cos >( a );
@@ -365,7 +404,7 @@ cos( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Tangent
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tan >
+auto
 tan( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tan >( a );
@@ -374,7 +413,7 @@ tan( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Sqrt
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sqrt >
+auto
 sqrt( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sqrt >( a );
@@ -383,7 +422,7 @@ sqrt( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Cbrt
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cbrt >
+auto
 cbrt( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cbrt >( a );
@@ -392,7 +431,7 @@ cbrt( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Power
 template< typename Real, typename Device, typename Index, typename ExpType >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Pow, ExpType >
+auto
 pow( const Containers::VectorView< Real, Device, Index >& a, const ExpType& exp )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Pow, ExpType >( a, exp );
@@ -401,7 +440,7 @@ pow( const Containers::VectorView< Real, Device, Index >& a, const ExpType& exp
 ////
 // Floor
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Floor >
+auto
 floor( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Floor >( a );
@@ -410,7 +449,7 @@ floor( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Ceil
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Ceil >
+auto
 ceil( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Ceil >( a );
@@ -419,7 +458,7 @@ ceil( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Acos
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Acos >
+auto
 acos( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Acos >( a );
@@ -428,7 +467,7 @@ acos( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Asin
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Asin >
+auto
 asin( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Asin >( a );
@@ -437,7 +476,7 @@ asin( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Atan
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Atan >
+auto
 atan( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Atan >( a );
@@ -446,7 +485,7 @@ atan( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Cosh
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cosh >
+auto
 cosh( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cosh >( a );
@@ -455,7 +494,7 @@ cosh( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Tanh
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tanh >
+auto
 tanh( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tanh >( a );
@@ -464,7 +503,7 @@ tanh( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Log
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log >
+auto
 log( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log >( a );
@@ -473,7 +512,7 @@ log( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Log10
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log10 >
+auto
 log10( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log10 >( a );
@@ -482,7 +521,7 @@ log10( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Log2
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log2 >
+auto
 log2( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log2 >( a );
@@ -491,7 +530,7 @@ log2( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Exp
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Exp >
+auto
 exp( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Exp >( a );
@@ -500,7 +539,7 @@ exp( const Containers::VectorView< Real, Device, Index >& a )
 ////
 // Sign
 template< typename Real, typename Device, typename Index >
-const Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sign >
+auto
 sign( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sign >( a );
@@ -511,7 +550,7 @@ sign( const Containers::VectorView< Real, Device, Index >& a )
 template< typename Real,
           typename Device,
           typename Index >
-typename Containers::VectorView< Real, Device, Index >::RealType
+Real
 min( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::ExpressionMin( a );
@@ -520,7 +559,7 @@ min( const Containers::VectorView< Real, Device, Index >& a )
 template< typename Real,
           typename Device,
           typename Index >
-typename Containers::VectorView< Real, Device, Index >::RealType
+Real
 argMin( const Containers::VectorView< Real, Device, Index >& a, Index& arg )
 {
    return Containers::Expressions::ExpressionArgMin( a, arg );
@@ -529,7 +568,7 @@ argMin( const Containers::VectorView< Real, Device, Index >& a, Index& arg )
 template< typename Real,
           typename Device,
           typename Index >
-typename Containers::VectorView< Real, Device, Index >::RealType
+Real
 max( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::ExpressionMax( a );
@@ -538,7 +577,7 @@ max( const Containers::VectorView< Real, Device, Index >& a )
 template< typename Real,
           typename Device,
           typename Index >
-typename Containers::VectorView< Real, Device, Index >::RealType
+Real
 argMax( const Containers::VectorView< Real, Device, Index >& a, Index& arg )
 {
    return Containers::Expressions::ExpressionArgMax( a, arg );
@@ -549,7 +588,6 @@ template< typename Real,
           typename Index >
 auto
 sum( const Containers::VectorView< Real, Device, Index >& a )
--> decltype( Containers::Expressions::ExpressionSum( a ) )
 {
    return Containers::Expressions::ExpressionSum( a );
 }
@@ -566,7 +604,7 @@ lpNorm( const Containers::VectorView< Real, Device, Index >& a, const Real2& p )
       return Containers::Expressions::ExpressionLpNorm( a, p );
    if( p == 2.0 )
       return TNL::sqrt( Containers::Expressions::ExpressionLpNorm( a, p ) );
-   return TNL::pow( Containers::Expressions::ExpressionLpNorm( a, p ), 1.0 / p );
+   return TNL::pow( Containers::Expressions::ExpressionLpNorm( a, p ), (Real2) (1.0 / p) );
 }
 
 template< typename Real,
@@ -574,7 +612,6 @@ template< typename Real,
           typename Index >
 auto
 product( const Containers::VectorView< Real, Device, Index >& a )
--> decltype( Containers::Expressions::ExpressionProduct( a ) )
 {
    return Containers::Expressions::ExpressionProduct( a );
 }
@@ -582,7 +619,7 @@ product( const Containers::VectorView< Real, Device, Index >& a )
 template< typename Real,
           typename Device,
           typename Index >
-bool
+auto
 logicalOr( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::ExpressionLogicalOr( a );
@@ -593,7 +630,6 @@ template< typename Real,
           typename Index >
 auto
 binaryOr( const Containers::VectorView< Real, Device, Index >& a )
--> decltype( Containers::Expressions::ExpressionBinaryOr( a ) )
 {
    return Containers::Expressions::ExpressionBinaryOr( a );
 }
@@ -601,7 +637,7 @@ binaryOr( const Containers::VectorView< Real, Device, Index >& a )
 template< typename Real,
           typename Device,
           typename Index >
-bool
+auto
 logicalAnd( const Containers::VectorView< Real, Device, Index >& a )
 {
    return Containers::Expressions::ExpressionLogicalAnd( a );
@@ -612,40 +648,39 @@ template< typename Real,
           typename Index >
 auto
 binaryAnd( const Containers::VectorView< Real, Device, Index >& a )
--> decltype( Containers::Expressions::ExpressionBinaryAnd( a ) )
 {
    return Containers::Expressions::ExpressionBinaryAnd( a );
 }
 
 ////
 // Dot product - the same as scalar product, just for convenience
-template< typename Real, typename Device, typename Index, typename ET >
+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 )
-->decltype( TNL::sum( a * b ) )
 {
    return TNL::sum( a * b );
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
+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 )
-->decltype( TNL::sum( a * b ) )
 {
    return TNL::sum( a * b );
 }
 
 template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2 >
-//auto
-Real1 dot( const Containers::VectorView< Real1, Device, Index1 >& a, const Containers::VectorView< Real2, Device, Index2 >& b )
-//->decltype( TNL::sum( a * b ) )
+auto
+dot( const Containers::VectorView< Real1, Device, Index1 >& a, const Containers::VectorView< Real2, Device, Index2 >& b )
 {
    return TNL::sum( a * b );
 }
 
 ////
 // TODO: Replace this with multiplication when its safe
-template< typename Real, typename Device, typename Index, typename ET >
+template< typename Real, typename Device, typename Index, typename ET,
+          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
 Containers::VectorView< Real, Device, Index >
 Scale( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
 {
@@ -653,7 +688,8 @@ Scale( const Containers::VectorView< Real, Device, Index >& a, const ET& b )
    return result;
 }
 
-template< typename ET, typename Real, typename Device, typename Index >
+template< typename ET, typename Real, typename Device, typename Index,
+          typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > >
 Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Multiplication >
 Scale( const ET& a, const Containers::VectorView< Real, Device, Index >& b )
 {
diff --git a/src/TNL/Devices/Host.h b/src/TNL/Devices/Host.h
index 297172774f573b2eeee3a2849b288c54d8427597..649749f588143ab80793e64c3d93e03bf2147229 100644
--- a/src/TNL/Devices/Host.h
+++ b/src/TNL/Devices/Host.h
@@ -19,6 +19,7 @@
 #endif
 
 namespace TNL {
+//! \brief Namespace for TNL execution models
 namespace Devices {
 
 class Host
diff --git a/src/TNL/Devices/MIC.h b/src/TNL/Devices/MIC.h
index db1a238097f12cdaf3a2076b030baebe50d94eaf..f347a24d1f9e4fa6d5cceb7e2693807c7158065a 100644
--- a/src/TNL/Devices/MIC.h
+++ b/src/TNL/Devices/MIC.h
@@ -134,29 +134,6 @@ class MIC
             }
         };
 
-        static inline
-        void* AllocMIC(size_t size)
-        {
-            Devices::MICHider<void> hide_ptr;
-            #pragma offload target(mic) out(hide_ptr) in(size)
-            {
-                hide_ptr.pointer=malloc(size);
-            }
-            return hide_ptr.pointer;
-        };
-
-        static inline
-        void FreeMIC(void* ptr)
-        {
-                Devices::MICHider<void> hide_ptr;
-                hide_ptr.pointer=ptr;
-                #pragma offload target(mic) in(hide_ptr)
-                {
-                        free(hide_ptr.pointer);
-                }
-        };
-
-
 #endif
 
    static void insertSmartPointer( Pointers::SmartPointer* pointer )
diff --git a/src/TNL/Matrices/MatrixOperations.h b/src/TNL/Matrices/MatrixOperations.h
index e3d7ed6e41d64355975b5a5c5e63ed25268b0ed9..07991a573662c7380d6fd2814b0a20db30e7dca8 100644
--- a/src/TNL/Matrices/MatrixOperations.h
+++ b/src/TNL/Matrices/MatrixOperations.h
@@ -341,7 +341,7 @@ public:
       // TODO: use static storage, e.g. from the CudaReductionBuffer, to avoid frequent reallocations
       Containers::Vector< RealType, Devices::Cuda, IndexType > xDevice;
       xDevice.setSize( n );
-      Containers::Algorithms::ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory< RealType, RealType, IndexType >( xDevice.getData(), x, n );
+      Containers::Algorithms::ArrayOperations< Devices::Cuda, Devices::Host >::copy< RealType, RealType, IndexType >( xDevice.getData(), x, n );
 
       // desGridSize = blocksPerMultiprocessor * numberOfMultiprocessors
       const int desGridSize = 32 * Devices::CudaDeviceInfo::getCudaMultiprocessors( Devices::CudaDeviceInfo::getActiveDevice() );
diff --git a/src/TNL/Pointers/DevicePointer.h b/src/TNL/Pointers/DevicePointer.h
index 867f18fcbf0bb4c2aaee8e621616c5fe0e6417dc..b0c0a934fa0dee01ebe4bb2d93abe3e6d0d36b68 100644
--- a/src/TNL/Pointers/DevicePointer.h
+++ b/src/TNL/Pointers/DevicePointer.h
@@ -12,6 +12,7 @@
 
 #pragma once
 
+#include <TNL/Allocators/Default.h>
 #include <TNL/Devices/Host.h>
 #include <TNL/Devices/Cuda.h>
 #include <TNL/Devices/MIC.h>
@@ -695,7 +696,7 @@ class DevicePointer< Object, Devices::MIC > : public SmartPointer
          if( ! this->pd )
             return false;
          // pass to device
-         this->mic_pointer = (ObjectType*)Devices::MIC::AllocMIC(sizeof(ObjectType));
+         this->mic_pointer = Allocators:::MIC< ObjectType >().allocate(1);
          if( ! this->mic_pointer )
             return false;
          Devices::MIC::CopyToMIC((void*)this->mic_pointer,(void*)this->pointer,sizeof(ObjectType));
@@ -733,7 +734,7 @@ class DevicePointer< Object, Devices::MIC > : public SmartPointer
                delete this->pd;
                this->pd = nullptr;
                if( this->mic_pointer )
-                  Devices::MIC::FreeMIC( (void*) this->mic_pointer );
+                  Allocators:::MIC< ObjectType >().deallocate(this->mic_pointer, 1);
             }
          }
       }
diff --git a/src/TNL/Pointers/SharedPointerMic.h b/src/TNL/Pointers/SharedPointerMic.h
index 0e19e78b21eb48d8d2c83df35332ad6f888e9a93..0c2958b4ad7c6552f58363c98dca5104908f04cc 100644
--- a/src/TNL/Pointers/SharedPointerMic.h
+++ b/src/TNL/Pointers/SharedPointerMic.h
@@ -14,6 +14,7 @@
 
 #include "SharedPointer.h"
 
+#include <TNL/Allocators/Default.h>
 #include <TNL/Devices/MIC.h>
 #include <TNL/Pointers/SmartPointer.h>
 
@@ -307,7 +308,7 @@ class SharedPointer< Object, Devices::MIC > : public SmartPointer
          if( ! this->pd )
             return false;
 
-         mic_pointer=(Object*)Devices::MIC::AllocMIC(sizeof(Object));
+         mic_pointer = Allocators::MIC< Object >().allocate(1);
          Devices::MIC::CopyToMIC((void*)this->mic_pointer,(void*) &this->pd->data,sizeof(Object));
 
          if( ! this->mic_pointer )
@@ -350,8 +351,8 @@ class SharedPointer< Object, Devices::MIC > : public SmartPointer
                this->pd = nullptr;
                if( this->mic_pointer )
                {
-                   Devices::MIC::FreeMIC((void*)mic_pointer);
-                   mic_pointer=nullptr;
+                  Allocators:::MIC< ObjectType >().deallocate(mic_pointer, 1);
+                  mic_pointer=nullptr;
                }
 #ifdef TNL_DEBUG_SHARED_POINTERS
                std::cerr << "...deleted data." << std::endl;
diff --git a/src/TNL/Pointers/UniquePointer.h b/src/TNL/Pointers/UniquePointer.h
index c8efd5afe38d47b07904be5e93d5de6f5fe53aec..cfb7b543fc3e94858ad5c34d4bf8e8c0faf85462 100644
--- a/src/TNL/Pointers/UniquePointer.h
+++ b/src/TNL/Pointers/UniquePointer.h
@@ -12,6 +12,7 @@
 
 #pragma once
 
+#include <TNL/Allocators/Default.h>
 #include <TNL/Devices/Host.h>
 #include <TNL/Devices/Cuda.h>
 #include <TNL/Devices/MIC.h>
@@ -446,7 +447,7 @@ class UniquePointer< Object, Devices::MIC > : public SmartPointer
          if( ! this->pd )
             return false;
          // pass to device
-         this->mic_pointer=(Object*)Devices::MIC::AllocMIC(sizeof(Object));
+         this->mic_pointer = Allocators::MIC< Object >().allocate(1);
          if( ! this->mic_pointer )
             return false;
          Devices::MIC::CopyToMIC((void*)mic_pointer,(void*)&this->pd->data,sizeof(Object));
@@ -477,7 +478,7 @@ class UniquePointer< Object, Devices::MIC > : public SmartPointer
          if( this->pd )
             delete this->pd;
          if( this->mic_pointer )
-             Devices::MIC::FreeMIC(mic_pointer);
+            Allocators:::MIC< ObjectType >().deallocate(mic_pointer, 1);
       }
 
       PointerData* pd;
diff --git a/src/TNL/Solvers/Linear/GMRES_impl.h b/src/TNL/Solvers/Linear/GMRES_impl.h
index f877172fc285d1a9018168a709fdb0a1d7d74058..06b1295014839a353f1e1d69e285b4628d650984 100644
--- a/src/TNL/Solvers/Linear/GMRES_impl.h
+++ b/src/TNL/Solvers/Linear/GMRES_impl.h
@@ -460,7 +460,7 @@ hauseholder_apply_trunc( HostView out,
    // The upper (m+1)x(m+1) submatrix of Y is duplicated in the YL buffer,
    // which resides on host and is broadcasted from rank 0 to all processes.
    HostView YL_i( &YL[ i * (restarting_max + 1) ], restarting_max + 1 );
-   Containers::Algorithms::ArrayOperations< Devices::Host, DeviceType >::copyMemory( YL_i.getData(), Traits::getLocalVectorView( y_i ).getData(), YL_i.getSize() );
+   Containers::Algorithms::ArrayOperations< Devices::Host, DeviceType >::copy( YL_i.getData(), Traits::getLocalVectorView( y_i ).getData(), YL_i.getSize() );
    // no-op if the problem is not distributed
    CommunicatorType::Bcast( YL_i.getData(), YL_i.getSize(), 0, Traits::getCommunicationGroup( *this->matrix ) );
 
@@ -475,7 +475,7 @@ hauseholder_apply_trunc( HostView out,
       }
       if( std::is_same< DeviceType, Devices::Cuda >::value ) {
          RealType host_z[ i + 1 ];
-         Containers::Algorithms::ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory( host_z, Traits::getLocalVectorView( z ).getData(), i + 1 );
+         Containers::Algorithms::ArrayOperations< Devices::Host, Devices::Cuda >::copy( host_z, Traits::getLocalVectorView( z ).getData(), i + 1 );
          for( int k = 0; k <= i; k++ )
             out[ k ] = host_z[ k ] - YL_i[ k ] * aux;
       }
diff --git a/src/TNL/TypeTraits.h b/src/TNL/TypeTraits.h
index d7a1a4f12791bbecda6368f9ac341f41a2327dbf..c251dca0180e5bddd0e083108f13b50e4ceb8383 100644
--- a/src/TNL/TypeTraits.h
+++ b/src/TNL/TypeTraits.h
@@ -13,6 +13,7 @@
 
 namespace TNL {
 
+// TODO: remove - not used anywhere
 template< typename T >
 struct ViewTypeGetter
 {
diff --git a/src/UnitTests/AllocatorsTest.cpp b/src/UnitTests/AllocatorsTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ba28216dc87bc8405b0ebb4b0d5da60fce2e0bf7
--- /dev/null
+++ b/src/UnitTests/AllocatorsTest.cpp
@@ -0,0 +1 @@
+#include "AllocatorsTest.h"
diff --git a/src/UnitTests/AllocatorsTest.cu b/src/UnitTests/AllocatorsTest.cu
new file mode 100644
index 0000000000000000000000000000000000000000..ba28216dc87bc8405b0ebb4b0d5da60fce2e0bf7
--- /dev/null
+++ b/src/UnitTests/AllocatorsTest.cu
@@ -0,0 +1 @@
+#include "AllocatorsTest.h"
diff --git a/src/UnitTests/AllocatorsTest.h b/src/UnitTests/AllocatorsTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..5434a495085d38ad345f0ece4f530aba2184a6ba
--- /dev/null
+++ b/src/UnitTests/AllocatorsTest.h
@@ -0,0 +1,115 @@
+/***************************************************************************
+                          AllocatorsTest.h  -  description
+                             -------------------
+    begin                : Jul 4, 2019
+    copyright            : (C) 2019 by Tomas Oberhuber et al.
+    email                : tomas.oberhuber@fjfi.cvut.cz
+ ***************************************************************************/
+
+/* See Copyright Notice in tnl/Copyright */
+
+#pragma once
+
+#ifdef HAVE_GTEST
+#include <TNL/Allocators/Host.h>
+#include <TNL/Allocators/Cuda.h>
+#include <TNL/Allocators/CudaHost.h>
+#include <TNL/Allocators/CudaManaged.h>
+#include <TNL/Containers/Algorithms/ArrayOperations.h>
+
+#include "gtest/gtest.h"
+
+using namespace TNL;
+
+constexpr int ARRAY_TEST_SIZE = 5000;
+
+// test fixture for typed tests
+template< typename Value >
+class AllocatorsTest : public ::testing::Test
+{
+protected:
+   using ValueType = Value;
+};
+
+// types for which ArrayTest is instantiated
+using ValueTypes = ::testing::Types< short int, int, long, float, double >;
+
+TYPED_TEST_SUITE( AllocatorsTest, ValueTypes );
+
+TYPED_TEST( AllocatorsTest, Host )
+{
+   using ValueType = typename TestFixture::ValueType;
+   using Allocator = Allocators::Host< ValueType >;
+
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
+   ASSERT_NE( data, nullptr );
+
+   // do something useful with the data
+   for (int i = 0; i < ARRAY_TEST_SIZE; i++) {
+      data[i] = 0;
+      EXPECT_EQ(data[i], 0);
+   }
+
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
+}
+
+#ifdef HAVE_CUDA
+TYPED_TEST( AllocatorsTest, CudaHost )
+{
+   using ValueType = typename TestFixture::ValueType;
+   using Allocator = Allocators::CudaHost< ValueType >;
+
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
+   ASSERT_NE( data, nullptr );
+
+   // do something useful with the data
+   for (int i = 0; i < ARRAY_TEST_SIZE; i++) {
+      data[i] = 0;
+      EXPECT_EQ(data[i], 0);
+   }
+
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
+}
+
+TYPED_TEST( AllocatorsTest, CudaManaged )
+{
+   using ValueType = typename TestFixture::ValueType;
+   using Allocator = Allocators::CudaManaged< ValueType >;
+
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
+   ASSERT_NE( data, nullptr );
+
+   // set data on the device
+   Containers::Algorithms::ArrayOperations< Devices::Cuda >::set( data, (ValueType) 0, ARRAY_TEST_SIZE );
+   ASSERT_NO_THROW( TNL_CHECK_CUDA_DEVICE );
+
+   // check values on the host
+   for (int i = 0; i < ARRAY_TEST_SIZE; i++)
+      EXPECT_EQ(data[i], 0);
+
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
+}
+
+TYPED_TEST( AllocatorsTest, Cuda )
+{
+   using ValueType = typename TestFixture::ValueType;
+   using Allocator = Allocators::CudaHost< ValueType >;
+
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
+   ASSERT_NE( data, nullptr );
+
+   // set data on the device
+   Containers::Algorithms::ArrayOperations< Devices::Cuda >::set( data, (ValueType) 0, ARRAY_TEST_SIZE );
+   ASSERT_NO_THROW( TNL_CHECK_CUDA_DEVICE );
+
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
+}
+#endif // HAVE_CUDA
+#endif // HAVE_GTEST
+
+
+#include "main.h"
diff --git a/src/UnitTests/CMakeLists.txt b/src/UnitTests/CMakeLists.txt
index f7d3b68b03d3f5e52a23f6bf47f5c25ac9b8f0ae..331d199388c3e13a2dc930744571d87847948311 100644
--- a/src/UnitTests/CMakeLists.txt
+++ b/src/UnitTests/CMakeLists.txt
@@ -14,6 +14,15 @@ if( BUILD_CUDA )
    TARGET_LINK_LIBRARIES( AssertCudaTest ${GTEST_BOTH_LIBRARIES} )
 endif()
 
+if( BUILD_CUDA )
+   CUDA_ADD_EXECUTABLE( AllocatorsTest AllocatorsTest.cu OPTIONS ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( AllocatorsTest ${GTEST_BOTH_LIBRARIES} )
+else()
+   ADD_EXECUTABLE( AllocatorsTest AllocatorsTest.cpp )
+   TARGET_COMPILE_OPTIONS( AllocatorsTest PRIVATE ${CXX_TESTS_FLAGS} )
+   TARGET_LINK_LIBRARIES( AllocatorsTest ${GTEST_BOTH_LIBRARIES} )
+endif()
+
 if( BUILD_CUDA )
    CUDA_ADD_EXECUTABLE( FileTest FileTest.cu OPTIONS ${CXX_TESTS_FLAGS} )
    TARGET_LINK_LIBRARIES( FileTest ${GTEST_BOTH_LIBRARIES} )
@@ -52,6 +61,7 @@ ADD_TEST( AssertTest ${EXECUTABLE_OUTPUT_PATH}/AssertTest${CMAKE_EXECUTABLE_SUFF
 if( BUILD_CUDA )
    ADD_TEST( AssertCudaTest ${EXECUTABLE_OUTPUT_PATH}/AssertCudaTest${CMAKE_EXECUTABLE_SUFFIX} )
 endif()
+ADD_TEST( AllocatorsTest ${EXECUTABLE_OUTPUT_PATH}/AllocatorsTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( FileTest ${EXECUTABLE_OUTPUT_PATH}/FileTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( StringTest ${EXECUTABLE_OUTPUT_PATH}/StringTest${CMAKE_EXECUTABLE_SUFFIX} )
 ADD_TEST( ObjectTest ${EXECUTABLE_OUTPUT_PATH}/ObjectTest${CMAKE_EXECUTABLE_SUFFIX} )
diff --git a/src/UnitTests/Containers/ArrayOperationsTest.h b/src/UnitTests/Containers/ArrayOperationsTest.h
index 4c1b6b9c2ced4d380e93f1056cafab50b0335b64..4a48261be0401eed2231a007d7e68dfed711cb2b 100644
--- a/src/UnitTests/Containers/ArrayOperationsTest.h
+++ b/src/UnitTests/Containers/ArrayOperationsTest.h
@@ -10,7 +10,9 @@
 
 #pragma once
 
-#ifdef HAVE_GTEST 
+#ifdef HAVE_GTEST
+#include <TNL/Allocators/Host.h>
+#include <TNL/Allocators/Cuda.h>
 #include <TNL/Containers/Algorithms/ArrayOperations.h>
 
 #include "gtest/gtest.h"
@@ -37,166 +39,147 @@ TYPED_TEST_SUITE( ArrayOperationsTest, ValueTypes );
 TYPED_TEST( ArrayOperationsTest, allocateMemory_host )
 {
    using ValueType = typename TestFixture::ValueType;
+   using Allocator = Allocators::Host< ValueType >;
 
-   ValueType* data;
-   ArrayOperations< Devices::Host >::allocateMemory( data, ARRAY_TEST_SIZE );
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
    ASSERT_NE( data, nullptr );
 
-   ArrayOperations< Devices::Host >::freeMemory( data );
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, setMemoryElement_host )
+TYPED_TEST( ArrayOperationsTest, setElement_host )
 {
    using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
+   using Allocator = Allocators::Host< ValueType >;
 
-   ValueType *data;
-   ArrayOperations< Devices::Host >::allocateMemory( data, size );
-   for( int i = 0; i < size; i++ ) {
-      ArrayOperations< Devices::Host >::setMemoryElement( data + i, (ValueType) i );
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
+   for( int i = 0; i < ARRAY_TEST_SIZE; i++ ) {
+      ArrayOperations< Devices::Host >::setElement( data + i, (ValueType) i );
       EXPECT_EQ( data[ i ], i );
-      EXPECT_EQ( ArrayOperations< Devices::Host >::getMemoryElement( data + i ), i );
+      EXPECT_EQ( ArrayOperations< Devices::Host >::getElement( data + i ), i );
    }
-   ArrayOperations< Devices::Host >::freeMemory( data );
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, setMemory_host )
+TYPED_TEST( ArrayOperationsTest, set_host )
 {
    using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
+   using Allocator = Allocators::Host< ValueType >;
 
-   ValueType *data;
-   ArrayOperations< Devices::Host >::allocateMemory( data, size );
-   ArrayOperations< Devices::Host >::setMemory( data, (ValueType) 13, size );
-   for( int i = 0; i < size; i ++ )
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( data, (ValueType) 13, ARRAY_TEST_SIZE );
+   for( int i = 0; i < ARRAY_TEST_SIZE; i ++ )
       EXPECT_EQ( data[ i ], 13 );
-   ArrayOperations< Devices::Host >::freeMemory( data );
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, copyMemory_host )
+TYPED_TEST( ArrayOperationsTest, copy_host )
 {
    using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
-
-   ValueType *data1, *data2;
-   ArrayOperations< Devices::Host >::allocateMemory( data1, size );
-   ArrayOperations< Devices::Host >::allocateMemory( data2, size );
-   ArrayOperations< Devices::Host >::setMemory( data1, (ValueType) 13, size );
-   ArrayOperations< Devices::Host >::copyMemory< ValueType, ValueType >( data2, data1, size );
-   for( int i = 0; i < size; i ++ )
+   using Allocator = Allocators::Host< ValueType >;
+
+   Allocator allocator;
+   ValueType* data1 = allocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* data2 = allocator.allocate( ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( data1, (ValueType) 13, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::copy< ValueType, ValueType >( data2, data1, ARRAY_TEST_SIZE );
+   for( int i = 0; i < ARRAY_TEST_SIZE; i ++ )
       EXPECT_EQ( data1[ i ], data2[ i ]);
-   ArrayOperations< Devices::Host >::freeMemory( data1 );
-   ArrayOperations< Devices::Host >::freeMemory( data2 );
+   allocator.deallocate( data1, ARRAY_TEST_SIZE );
+   allocator.deallocate( data2, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, copyMemoryWithConversion_host )
+TYPED_TEST( ArrayOperationsTest, copyWithConversion_host )
 {
-   using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
-
-   int *data1;
-   float *data2;
-   ArrayOperations< Devices::Host >::allocateMemory( data1, size );
-   ArrayOperations< Devices::Host >::allocateMemory( data2, size );
-   ArrayOperations< Devices::Host >::setMemory( data1, 13, size );
-   ArrayOperations< Devices::Host >::copyMemory< float, int >( data2, data1, size );
-   for( int i = 0; i < size; i ++ )
+   using Allocator1 = Allocators::Host< int >;
+   using Allocator2 = Allocators::Host< float >;
+
+   Allocator1 allocator1;
+   Allocator2 allocator2;
+   int* data1 = allocator1.allocate( ARRAY_TEST_SIZE );
+   float* data2 = allocator2.allocate( ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( data1, 13, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::copy< float, int >( data2, data1, ARRAY_TEST_SIZE );
+   for( int i = 0; i < ARRAY_TEST_SIZE; i ++ )
       EXPECT_EQ( data1[ i ], data2[ i ] );
-   ArrayOperations< Devices::Host >::freeMemory( data1 );
-   ArrayOperations< Devices::Host >::freeMemory( data2 );
+   allocator1.deallocate( data1, ARRAY_TEST_SIZE );
+   allocator2.deallocate( data2, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, compareMemory_host )
+TYPED_TEST( ArrayOperationsTest, compare_host )
 {
    using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
-
-   ValueType *data1, *data2;
-   ArrayOperations< Devices::Host >::allocateMemory( data1, size );
-   ArrayOperations< Devices::Host >::allocateMemory( data2, size );
-   ArrayOperations< Devices::Host >::setMemory( data1, (ValueType) 7, size );
-   ArrayOperations< Devices::Host >::setMemory( data2, (ValueType) 0, size );
-   EXPECT_FALSE( ( ArrayOperations< Devices::Host >::compareMemory< ValueType, ValueType >( data1, data2, size ) ) );
-   ArrayOperations< Devices::Host >::setMemory( data2, (ValueType) 7, size );
-   EXPECT_TRUE( ( ArrayOperations< Devices::Host >::compareMemory< ValueType, ValueType >( data1, data2, size ) ) );
-   ArrayOperations< Devices::Host >::freeMemory( data1 );
-   ArrayOperations< Devices::Host >::freeMemory( data2 );
+   using Allocator = Allocators::Host< ValueType >;
+
+   Allocator allocator;
+   ValueType* data1 = allocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* data2 = allocator.allocate( ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( data1, (ValueType) 7, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( data2, (ValueType) 0, ARRAY_TEST_SIZE );
+   EXPECT_FALSE( ( ArrayOperations< Devices::Host >::compare< ValueType, ValueType >( data1, data2, ARRAY_TEST_SIZE ) ) );
+   ArrayOperations< Devices::Host >::set( data2, (ValueType) 7, ARRAY_TEST_SIZE );
+   EXPECT_TRUE( ( ArrayOperations< Devices::Host >::compare< ValueType, ValueType >( data1, data2, ARRAY_TEST_SIZE ) ) );
+   allocator.deallocate( data1, ARRAY_TEST_SIZE );
+   allocator.deallocate( data2, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, compareMemoryWithConversion_host )
+TYPED_TEST( ArrayOperationsTest, compareWithConversion_host )
 {
-   const int size = ARRAY_TEST_SIZE;
-
-   int *data1;
-   float *data2;
-   ArrayOperations< Devices::Host >::allocateMemory( data1, size );
-   ArrayOperations< Devices::Host >::allocateMemory( data2, size );
-   ArrayOperations< Devices::Host >::setMemory( data1, 7, size );
-   ArrayOperations< Devices::Host >::setMemory( data2, (float) 0.0, size );
-   EXPECT_FALSE( ( ArrayOperations< Devices::Host >::compareMemory< int, float >( data1, data2, size ) ) );
-   ArrayOperations< Devices::Host >::setMemory( data2, (float) 7.0, size );
-   EXPECT_TRUE( ( ArrayOperations< Devices::Host >::compareMemory< int, float >( data1, data2, size ) ) );
-   ArrayOperations< Devices::Host >::freeMemory( data1 );
-   ArrayOperations< Devices::Host >::freeMemory( data2 );
+   using Allocator1 = Allocators::Host< int >;
+   using Allocator2 = Allocators::Host< float >;
+
+   Allocator1 allocator1;
+   Allocator2 allocator2;
+   int* data1 = allocator1.allocate( ARRAY_TEST_SIZE );
+   float* data2 = allocator2.allocate( ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( data1, 7, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( data2, (float) 0.0, ARRAY_TEST_SIZE );
+   EXPECT_FALSE( ( ArrayOperations< Devices::Host >::compare< int, float >( data1, data2, ARRAY_TEST_SIZE ) ) );
+   ArrayOperations< Devices::Host >::set( data2, (float) 7.0, ARRAY_TEST_SIZE );
+   EXPECT_TRUE( ( ArrayOperations< Devices::Host >::compare< int, float >( data1, data2, ARRAY_TEST_SIZE ) ) );
+   allocator1.deallocate( data1, ARRAY_TEST_SIZE );
+   allocator2.deallocate( data2, ARRAY_TEST_SIZE );
 }
 
 TYPED_TEST( ArrayOperationsTest, containsValue_host )
 {
-   const int size = ARRAY_TEST_SIZE;
+   using ValueType = typename TestFixture::ValueType;
+   using Allocator = Allocators::Host< ValueType >;
+
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
 
-   int *data1;
-   float *data2;
-   ArrayOperations< Devices::Host >::allocateMemory( data1, size );
-   ArrayOperations< Devices::Host >::allocateMemory( data2, size );
    for( int i = 0; i < ARRAY_TEST_SIZE; i++ )
-   {
-      data1[ i ] = i % 10;
-      data2[ i ] = ( float ) ( i % 10 );
-   }
+      data[ i ] = i % 10;
    for( int i = 0; i < 10; i++ )
-   {
-      EXPECT_TRUE( ( ArrayOperations< Devices::Host >::containsValue( data1, size, i ) ) );
-      EXPECT_TRUE( ( ArrayOperations< Devices::Host >::containsValue( data2, size, ( float ) i ) ) );
-   }
+      EXPECT_TRUE( ( ArrayOperations< Devices::Host >::containsValue( data, ARRAY_TEST_SIZE, (ValueType) i ) ) );
    for( int i = 10; i < 20; i++ )
-   {
-      EXPECT_FALSE( ( ArrayOperations< Devices::Host >::containsValue( data1, size, i ) ) );
-      EXPECT_FALSE( ( ArrayOperations< Devices::Host >::containsValue( data2, size, ( float ) i ) ) );
-   }
-   ArrayOperations< Devices::Host >::freeMemory( data1 );
-   ArrayOperations< Devices::Host >::freeMemory( data2 );
+      EXPECT_FALSE( ( ArrayOperations< Devices::Host >::containsValue( data, ARRAY_TEST_SIZE, (ValueType) i ) ) );
+
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
 }
 
 TYPED_TEST( ArrayOperationsTest, containsOnlyValue_host )
 {
-   const int size = ARRAY_TEST_SIZE;
+   using ValueType = typename TestFixture::ValueType;
+   using Allocator = Allocators::Host< ValueType >;
+
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
 
-   int *data1;
-   float *data2;
-   ArrayOperations< Devices::Host >::allocateMemory( data1, size );
-   ArrayOperations< Devices::Host >::allocateMemory( data2, size );
    for( int i = 0; i < ARRAY_TEST_SIZE; i++ )
-   {
-      data1[ i ] = i % 10;
-      data2[ i ] = ( float ) ( i % 10 );
-   }
+      data[ i ] = i % 10;
    for( int i = 0; i < 20; i++ )
-   {
-      EXPECT_FALSE( ( ArrayOperations< Devices::Host >::containsOnlyValue( data1, size, i ) ) );
-      EXPECT_FALSE( ( ArrayOperations< Devices::Host >::containsOnlyValue( data2, size, ( float ) i ) ) );
-   }
+      EXPECT_FALSE( ( ArrayOperations< Devices::Host >::containsOnlyValue( data, ARRAY_TEST_SIZE, (ValueType) i ) ) );
 
    for( int i = 0; i < ARRAY_TEST_SIZE; i++ )
-   {
-      data1[ i ] = 10;
-      data2[ i ] = ( float ) 10;
-   }
-
-   EXPECT_TRUE( ( ArrayOperations< Devices::Host >::containsOnlyValue( data1, size, 10 ) ) );
-   EXPECT_TRUE( ( ArrayOperations< Devices::Host >::containsOnlyValue( data2, size, ( float ) 10 ) ) );
+      data[ i ] = 10;
+   EXPECT_TRUE( ( ArrayOperations< Devices::Host >::containsOnlyValue( data, ARRAY_TEST_SIZE, (ValueType) 10 ) ) );
 
-   ArrayOperations< Devices::Host >::freeMemory( data1 );
-   ArrayOperations< Devices::Host >::freeMemory( data2 );
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
 }
 
 
@@ -204,239 +187,223 @@ TYPED_TEST( ArrayOperationsTest, containsOnlyValue_host )
 TYPED_TEST( ArrayOperationsTest, allocateMemory_cuda )
 {
    using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
+   using Allocator = Allocators::Cuda< ValueType >;
 
-   ValueType* data;
-   ArrayOperations< Devices::Cuda >::allocateMemory( data, size );
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
    ASSERT_NO_THROW( TNL_CHECK_CUDA_DEVICE );
    ASSERT_NE( data, nullptr );
 
-   ArrayOperations< Devices::Cuda >::freeMemory( data );
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
    ASSERT_NO_THROW( TNL_CHECK_CUDA_DEVICE );
 }
 
-TYPED_TEST( ArrayOperationsTest, setMemoryElement_cuda )
+TYPED_TEST( ArrayOperationsTest, setElement_cuda )
 {
    using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
+   using Allocator = Allocators::Cuda< ValueType >;
 
-   ValueType* data;
-   ArrayOperations< Devices::Cuda >::allocateMemory( data, size );
+   Allocator allocator;
+   ValueType* data = allocator.allocate( ARRAY_TEST_SIZE );
    ASSERT_NO_THROW( TNL_CHECK_CUDA_DEVICE );
 
-   for( int i = 0; i < size; i++ )
-      ArrayOperations< Devices::Cuda >::setMemoryElement( &data[ i ], (ValueType) i );
+   for( int i = 0; i < ARRAY_TEST_SIZE; i++ )
+      ArrayOperations< Devices::Cuda >::setElement( &data[ i ], (ValueType) i );
 
-   for( int i = 0; i < size; i++ )
+   for( int i = 0; i < ARRAY_TEST_SIZE; i++ )
    {
       ValueType d;
       ASSERT_EQ( cudaMemcpy( &d, &data[ i ], sizeof( ValueType ), cudaMemcpyDeviceToHost ), cudaSuccess );
       EXPECT_EQ( d, i );
-      EXPECT_EQ( ArrayOperations< Devices::Cuda >::getMemoryElement( &data[ i ] ), i );
+      EXPECT_EQ( ArrayOperations< Devices::Cuda >::getElement( &data[ i ] ), i );
    }
 
-   ArrayOperations< Devices::Cuda >::freeMemory( data );
+   allocator.deallocate( data, ARRAY_TEST_SIZE );
    ASSERT_NO_THROW( TNL_CHECK_CUDA_DEVICE );
 }
 
-TYPED_TEST( ArrayOperationsTest, setMemory_cuda )
+TYPED_TEST( ArrayOperationsTest, set_cuda )
 {
    using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
-
-   ValueType *hostData, *deviceData;
-   ArrayOperations< Devices::Host >::allocateMemory( hostData, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( deviceData, size );
-   ArrayOperations< Devices::Host >::setMemory( hostData, (ValueType) 0, size );
-   ArrayOperations< Devices::Cuda >::setMemory( deviceData, (ValueType) 13, size );
+   using HostAllocator = Allocators::Host< ValueType >;
+   using CudaAllocator = Allocators::Cuda< ValueType >;
+
+   HostAllocator hostAllocator;
+   CudaAllocator cudaAllocator;
+   ValueType* hostData = hostAllocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* deviceData = cudaAllocator.allocate( ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( hostData, (ValueType) 0, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda >::set( deviceData, (ValueType) 13, ARRAY_TEST_SIZE );
    ASSERT_NO_THROW( TNL_CHECK_CUDA_DEVICE );
-   ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory< ValueType, ValueType >( hostData, deviceData, size );
+   ArrayOperations< Devices::Host, Devices::Cuda >::copy< ValueType, ValueType >( hostData, deviceData, ARRAY_TEST_SIZE );
    ASSERT_NO_THROW( TNL_CHECK_CUDA_DEVICE );
-   for( int i = 0; i < size; i++ )
+   for( int i = 0; i < ARRAY_TEST_SIZE; i++ )
       EXPECT_EQ( hostData[ i ], 13 );
-   ArrayOperations< Devices::Host >::freeMemory( hostData );
-   ArrayOperations< Devices::Cuda >::freeMemory( deviceData );
+   hostAllocator.deallocate( hostData, ARRAY_TEST_SIZE );
+   cudaAllocator.deallocate( deviceData, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, copyMemory_cuda )
+TYPED_TEST( ArrayOperationsTest, copy_cuda )
 {
    using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
-
-   ValueType *hostData, *hostData2, *deviceData, *deviceData2;
-   ArrayOperations< Devices::Host >::allocateMemory( hostData, size );
-   ArrayOperations< Devices::Host >::allocateMemory( hostData2, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( deviceData, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( deviceData2, size );
-   ArrayOperations< Devices::Host >::setMemory( hostData, (ValueType) 13, size );
-   ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory< ValueType >( deviceData, hostData, size );
-   ArrayOperations< Devices::Cuda >::copyMemory< ValueType, ValueType >( deviceData2, deviceData, size );
-   ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory< ValueType, ValueType >( hostData2, deviceData2, size );
-   EXPECT_TRUE( ( ArrayOperations< Devices::Host >::compareMemory< ValueType, ValueType >( hostData, hostData2, size) ) );
-   ArrayOperations< Devices::Host >::freeMemory( hostData );
-   ArrayOperations< Devices::Host >::freeMemory( hostData2 );
-   ArrayOperations< Devices::Cuda >::freeMemory( deviceData );
-   ArrayOperations< Devices::Cuda >::freeMemory( deviceData2 );
+   using HostAllocator = Allocators::Host< ValueType >;
+   using CudaAllocator = Allocators::Cuda< ValueType >;
+
+   HostAllocator hostAllocator;
+   CudaAllocator cudaAllocator;
+   ValueType* hostData = hostAllocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* hostData2 = hostAllocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* deviceData = cudaAllocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* deviceData2 = cudaAllocator.allocate( ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( hostData, (ValueType) 13, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda, Devices::Host >::copy< ValueType >( deviceData, hostData, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda >::copy< ValueType, ValueType >( deviceData2, deviceData, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host, Devices::Cuda >::copy< ValueType, ValueType >( hostData2, deviceData2, ARRAY_TEST_SIZE );
+   EXPECT_TRUE( ( ArrayOperations< Devices::Host >::compare< ValueType, ValueType >( hostData, hostData2, ARRAY_TEST_SIZE) ) );
+   hostAllocator.deallocate( hostData, ARRAY_TEST_SIZE );
+   hostAllocator.deallocate( hostData2, ARRAY_TEST_SIZE );
+   cudaAllocator.deallocate( deviceData, ARRAY_TEST_SIZE );
+   cudaAllocator.deallocate( deviceData2, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, copyMemoryWithConversions_cuda )
+TYPED_TEST( ArrayOperationsTest, copyWithConversions_cuda )
 {
-   const int size = ARRAY_TEST_SIZE;
-
-   int *hostData;
-   double *hostData2;
-   long *deviceData;
-   float *deviceData2;
-   ArrayOperations< Devices::Host >::allocateMemory( hostData, size );
-   ArrayOperations< Devices::Host >::allocateMemory( hostData2, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( deviceData, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( deviceData2, size );
-   ArrayOperations< Devices::Host >::setMemory( hostData, 13, size );
-   ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory< long, int >( deviceData, hostData, size );
-   ArrayOperations< Devices::Cuda >::copyMemory< float, long >( deviceData2, deviceData, size );
-   ArrayOperations< Devices::Host, Devices::Cuda >::copyMemory< double, float >( hostData2, deviceData2, size );
-   for( int i = 0; i < size; i ++ )
+   using HostAllocator1 = Allocators::Host< int >;
+   using HostAllocator2 = Allocators::Host< double >;
+   using CudaAllocator1 = Allocators::Cuda< long >;
+   using CudaAllocator2 = Allocators::Cuda< float >;
+
+   HostAllocator1 hostAllocator1;
+   HostAllocator2 hostAllocator2;
+   CudaAllocator1 cudaAllocator1;
+   CudaAllocator2 cudaAllocator2;
+   int* hostData = hostAllocator1.allocate( ARRAY_TEST_SIZE );
+   double* hostData2 = hostAllocator2.allocate( ARRAY_TEST_SIZE );
+   long* deviceData = cudaAllocator1.allocate( ARRAY_TEST_SIZE );
+   float* deviceData2 = cudaAllocator2.allocate( ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host >::set( hostData, 13, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda, Devices::Host >::copy< long, int >( deviceData, hostData, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda >::copy< float, long >( deviceData2, deviceData, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Host, Devices::Cuda >::copy< double, float >( hostData2, deviceData2, ARRAY_TEST_SIZE );
+   for( int i = 0; i < ARRAY_TEST_SIZE; i ++ )
       EXPECT_EQ( hostData[ i ], hostData2[ i ] );
-   ArrayOperations< Devices::Host >::freeMemory( hostData );
-   ArrayOperations< Devices::Host >::freeMemory( hostData2 );
-   ArrayOperations< Devices::Cuda >::freeMemory( deviceData );
-   ArrayOperations< Devices::Cuda >::freeMemory( deviceData2 );
+   hostAllocator1.deallocate( hostData, ARRAY_TEST_SIZE );
+   hostAllocator2.deallocate( hostData2, ARRAY_TEST_SIZE );
+   cudaAllocator1.deallocate( deviceData, ARRAY_TEST_SIZE );
+   cudaAllocator2.deallocate( deviceData2, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, compareMemory_cuda )
+TYPED_TEST( ArrayOperationsTest, compare_cuda )
 {
    using ValueType = typename TestFixture::ValueType;
-   const int size = ARRAY_TEST_SIZE;
-
-   ValueType *hostData, *deviceData, *deviceData2;
-   ArrayOperations< Devices::Host >::allocateMemory( hostData, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( deviceData, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( deviceData2, size );
-
-   ArrayOperations< Devices::Host >::setMemory( hostData, (ValueType) 7, size );
-   ArrayOperations< Devices::Cuda >::setMemory( deviceData, (ValueType) 8, size );
-   ArrayOperations< Devices::Cuda >::setMemory( deviceData2, (ValueType) 9, size );
-   EXPECT_FALSE(( ArrayOperations< Devices::Host, Devices::Cuda >::compareMemory< ValueType, ValueType >( hostData, deviceData, size ) ));
-   EXPECT_FALSE(( ArrayOperations< Devices::Cuda, Devices::Host >::compareMemory< ValueType, ValueType >( deviceData, hostData, size ) ));
-   EXPECT_FALSE(( ArrayOperations< Devices::Cuda >::compareMemory< ValueType, ValueType >( deviceData, deviceData2, size ) ));
-
-   ArrayOperations< Devices::Cuda >::setMemory( deviceData, (ValueType) 7, size );
-   ArrayOperations< Devices::Cuda >::setMemory( deviceData2, (ValueType) 7, size );
-   EXPECT_TRUE(( ArrayOperations< Devices::Host, Devices::Cuda >::compareMemory< ValueType, ValueType >( hostData, deviceData, size ) ));
-   EXPECT_TRUE(( ArrayOperations< Devices::Cuda, Devices::Host >::compareMemory< ValueType, ValueType >( deviceData, hostData, size ) ));
-   EXPECT_TRUE(( ArrayOperations< Devices::Cuda >::compareMemory< ValueType, ValueType >( deviceData, deviceData2, size ) ));
-
-   ArrayOperations< Devices::Host >::freeMemory( hostData );
-   ArrayOperations< Devices::Cuda >::freeMemory( deviceData );
-   ArrayOperations< Devices::Cuda >::freeMemory( deviceData2 );
+   using HostAllocator = Allocators::Host< ValueType >;
+   using CudaAllocator = Allocators::Cuda< ValueType >;
+
+   HostAllocator hostAllocator;
+   CudaAllocator cudaAllocator;
+   ValueType* hostData = hostAllocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* deviceData = cudaAllocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* deviceData2 = cudaAllocator.allocate( ARRAY_TEST_SIZE );
+
+   ArrayOperations< Devices::Host >::set( hostData, (ValueType) 7, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda >::set( deviceData, (ValueType) 8, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda >::set( deviceData2, (ValueType) 9, ARRAY_TEST_SIZE );
+   EXPECT_FALSE(( ArrayOperations< Devices::Host, Devices::Cuda >::compare< ValueType, ValueType >( hostData, deviceData, ARRAY_TEST_SIZE ) ));
+   EXPECT_FALSE(( ArrayOperations< Devices::Cuda, Devices::Host >::compare< ValueType, ValueType >( deviceData, hostData, ARRAY_TEST_SIZE ) ));
+   EXPECT_FALSE(( ArrayOperations< Devices::Cuda >::compare< ValueType, ValueType >( deviceData, deviceData2, ARRAY_TEST_SIZE ) ));
+
+   ArrayOperations< Devices::Cuda >::set( deviceData, (ValueType) 7, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda >::set( deviceData2, (ValueType) 7, ARRAY_TEST_SIZE );
+   EXPECT_TRUE(( ArrayOperations< Devices::Host, Devices::Cuda >::compare< ValueType, ValueType >( hostData, deviceData, ARRAY_TEST_SIZE ) ));
+   EXPECT_TRUE(( ArrayOperations< Devices::Cuda, Devices::Host >::compare< ValueType, ValueType >( deviceData, hostData, ARRAY_TEST_SIZE ) ));
+   EXPECT_TRUE(( ArrayOperations< Devices::Cuda >::compare< ValueType, ValueType >( deviceData, deviceData2, ARRAY_TEST_SIZE ) ));
+
+   hostAllocator.deallocate( hostData, ARRAY_TEST_SIZE );
+   cudaAllocator.deallocate( deviceData, ARRAY_TEST_SIZE );
+   cudaAllocator.deallocate( deviceData2, ARRAY_TEST_SIZE );
 }
 
-TYPED_TEST( ArrayOperationsTest, compareMemoryWithConversions_cuda )
+TYPED_TEST( ArrayOperationsTest, compareWithConversions_cuda )
 {
-   const int size = ARRAY_TEST_SIZE;
-
-   int *hostData;
-   float *deviceData;
-   double *deviceData2;
-   ArrayOperations< Devices::Host >::allocateMemory( hostData, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( deviceData, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( deviceData2, size );
-
-   ArrayOperations< Devices::Host >::setMemory( hostData, 7, size );
-   ArrayOperations< Devices::Cuda >::setMemory( deviceData, (float) 8, size );
-   ArrayOperations< Devices::Cuda >::setMemory( deviceData2, (double) 9, size );
-   EXPECT_FALSE(( ArrayOperations< Devices::Host, Devices::Cuda >::compareMemory< int, float >( hostData, deviceData, size ) ));
-   EXPECT_FALSE(( ArrayOperations< Devices::Cuda, Devices::Host >::compareMemory< float, int >( deviceData, hostData, size ) ));
-   EXPECT_FALSE(( ArrayOperations< Devices::Cuda >::compareMemory< float, double >( deviceData, deviceData2, size ) ));
-
-   ArrayOperations< Devices::Cuda >::setMemory( deviceData, (float) 7, size );
-   ArrayOperations< Devices::Cuda >::setMemory( deviceData2, (double) 7, size );
-   EXPECT_TRUE(( ArrayOperations< Devices::Host, Devices::Cuda >::compareMemory< int, float >( hostData, deviceData, size ) ));
-   EXPECT_TRUE(( ArrayOperations< Devices::Cuda, Devices::Host >::compareMemory< float, int >( deviceData, hostData, size ) ));
-   EXPECT_TRUE(( ArrayOperations< Devices::Cuda >::compareMemory< float, double >( deviceData, deviceData2, size ) ));
-
-   ArrayOperations< Devices::Host >::freeMemory( hostData );
-   ArrayOperations< Devices::Cuda >::freeMemory( deviceData );
-   ArrayOperations< Devices::Cuda >::freeMemory( deviceData2 );
+   using HostAllocator = Allocators::Host< int >;
+   using CudaAllocator1 = Allocators::Cuda< float >;
+   using CudaAllocator2 = Allocators::Cuda< double >;
+
+   HostAllocator hostAllocator;
+   CudaAllocator1 cudaAllocator1;
+   CudaAllocator2 cudaAllocator2;
+   int* hostData = hostAllocator.allocate( ARRAY_TEST_SIZE );
+   float* deviceData = cudaAllocator1.allocate( ARRAY_TEST_SIZE );
+   double* deviceData2 = cudaAllocator2.allocate( ARRAY_TEST_SIZE );
+
+   ArrayOperations< Devices::Host >::set( hostData, 7, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda >::set( deviceData, (float) 8, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda >::set( deviceData2, (double) 9, ARRAY_TEST_SIZE );
+   EXPECT_FALSE(( ArrayOperations< Devices::Host, Devices::Cuda >::compare< int, float >( hostData, deviceData, ARRAY_TEST_SIZE ) ));
+   EXPECT_FALSE(( ArrayOperations< Devices::Cuda, Devices::Host >::compare< float, int >( deviceData, hostData, ARRAY_TEST_SIZE ) ));
+   EXPECT_FALSE(( ArrayOperations< Devices::Cuda >::compare< float, double >( deviceData, deviceData2, ARRAY_TEST_SIZE ) ));
+
+   ArrayOperations< Devices::Cuda >::set( deviceData, (float) 7, ARRAY_TEST_SIZE );
+   ArrayOperations< Devices::Cuda >::set( deviceData2, (double) 7, ARRAY_TEST_SIZE );
+   EXPECT_TRUE(( ArrayOperations< Devices::Host, Devices::Cuda >::compare< int, float >( hostData, deviceData, ARRAY_TEST_SIZE ) ));
+   EXPECT_TRUE(( ArrayOperations< Devices::Cuda, Devices::Host >::compare< float, int >( deviceData, hostData, ARRAY_TEST_SIZE ) ));
+   EXPECT_TRUE(( ArrayOperations< Devices::Cuda >::compare< float, double >( deviceData, deviceData2, ARRAY_TEST_SIZE ) ));
+
+   hostAllocator.deallocate( hostData, ARRAY_TEST_SIZE );
+   cudaAllocator1.deallocate( deviceData, ARRAY_TEST_SIZE );
+   cudaAllocator2.deallocate( deviceData2, ARRAY_TEST_SIZE );
 }
 
 TYPED_TEST( ArrayOperationsTest, containsValue_cuda )
 {
-   const int size = ARRAY_TEST_SIZE;
+   using ValueType = typename TestFixture::ValueType;
+   using HostAllocator = Allocators::Host< ValueType >;
+   using CudaAllocator = Allocators::Cuda< ValueType >;
 
-   int *data1_host, *data1_cuda;
-   float *data2_host, *data2_cuda;
-   ArrayOperations< Devices::Host >::allocateMemory( data1_host, size );
-   ArrayOperations< Devices::Host >::allocateMemory( data2_host, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( data1_cuda, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( data2_cuda, size );
+   HostAllocator hostAllocator;
+   CudaAllocator cudaAllocator;
+   ValueType* hostData = hostAllocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* deviceData = cudaAllocator.allocate( ARRAY_TEST_SIZE );
 
    for( int i = 0; i < ARRAY_TEST_SIZE; i++ )
-   {
-      data1_host[ i ] = i % 10;
-      data2_host[ i ] = ( float ) ( i % 10 );
-   }
-
-   ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory( data1_cuda, data1_host, size );
-   ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory( data2_cuda, data2_host, size );
+      hostData[ i ] = i % 10;
+   ArrayOperations< Devices::Cuda, Devices::Host >::copy( deviceData, hostData, ARRAY_TEST_SIZE );
 
    for( int i = 0; i < 10; i++ )
-   {
-      EXPECT_TRUE( ( ArrayOperations< Devices::Cuda >::containsValue( data1_cuda, size, i ) ) );
-      EXPECT_TRUE( ( ArrayOperations< Devices::Cuda >::containsValue( data2_cuda, size, ( float ) i ) ) );
-   }
+      EXPECT_TRUE( ( ArrayOperations< Devices::Cuda >::containsValue( deviceData, ARRAY_TEST_SIZE, (ValueType) i ) ) );
    for( int i = 10; i < 20; i++ )
-   {
-      EXPECT_FALSE( ( ArrayOperations< Devices::Cuda >::containsValue( data1_cuda, size, i ) ) );
-      EXPECT_FALSE( ( ArrayOperations< Devices::Cuda >::containsValue( data2_cuda, size, ( float ) i ) ) );
-   }
+      EXPECT_FALSE( ( ArrayOperations< Devices::Cuda >::containsValue( deviceData, ARRAY_TEST_SIZE, (ValueType) i ) ) );
 
-   ArrayOperations< Devices::Host >::freeMemory( data1_host );
-   ArrayOperations< Devices::Host >::freeMemory( data2_host );
-   ArrayOperations< Devices::Cuda >::freeMemory( data1_cuda );
-   ArrayOperations< Devices::Cuda >::freeMemory( data2_cuda );
+   hostAllocator.deallocate( hostData, ARRAY_TEST_SIZE );
+   cudaAllocator.deallocate( deviceData, ARRAY_TEST_SIZE );
 }
 
 TYPED_TEST( ArrayOperationsTest, containsOnlyValue_cuda )
 {
-   const int size = ARRAY_TEST_SIZE;
+   using ValueType = typename TestFixture::ValueType;
+   using HostAllocator = Allocators::Host< ValueType >;
+   using CudaAllocator = Allocators::Cuda< ValueType >;
 
-   int *data1_host, *data1_cuda;
-   float *data2_host, *data2_cuda;
-   ArrayOperations< Devices::Host >::allocateMemory( data1_host, size );
-   ArrayOperations< Devices::Host >::allocateMemory( data2_host, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( data1_cuda, size );
-   ArrayOperations< Devices::Cuda >::allocateMemory( data2_cuda, size );
+   HostAllocator hostAllocator;
+   CudaAllocator cudaAllocator;
+   ValueType* hostData = hostAllocator.allocate( ARRAY_TEST_SIZE );
+   ValueType* deviceData = cudaAllocator.allocate( ARRAY_TEST_SIZE );
 
    for( int i = 0; i < ARRAY_TEST_SIZE; i++ )
-   {
-      data1_host[ i ] = i % 10;
-      data2_host[ i ] = ( float ) ( i % 10 );
-   }
-   ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory( data1_cuda, data1_host, size );
-   ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory( data2_cuda, data2_host, size );
+      hostData[ i ] = i % 10;
+   ArrayOperations< Devices::Cuda, Devices::Host >::copy( deviceData, hostData, ARRAY_TEST_SIZE );
 
    for( int i = 0; i < 20; i++ )
-   {
-      EXPECT_FALSE( ( ArrayOperations< Devices::Cuda >::containsOnlyValue( data1_cuda, size, i ) ) );
-      EXPECT_FALSE( ( ArrayOperations< Devices::Cuda >::containsOnlyValue( data2_cuda, size, ( float ) i ) ) );
-   }
+      EXPECT_FALSE( ( ArrayOperations< Devices::Cuda >::containsOnlyValue( deviceData, ARRAY_TEST_SIZE, (ValueType) i ) ) );
 
    for( int i = 0; i < ARRAY_TEST_SIZE; i++ )
-   {
-      data1_host[ i ] = 10;
-      data2_host[ i ] = ( float ) 10;
-   }
-   ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory( data1_cuda, data1_host, size );
-   ArrayOperations< Devices::Cuda, Devices::Host >::copyMemory( data2_cuda, data2_host, size );
+      hostData[ i ] = 10;
+   ArrayOperations< Devices::Cuda, Devices::Host >::copy( deviceData, hostData, ARRAY_TEST_SIZE );
 
-   EXPECT_TRUE( ( ArrayOperations< Devices::Cuda >::containsOnlyValue( data1_cuda, size, 10 ) ) );
-   EXPECT_TRUE( ( ArrayOperations< Devices::Cuda >::containsOnlyValue( data2_cuda, size, ( float ) 10 ) ) );
+   EXPECT_TRUE( ( ArrayOperations< Devices::Cuda >::containsOnlyValue( deviceData, ARRAY_TEST_SIZE, (ValueType) 10 ) ) );
 
-   ArrayOperations< Devices::Host >::freeMemory( data1_host );
-   ArrayOperations< Devices::Host >::freeMemory( data2_host );
-   ArrayOperations< Devices::Cuda >::freeMemory( data1_cuda );
-   ArrayOperations< Devices::Cuda >::freeMemory( data2_cuda );
+   hostAllocator.deallocate( hostData, ARRAY_TEST_SIZE );
+   cudaAllocator.deallocate( deviceData, ARRAY_TEST_SIZE );
 }
 #endif // HAVE_CUDA
 #endif // HAVE_GTEST
diff --git a/src/UnitTests/Containers/ArrayTest.h b/src/UnitTests/Containers/ArrayTest.h
index fe0e538b50e9f621f49b051eb6bc010fd7e55eb6..9960e55f337717ab29176f795982f99e2c3d4b7e 100644
--- a/src/UnitTests/Containers/ArrayTest.h
+++ b/src/UnitTests/Containers/ArrayTest.h
@@ -145,7 +145,6 @@ TYPED_TEST_SUITE( ArrayTest, ArrayTypes );
 TYPED_TEST( ArrayTest, constructors )
 {
    using ArrayType = typename TestFixture::ArrayType;
-   //using ArrayType = Array< float, Devices::Host, long >;
 
    ArrayType u;
    EXPECT_EQ( u.getSize(), 0 );
@@ -178,13 +177,61 @@ TYPED_TEST( ArrayTest, constructors )
    EXPECT_EQ( a2.getElement( 2 ), 6 );
 
    std::vector< int > q = { 7, 8, 9 };
-
    ArrayType a3( q );
    EXPECT_EQ( a3.getElement( 0 ), 7 );
    EXPECT_EQ( a3.getElement( 1 ), 8 );
    EXPECT_EQ( a3.getElement( 2 ), 9 );
 }
 
+TYPED_TEST( ArrayTest, constructorsWithAllocators )
+{
+   using ArrayType = typename TestFixture::ArrayType;
+   using AllocatorType = typename ArrayType::AllocatorType;
+
+   AllocatorType allocator;
+
+   ArrayType u( allocator );
+   EXPECT_EQ( u.getAllocator(), allocator );
+   u.setSize( 10 );
+   EXPECT_EQ( u.getSize(), 10 );
+
+   ArrayType v( 10, allocator );
+   EXPECT_EQ( v.getSize(), 10 );
+   EXPECT_EQ( v.getAllocator(), allocator );
+   v.reset();
+   EXPECT_EQ( v.getAllocator(), allocator );
+
+   // deep copy
+   ArrayType w( u, allocator );
+   EXPECT_NE( w.getData(), u.getData() );
+   EXPECT_EQ( w.getSize(), u.getSize() );
+   for( int i = 0; i < 10; i++ )
+      EXPECT_EQ( u.getElement( i ), w.getElement( i ) );
+   EXPECT_EQ( w.getAllocator(), allocator );
+   u.reset();
+   EXPECT_EQ( w.getSize(), 10 );
+
+   ArrayType a1( { 1, 2, 3 }, allocator );
+   EXPECT_EQ( a1.getElement( 0 ), 1 );
+   EXPECT_EQ( a1.getElement( 1 ), 2 );
+   EXPECT_EQ( a1.getElement( 2 ), 3 );
+   EXPECT_EQ( a1.getAllocator(), allocator );
+
+   std::list< int > l = { 4, 5, 6 };
+   ArrayType a2( l, allocator );
+   EXPECT_EQ( a2.getElement( 0 ), 4 );
+   EXPECT_EQ( a2.getElement( 1 ), 5 );
+   EXPECT_EQ( a2.getElement( 2 ), 6 );
+   EXPECT_EQ( a2.getAllocator(), allocator );
+
+   std::vector< int > q = { 7, 8, 9 };
+   ArrayType a3( q, allocator );
+   EXPECT_EQ( a3.getElement( 0 ), 7 );
+   EXPECT_EQ( a3.getElement( 1 ), 8 );
+   EXPECT_EQ( a3.getElement( 2 ), 9 );
+   EXPECT_EQ( a3.getAllocator(), allocator );
+}
+
 TYPED_TEST( ArrayTest, setSize )
 {
    using ArrayType = typename TestFixture::ArrayType;
@@ -519,4 +566,4 @@ TYPED_TEST( ArrayTest, LoadViaView )
 #endif // HAVE_GTEST
 
 
-#include "../main.h"
\ No newline at end of file
+#include "../main.h"