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 ], ©_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"