diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 19fba55896cf254ba6de5d92d4d35b9976352aef..a1a9e8274506e0559a3d62839cef04d8afd4905f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,11 +33,6 @@ stages: .build_template_def: &build_template stage: build script: - # set MPI compiler wrapper - - if [[ ${WITH_MPI} == "yes" ]]; then - export CXX=mpicxx; - export CC=mpicc; - fi # all cores including hyperthreading # - export NUM_CORES=$(grep "core id" /proc/cpuinfo | wc -l) # # all pyhsical cores @@ -53,6 +48,7 @@ stages: -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=$(pwd)/${BUILD_TYPE}_install_prefix -DWITH_OPENMP=${WITH_OPENMP} + -DWITH_MPI=${WITH_MPI} -DWITH_CUDA=${WITH_CUDA} -DWITH_CUDA_ARCH=${WITH_CUDA_ARCH} -DWITH_MIC=${WITH_MIC} diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ef24e584afce4c7761c45056198d730f3a6a420..c4ea91fb48d143d8e1ad1bc35bc1cdcde531117f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ option(WITH_MIC "Build with MIC support" OFF) option(WITH_CUDA "Build with CUDA support" ON) set(WITH_CUDA_ARCH "auto" CACHE STRING "Build for these CUDA architectures") option(WITH_OPENMP "Build with OpenMP support" ON) +option(WITH_MPI "Build with MPI support" ON) option(WITH_GMP "Build with GMP support" OFF) option(WITH_TESTS "Build tests" ON) option(WITH_PROFILING "Enable code profiling compiler flags" OFF ) @@ -39,10 +40,11 @@ set( TNL_TARGET_DATA_DIRECTORY "share/TNL" ) # the cmake directory in the TNL repository set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ) -# Note that in cmake 3.10 the FindOpenMP module is broken - it does not work when +# Note that in cmake 3.10 the FindOpenMP and FindMPI modules are broken - they do not work when # CMAKE_EXECUTABLE_SUFFIX is not empty, see https://www.mail-archive.com/cmake@cmake.org/msg56886.html -# Hence, we find OpenMP before setting CMAKE_EXECUTABLE_SUFFIX. +# Hence, we find OpenMP and MPI before setting CMAKE_EXECUTABLE_SUFFIX. find_package( OpenMP ) +find_package( MPI ) #### # Settings for debug/release version @@ -127,27 +129,40 @@ if( DEFINED ENV{CI_JOB_NAME} OR ${CMAKE_GENERATOR} STREQUAL "Ninja" ) endif() endif() -##### -# Check for MPI -- poznej podle vraperu compileru -- da se testovat preklad bez MPI +# gtest has to be built before we add the MPI flags +if( ${WITH_TESTS} ) + enable_testing() + + # build gtest libs + include( BuildGtest ) + + if( ${WITH_COVERAGE} AND CMAKE_BUILD_TYPE STREQUAL "Debug" ) + # enable code coverage reports + include( UseCodeCoverage ) + endif() +endif() + +#### +# Check for OpenMP # -get_filename_component( CXX_COMPILER_NAME ${CMAKE_CXX_COMPILER} NAME ) -if( ${CXX_COMPILER_NAME} STREQUAL "mpicxx" ) - message( "MPI compiler detected." ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_MPI" ) - set( CUDA_HOST_COMPILER "mpicxx" ) - set( BUILD_MPI ON ) +if( OPENMP_FOUND AND ${WITH_OPENMP} ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_OPENMP ${OpenMP_CXX_FLAGS}" ) endif() #### -# Check for MPI -- not working +# Check for MPI # -#find_package( MPI ) -#if( MPI_CXX_FOUND ) - # set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_MPI" ) - # message( "MPI headers found -- ${MPI_CXX_INCLUDE_PATH}") - # message( "MPI link flags -- ${MPI_CXX_LINK_FLAGS}") - # message( "MPI libraries-- ${MPI_CXX_LIBRARIES}") -#endif() +if( MPI_CXX_FOUND AND ${WITH_MPI} ) + set( BUILD_MPI TRUE) + # add the appropriate flags to all targets (will be hidden from the CMAKE_CXX_* variables) + include_directories( ${MPI_CXX_INCLUDE_DIRS} ) + add_compile_options( ${MPI_CXX_COMPILE_OPTIONS} ) + add_compile_definitions( ${MPI_CXX_COMPILE_DEFINITIONS} ) + add_link_options( "SHELL:${MPI_CXX_LINK_FLAGS}" ) + link_libraries( ${MPI_CXX_LIBRARIES} ) + # enable MPI in TNL + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_MPI" ) +endif() ##### # Check for CUDA @@ -243,13 +258,6 @@ if( ${WITH_CUDA} ) endif() -#### -# Check for OpenMP -# -if( OPENMP_FOUND AND ${WITH_OPENMP} ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_OPENMP ${OpenMP_CXX_FLAGS}" ) -endif() - if( ${WITH_PROFILING} ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g" ) set( CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} --generate-line-info") @@ -304,18 +312,6 @@ if( ${WITH_GMP} ) endif() endif() -if( ${WITH_TESTS} ) - enable_testing() - - # build gtest libs - include( BuildGtest ) - - if( ${WITH_COVERAGE} AND CMAKE_BUILD_TYPE STREQUAL "Debug" ) - # enable code coverage reports - include( UseCodeCoverage ) - endif() -endif() - #if( BUILD_MPI ) # FIND_PATH( PETSC_INCLUDE_DIR petsc.h # /usr/include/petsc @@ -396,6 +392,7 @@ message( " WITH_MIC = ${WITH_MIC}" ) message( " WITH_CUDA = ${WITH_CUDA}" ) message( " WITH_CUDA_ARCH = ${WITH_CUDA_ARCH}" ) message( " WITH_OPENMP = ${WITH_OPENMP}" ) +message( " WITH_MPI = ${WITH_MPI}" ) message( " WITH_GMP = ${WITH_GMP}" ) message( " WITH_TESTS = ${WITH_TESTS}" ) message( " WITH_PROFILING = ${WITH_PROFILING}" ) @@ -420,3 +417,10 @@ message( " CMAKE_SHARED_LINKER_FLAGS_DEBUG = ${CMAKE_SHARED_LINKER_FLAGS_DEBUG message( " CMAKE_SHARED_LINKER_FLAGS_RELEASE = ${CMAKE_SHARED_LINKER_FLAGS_RELEASE}" ) message( " CUDA_NVCC_FLAGS = ${CUDA_NVCC_FLAGS}" ) message( " GMP_LIBRARIES = ${GMP_LIBRARIES}" ) +if( MPI_CXX_FOUND AND ${WITH_MPI} ) + message( " MPI_CXX_COMPILE_OPTIONS = ${MPI_CXX_COMPILE_OPTIONS}" ) + message( " MPI_CXX_COMPILE_DEFINITIONS = ${MPI_CXX_COMPILE_DEFINITIONS}" ) + message( " MPI_CXX_INCLUDE_DIRS = ${MPI_CXX_INCLUDE_DIRS}" ) + message( " MPI_CXX_LINK_FLAGS = ${MPI_CXX_LINK_FLAGS}" ) + message( " MPI_CXX_LIBRARIES = ${MPI_CXX_LIBRARIES}" ) +endif() diff --git a/Documentation/Pages/comparison-with-other-libraries.md b/Documentation/Pages/comparison-with-other-libraries.md new file mode 100644 index 0000000000000000000000000000000000000000..755110a7204fb52c5e8bcac85ea6a62b902c7eba --- /dev/null +++ b/Documentation/Pages/comparison-with-other-libraries.md @@ -0,0 +1,52 @@ +\page comparison_with_other_libraries Comparison with other libraries + +## Memory space and execution model + +TNL has separate concepts for the memory space and execution model, which are +represented by different template parameters. See the \ref core_concepts +"Core concepts" page for details. + +- Most other libraries have separate types for CPU and GPU data structures + (e.g. `Vector` and `cuVector`): + - [Thrust](https://github.com/thrust/thrust/): `host_vector`, `device_vector` + (plus macro-based selection, see below) + - [Paralution](http://www.paralution.com/documentation/): `HostVector`, `AcceleratorVector` + - [Bandicoot](https://coot.sourceforge.io/), [Kaldi](http://kaldi-asr.org/doc/about.html) +- These libraries have the concept of a "memory space" which is configurable as + a template parameter: + - [CUV](https://github.com/deeplearningais/CUV) + - [CUSP](http://cusplibrary.github.io/classcusp_1_1array1d.html) - but CUSP + uses Thrust, so `device_memory` might be the same as `host_memory` if OpenMP + is used as the `device` + - [Kokkos](https://github.com/kokkos/kokkos) - they have a concept of a + "memory space" and "execution space", but there is also some default choice + of the spaces, possibly even through command-line arguments (in which case + the array type would be polymorphic, because something has to store the + current memory/execution space) +- These libraries have transparent access to the data from GPU and CPU: + - the CUDA toolkit itself, via `cudaMallocManaged` + - [cudarrays](https://github.com/cudarrays/cudarrays) - they have custom + virtual memory system using `cudaMalloc` and the standard host allocator +- These libraries select the (default) device based on some macro + (this approach is way too simple, because multiple different devices cannot be + combined): + - Thrust: see [device backends](https://github.com/thrust/thrust/wiki/Device-Backends) + and [host backends](https://github.com/thrust/thrust/wiki/Host-Backends) +- These libraries do not abstract memory space, only execution model: + - [RAJA](https://github.com/LLNL/RAJA) + - [Nebo](https://www.sciencedirect.com/science/article/pii/S0164121216000182) + (also with a macro-based selection) + +## Multidimensional arrays + +TODO: compare the implementation of multidimensional arrays +(features described in the merge request: https://mmg-gitlab.fjfi.cvut.cz/gitlab/tnl/tnl-dev/merge_requests/18 ) + +- http://cpptruths.blogspot.cz/2011/10/multi-dimensional-arrays-in-c11.html +- http://www.nongnu.org/tensors/ (last commit in 2012) +- https://bitbucket.org/wlandry/ftensor/src +- [Eigen tensors](https://bitbucket.org/eigen/eigen/src/default/unsupported/Eigen/CXX11/src/Tensor/README.md?at=default&fileviewer=file-view-default) - Many operations, expression templates, either pure-static or pure-dynamic sizes, only column-major format (row-major support is incomplete), little GPU support. +- [cudarrays](https://github.com/cudarrays/cudarrays) - Only up to 3D arrays, both static and dynamic, compile-time permutations using `std::tuple`. +- [RAJA](https://github.com/LLNL/RAJA) - No memory management, views are initialized with a raw pointer, index permutations are initialized at runtime, only dynamic dimensions. +- [Kokkos](https://github.com/kokkos/kokkos) - Configurable layout and default selection based on the memory/execution space, but only AoS and SoA are considered, even for `N > 2`. For parallel work there is only one leading dimension - it does not map to 2D or 3D CUDA grids. +- [CUV](https://github.com/deeplearningais/CUV) - Assumption that "everything is an n-dimensional array" (like Matlab), CPU and GPU support, column-major or row-major, integration with Python and Numpy. diff --git a/Documentation/Pages/core-concepts.md b/Documentation/Pages/core-concepts.md index 1450ada792ded0c5031bd5648c3c3b7800a9bba6..8e151191eaff9008b177991c75a5bff58aead1f5 100644 --- a/Documentation/Pages/core-concepts.md +++ b/Documentation/Pages/core-concepts.md @@ -11,15 +11,24 @@ TNL is based on the following core concepts: (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" +3. \ref TNL::Communicators "Communicators" + - Communicators represent the main abstraction for distributed computations, + where multiple programs (or instances of the same program) have to + communicate with each other. + - At present, there are only two communicators: + \ref TNL::Communicators::MpiCommunicator "MpiCommunicator" + (uses [MPI](https://en.wikipedia.org/wiki/Message_Passing_Interface)) and + \ref TNL::Communicators::NoDistrCommunicator "NoDistrCommunicator" + (dummy communicator without any distribution support). +4. \ref TNL::Containers::Algorithms "Algorithms" - Basic (container-free) algorithms specialized by `Device`/`Executor`. - `ParallelFor`, `Reduction`, `MultiReduction`, `ArrayOperations`, ... -4. \ref TNL::Containers "Containers" +5. \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 +6. 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. diff --git a/Documentation/Pages/main-page.md b/Documentation/Pages/main-page.md index 8cdc9b506ad9e490460a6757628ba840a03fd424..4780f768500e586642017bf7eba9044acc9d6040 100644 --- a/Documentation/Pages/main-page.md +++ b/Documentation/Pages/main-page.md @@ -51,6 +51,8 @@ several modules: [libpng](http://www.libpng.org/pub/png/libpng.html) for PNG files, or [libjpeg](http://libjpeg.sourceforge.net/) for JPEG files. +See also \ref comparison_with_other_libraries "Comparison with other libraries". + ## Installation You can either download the [stable version](http://tnl-project.org/download/) diff --git a/build b/build index ec97d180033a42bb17b88a2dc8447f8e132d70fe..006088eaa0918f6ddb73170a0d7b19d6ee56cf61 100755 --- a/build +++ b/build @@ -107,33 +107,6 @@ else export CC=gcc fi -if [[ ${WITH_MPI} == "yes" ]]; then - # NOTE: OpenMPI provides mpic++, but Intel MPI does not - if [[ ! -x "$(command -v mpicxx)" ]]; then - echo "Warning: mpicxx is not installed on this system. MPI support is turned off." - else - # instruct OpenMPI to use the original compiler - # reference: https://www.open-mpi.org/faq/?category=mpi-apps#override-wrappers-after-v1.0 - # FIXME: this does not work with CUDA_HOST_COMPILER=mpicxx -# if [ -n "$CXX" ]; then -# export OMPI_CXX="$CXX" -# fi - export CUDA_ARCH_HOST_COMPILER="$CXX" - export CUDA_HOST_COMPILER=mpicxx - export CXX=mpicxx - fi - if [[ ! -x "$(command -v mpicc)" ]]; then - echo "Warning: mpicc is not installed on this system." - else - # instruct OpenMPI to use the original compiler - # reference: https://www.open-mpi.org/faq/?category=mpi-apps#override-wrappers-after-v1.0 -# if [ -n "$CC" ]; then -# export OMPI_CC="$CC" -# fi - export CC=mpicc - fi -fi - if hash ninja 2>/dev/null; then generator=Ninja make=ninja @@ -154,6 +127,7 @@ cmake_command=( -DWITH_CUDA=${WITH_CUDA} -DWITH_CUDA_ARCH=${WITH_CUDA_ARCH} -DWITH_OPENMP=${WITH_OPENMP} + -DWITH_MPI=${WITH_MPI} -DWITH_GMP=${WITH_GMP} -DWITH_TESTS=${WITH_TESTS} -DWITH_PROFILING=${WITH_PROFILING} diff --git a/scripts/make_coverage_report b/scripts/make_coverage_report index d65e882a4f658a241bf77f0a5f967db6bbe70714..8a6163d0fe2ebe9748a8037a1ca3c58db42ad82b 100755 --- a/scripts/make_coverage_report +++ b/scripts/make_coverage_report @@ -8,7 +8,7 @@ pushd Debug ../build --root-dir=.. --build=Debug \ --with-examples=no --with-benchmarks=no --with-tools=no --with-python=no --with-doc=no \ --with-tests=yes --run-tests=no \ - --with-clang=yes --with-cuda=yes --with-mpi=no --with-coverage=yes + --with-clang=yes --with-cuda=yes --with-coverage=yes popd tests=( @@ -27,9 +27,12 @@ tests=( ArrayTest-dbg # ArrayTestCuda-dbg # FIXME: CUDA ArrayViewTest-dbg - VectorTest-{1..3}-dbg - BinaryVectorOperationsTest-dbg - UnaryVectorOperationsTest-dbg + VectorTest-dbg + VectorPrefixSumTest-dbg + VectorEvaluateAndReduceTest-dbg + VectorBinaryOperationsTest-dbg + VectorUnaryOperationsTest-dbg + VectorVerticalOperationsTest-dbg StaticArrayTest-dbg StaticVectorTest-dbg StaticVectorOperationsTest-dbg @@ -37,6 +40,11 @@ tests=( # MultireductionTest-dbg # FIXME: CUDA MultimapTest-dbg StaticMultimapTest-dbg + # TODO: run these with mpirun (coverage.py does not support that) + DistributedArrayTest-dbg + DistributedVectorBinaryOperationsTest-dbg + DistributedVectorUnaryOperationsTest-dbg + DistributedVectorVerticalOperationsTest-dbg # Functions # BoundaryMeshFunctionTest-dbg # FIXME: CUDA diff --git a/src/Benchmarks/BLAS/VectorOperations.h b/src/Benchmarks/BLAS/VectorOperations.h new file mode 100644 index 0000000000000000000000000000000000000000..0ad2c1ee6829aefbc184a1725afb75e665110724 --- /dev/null +++ b/src/Benchmarks/BLAS/VectorOperations.h @@ -0,0 +1,141 @@ +/*************************************************************************** + VectorOperations.h - description + ------------------- + begin : Nov 8, 2012 + copyright : (C) 2012 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include +#include +#include + +namespace TNL { +namespace Benchmarks { + +template< typename Device > +struct VectorOperations; + +template<> +struct VectorOperations< Devices::Host > +{ + static constexpr int OpenMPVectorOperationsThreshold = 512; + static constexpr int PrefetchDistance = 128; + + template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2 > + static void addVector( Vector1& y, + const Vector2& x, + const Scalar1 alpha, + const Scalar2 thisMultiplicator = 1.0 ) + { + typedef typename Vector1::IndexType Index; + + TNL_ASSERT_GT( x.getSize(), 0, "Vector size must be positive." ); + TNL_ASSERT_EQ( x.getSize(), y.getSize(), "The vector sizes must be the same." ); + + const Index n = y.getSize(); + + if( thisMultiplicator == 1.0 ) + #ifdef HAVE_OPENMP + #pragma omp parallel for if( TNL::Devices::Host::isOMPEnabled() && n > OpenMPVectorOperationsThreshold ) + #endif + for( Index i = 0; i < n; i ++ ) + y[ i ] += alpha * x[ i ]; + else + #ifdef HAVE_OPENMP + #pragma omp parallel for if( TNL::Devices::Host::isOMPEnabled() && n > OpenMPVectorOperationsThreshold ) + #endif + for( Index i = 0; i < n; i ++ ) + y[ i ] = thisMultiplicator * y[ i ] + alpha * x[ i ]; +} + + template< typename Vector1, typename Vector2, typename Vector3, typename Scalar1, typename Scalar2, typename Scalar3 > + static void addVectors( Vector1& v, + const Vector2& v1, + const Scalar1 multiplicator1, + const Vector3& v2, + const Scalar2 multiplicator2, + const Scalar3 thisMultiplicator = 1.0 ) + { + typedef typename Vector1::IndexType Index; + + TNL_ASSERT_GT( v.getSize(), 0, "Vector size must be positive." ); + TNL_ASSERT_EQ( v.getSize(), v1.getSize(), "The vector sizes must be the same." ); + TNL_ASSERT_EQ( v.getSize(), v2.getSize(), "The vector sizes must be the same." ); + + const Index n = v.getSize(); + if( thisMultiplicator == 1.0 ) + #ifdef HAVE_OPENMP + #pragma omp parallel for if( TNL::Devices::Host::isOMPEnabled() && n > OpenMPVectorOperationsThreshold ) + #endif + for( Index i = 0; i < n; i ++ ) + v[ i ] += multiplicator1 * v1[ i ] + multiplicator2 * v2[ i ]; + else + #ifdef HAVE_OPENMP + #pragma omp parallel for if( TNL::Devices::Host::isOMPEnabled() && n > OpenMPVectorOperationsThreshold ) + #endif + for( Index i = 0; i < n; i ++ ) + v[ i ] = thisMultiplicator * v[ i ] + multiplicator1 * v1[ i ] + multiplicator2 * v2[ i ]; + } +}; + +template<> +struct VectorOperations< Devices::Cuda > +{ + template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2 > + static void addVector( Vector1& _y, + const Vector2& _x, + const Scalar1 alpha, + const Scalar2 thisMultiplicator = 1.0 ) + { + TNL_ASSERT_GT( _x.getSize(), 0, "Vector size must be positive." ); + TNL_ASSERT_EQ( _x.getSize(), _y.getSize(), "The vector sizes must be the same." ); + + using IndexType = typename Vector1::IndexType; + using RealType = typename Vector1::RealType; + + RealType* y = _y.getData(); + const RealType* x = _x.getData(); + auto add1 = [=] __cuda_callable__ ( IndexType i ) { y[ i ] += alpha * x[ i ]; }; + auto add2 = [=] __cuda_callable__ ( IndexType i ) { y[ i ] = thisMultiplicator * y[ i ] + alpha * x[ i ]; }; + + if( thisMultiplicator == 1.0 ) + ParallelFor< Devices::Cuda >::exec( (IndexType) 0, _y.getSize(), add1 ); + else + ParallelFor< Devices::Cuda >::exec( (IndexType) 0, _y.getSize(), add2 ); + } + + template< typename Vector1, typename Vector2, typename Vector3, typename Scalar1, typename Scalar2, typename Scalar3 > + static void addVectors( Vector1& _v, + const Vector2& _v1, + const Scalar1 multiplicator1, + const Vector3& _v2, + const Scalar2 multiplicator2, + const Scalar3 thisMultiplicator = 1.0 ) + { + TNL_ASSERT_GT( _v.getSize(), 0, "Vector size must be positive." ); + TNL_ASSERT_EQ( _v.getSize(), _v1.getSize(), "The vector sizes must be the same." ); + TNL_ASSERT_EQ( _v.getSize(), _v2.getSize(), "The vector sizes must be the same." ); + + using IndexType = typename Vector1::IndexType; + using RealType = typename Vector1::RealType; + + RealType* v = _v.getData(); + const RealType* v1 = _v1.getData(); + const RealType* v2 = _v2.getData(); + auto add1 = [=] __cuda_callable__ ( IndexType i ) { v[ i ] += multiplicator1 * v1[ i ] + multiplicator2 * v2[ i ]; }; + auto add2 = [=] __cuda_callable__ ( IndexType i ) { v[ i ] = thisMultiplicator * v[ i ] + multiplicator1 * v1[ i ] + multiplicator2 * v2[ i ]; }; + + if( thisMultiplicator == 1.0 ) + ParallelFor< Devices::Cuda >::exec( (IndexType) 0, _v.getSize(), add1 ); + else + ParallelFor< Devices::Cuda >::exec( (IndexType) 0, _v.getSize(), add2 ); + } +}; + +} // namespace Benchmarks +} // namespace TNL diff --git a/src/Benchmarks/BLAS/vector-operations.h b/src/Benchmarks/BLAS/vector-operations.h index 219cbc33477be7d3cc697d3ed340ca7eae53b604..25fa055bf59afd1dcaebb85b94af7ab58479ec5b 100644 --- a/src/Benchmarks/BLAS/vector-operations.h +++ b/src/Benchmarks/BLAS/vector-operations.h @@ -18,6 +18,7 @@ #include #include "CommonVectorOperations.h" +#include "VectorOperations.h" #ifdef HAVE_BLAS #include "blasWrappers.h" @@ -124,10 +125,10 @@ benchmarkVectorOperations( Benchmark & benchmark, }; benchmark.setOperation( "max", datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", maxHost ); + benchmark.time< Devices::Host >( reset1, "CPU legacy", maxHost ); benchmark.time< Devices::Host >( reset1, "CPU ET", maxHostET ); #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", maxCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU legacy", maxCuda ); benchmark.time< Devices::Cuda >( reset1, "GPU ET", maxCudaET ); #endif @@ -146,10 +147,10 @@ benchmarkVectorOperations( Benchmark & benchmark, resultDevice = min( deviceView ); }; benchmark.setOperation( "min", datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", minHost ); + benchmark.time< Devices::Host >( reset1, "CPU legacy", minHost ); benchmark.time< Devices::Host >( reset1, "CPU ET", minHostET ); #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", minCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU legacy", minCuda ); benchmark.time< Devices::Cuda >( reset1, "GPU ET", minCudaET ); #endif @@ -183,13 +184,13 @@ benchmarkVectorOperations( Benchmark & benchmark, }; #endif benchmark.setOperation( "absMax", datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", absMaxHost ); + benchmark.time< Devices::Host >( reset1, "CPU legacy", absMaxHost ); benchmark.time< Devices::Host >( reset1, "CPU ET", absMaxHostET ); #ifdef HAVE_BLAS benchmark.time< Devices::Host >( reset1, "CPU BLAS", absMaxBlas ); #endif #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", absMaxCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU legacy", absMaxCuda ); benchmark.time< Devices::Cuda >( reset1, "GPU ET", absMaxCudaET ); benchmark.time< Devices::Cuda >( reset1, "cuBLAS", absMaxCublas ); #endif @@ -224,11 +225,11 @@ benchmarkVectorOperations( Benchmark & benchmark, }; #endif benchmark.setOperation( "absMin", datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", absMinHost ); + benchmark.time< Devices::Host >( reset1, "CPU legacy", absMinHost ); benchmark.time< Devices::Host >( reset1, "CPU ET", absMinHostET ); //benchmark.time< Devices::Host >( reset1, "CPU BLAS", absMinBlas ); #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", absMinCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU legacy", absMinCuda ); benchmark.time< Devices::Cuda >( reset1, "GPU ET", absMinCudaET ); benchmark.time< Devices::Cuda >( reset1, "cuBLAS", absMinCublas ); #endif @@ -248,10 +249,10 @@ benchmarkVectorOperations( Benchmark & benchmark, resultDevice = sum( deviceView ); }; benchmark.setOperation( "sum", datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", sumHost ); + benchmark.time< Devices::Host >( reset1, "CPU legacy", sumHost ); benchmark.time< Devices::Host >( reset1, "CPU ET", sumHostET ); #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", sumCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU legacy", sumCuda ); benchmark.time< Devices::Cuda >( reset1, "GPU ET", sumCudaET ); #endif @@ -282,13 +283,13 @@ benchmarkVectorOperations( Benchmark & benchmark, }; #endif benchmark.setOperation( "l1 norm", datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", l1normHost ); + benchmark.time< Devices::Host >( reset1, "CPU legacy", l1normHost ); benchmark.time< Devices::Host >( reset1, "CPU ET", l1normHostET ); #ifdef HAVE_BLAS benchmark.time< Devices::Host >( reset1, "CPU BLAS", l1normBlas ); #endif #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", l1normCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU legacy", l1normCuda ); benchmark.time< Devices::Cuda >( reset1, "GPU ET", l1normCudaET ); benchmark.time< Devices::Cuda >( reset1, "cuBLAS", l1normCublas ); #endif @@ -320,13 +321,13 @@ benchmarkVectorOperations( Benchmark & benchmark, }; #endif benchmark.setOperation( "l2 norm", datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", l2normHost ); + benchmark.time< Devices::Host >( reset1, "CPU legacy", l2normHost ); benchmark.time< Devices::Host >( reset1, "CPU ET", l2normHostET ); #ifdef HAVE_BLAS benchmark.time< Devices::Host >( reset1, "CPU BLAS", l2normBlas ); #endif #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", l2normCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU legacy", l2normCuda ); benchmark.time< Devices::Cuda >( reset1, "GPU ET", l2normCudaET ); benchmark.time< Devices::Cuda >( reset1, "cuBLAS", l2normCublas ); #endif @@ -347,10 +348,10 @@ benchmarkVectorOperations( Benchmark & benchmark, }; benchmark.setOperation( "l3 norm", datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", l3normHost ); + benchmark.time< Devices::Host >( reset1, "CPU legacy", l3normHost ); benchmark.time< Devices::Host >( reset1, "CPU ET", l3normHostET ); #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", l3normCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU legacy", l3normCuda ); benchmark.time< Devices::Cuda >( reset1, "GPU ET", l3normCudaET ); #endif @@ -383,13 +384,13 @@ benchmarkVectorOperations( Benchmark & benchmark, }; #endif benchmark.setOperation( "scalar product", 2 * datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", scalarProductHost ); + benchmark.time< Devices::Host >( reset1, "CPU legacy", scalarProductHost ); benchmark.time< Devices::Host >( reset1, "CPU ET", scalarProductHostET ); #ifdef HAVE_BLAS benchmark.time< Devices::Host >( reset1, "CPU BLAS", scalarProductBlas ); #endif #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", scalarProductCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU legacy", scalarProductCuda ); benchmark.time< Devices::Cuda >( reset1, "GPU ET", scalarProductCudaET ); benchmark.time< Devices::Cuda >( reset1, "cuBLAS", scalarProductCublas ); #endif @@ -443,19 +444,19 @@ benchmarkVectorOperations( Benchmark & benchmark, }; #endif benchmark.setOperation( "scalar multiplication", 2 * datasetSize ); - benchmark.time< Devices::Host >( reset1, "CPU", multiplyHost ); + benchmark.time< Devices::Host >( reset1, "CPU ET", multiplyHost ); #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( reset1, "GPU", multiplyCuda ); + benchmark.time< Devices::Cuda >( reset1, "GPU ET", multiplyCuda ); benchmark.time< Devices::Cuda >( reset1, "cuBLAS", multiplyCublas ); #endif //// // Vector addition auto addVectorHost = [&]() { - hostVector.addVector( hostVector2 ); + Benchmarks::VectorOperations< Devices::Host >::addVector( hostVector, hostVector2, (Real) 1.0, (Real) 1.0 ); }; auto addVectorCuda = [&]() { - deviceVector.addVector( deviceVector2 ); + Benchmarks::VectorOperations< Devices::Cuda >::addVector( deviceVector, deviceVector2, (Real) 1.0, (Real) 1.0 ); }; auto addVectorHostET = [&]() { hostView += hostView2; @@ -481,13 +482,13 @@ benchmarkVectorOperations( Benchmark & benchmark, }; #endif benchmark.setOperation( "vector addition", 3 * datasetSize ); - benchmark.time< Devices::Host >( resetAll, "CPU", addVectorHost ); + benchmark.time< Devices::Host >( resetAll, "CPU legacy", addVectorHost ); benchmark.time< Devices::Host >( resetAll, "CPU ET", addVectorHostET ); #ifdef HAVE_BLAS benchmark.time< Devices::Host >( resetAll, "CPU BLAS", addVectorBlas ); #endif #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( resetAll, "GPU", addVectorCuda ); + benchmark.time< Devices::Cuda >( resetAll, "GPU legacy", addVectorCuda ); benchmark.time< Devices::Cuda >( resetAll, "GPU ET", addVectorCudaET ); benchmark.time< Devices::Cuda >( resetAll, "cuBLAS", addVectorCublas ); #endif @@ -495,12 +496,12 @@ benchmarkVectorOperations( Benchmark & benchmark, //// // Two vectors addition auto addTwoVectorsHost = [&]() { - hostVector.addVector( hostVector2 ); - hostVector.addVector( hostVector3 ); + Benchmarks::VectorOperations< Devices::Host >::addVector( hostVector, hostVector2, (Real) 1.0, (Real) 1.0 ); + Benchmarks::VectorOperations< Devices::Host >::addVector( hostVector, hostVector3, (Real) 1.0, (Real) 1.0 ); }; auto addTwoVectorsCuda = [&]() { - deviceVector.addVector( deviceVector2 ); - deviceVector.addVector( deviceVector3 ); + Benchmarks::VectorOperations< Devices::Cuda >::addVector( deviceVector, deviceVector2, (Real) 1.0, (Real) 1.0 ); + Benchmarks::VectorOperations< Devices::Cuda >::addVector( deviceVector, deviceVector3, (Real) 1.0, (Real) 1.0 ); }; auto addTwoVectorsHostET = [&]() { hostView += hostView2 + hostView3; @@ -533,13 +534,13 @@ benchmarkVectorOperations( Benchmark & benchmark, }; #endif benchmark.setOperation( "two vectors addition", 4 * datasetSize ); - benchmark.time< Devices::Host >( resetAll, "CPU", addTwoVectorsHost ); + benchmark.time< Devices::Host >( resetAll, "CPU legacy", addTwoVectorsHost ); benchmark.time< Devices::Host >( resetAll, "CPU ET", addTwoVectorsHostET ); #ifdef HAVE_BLAS benchmark.time< Devices::Host >( resetAll, "CPU BLAS", addTwoVectorsBlas ); #endif #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( resetAll, "GPU", addTwoVectorsCuda ); + benchmark.time< Devices::Cuda >( resetAll, "GPU legacy", addTwoVectorsCuda ); benchmark.time< Devices::Cuda >( resetAll, "GPU ET", addTwoVectorsCudaET ); benchmark.time< Devices::Cuda >( resetAll, "cuBLAS", addTwoVectorsCublas ); #endif @@ -547,14 +548,14 @@ benchmarkVectorOperations( Benchmark & benchmark, //// // Three vectors addition auto addThreeVectorsHost = [&]() { - hostVector.addVector( hostVector2 ); - hostVector.addVector( hostVector3 ); - hostVector.addVector( hostVector4 ); + Benchmarks::VectorOperations< Devices::Host >::addVector( hostVector, hostVector2, (Real) 1.0, (Real) 1.0 ); + Benchmarks::VectorOperations< Devices::Host >::addVector( hostVector, hostVector3, (Real) 1.0, (Real) 1.0 ); + Benchmarks::VectorOperations< Devices::Host >::addVector( hostVector, hostVector4, (Real) 1.0, (Real) 1.0 ); }; auto addThreeVectorsCuda = [&]() { - deviceVector.addVector( deviceVector2 ); - deviceVector.addVector( deviceVector3 ); - deviceVector.addVector( deviceVector4 ); + Benchmarks::VectorOperations< Devices::Cuda >::addVector( deviceVector, deviceVector2, (Real) 1.0, (Real) 1.0 ); + Benchmarks::VectorOperations< Devices::Cuda >::addVector( deviceVector, deviceVector3, (Real) 1.0, (Real) 1.0 ); + Benchmarks::VectorOperations< Devices::Cuda >::addVector( deviceVector, deviceVector4, (Real) 1.0, (Real) 1.0 ); }; auto addThreeVectorsHostET = [&]() { hostView += hostView2 + hostView3 + hostView4; @@ -594,13 +595,13 @@ benchmarkVectorOperations( Benchmark & benchmark, }; #endif benchmark.setOperation( "three vectors addition", 5 * datasetSize ); - benchmark.time< Devices::Host >( resetAll, "CPU", addThreeVectorsHost ); + benchmark.time< Devices::Host >( resetAll, "CPU legacy", addThreeVectorsHost ); benchmark.time< Devices::Host >( resetAll, "CPU ET", addThreeVectorsHostET ); #ifdef HAVE_BLAS benchmark.time< Devices::Host >( resetAll, "CPU BLAS", addThreeVectorsBlas ); #endif #ifdef HAVE_CUDA - benchmark.time< Devices::Cuda >( resetAll, "GPU", addThreeVectorsCuda ); + benchmark.time< Devices::Cuda >( resetAll, "GPU legacy", addThreeVectorsCuda ); benchmark.time< Devices::Cuda >( resetAll, "GPU ET", addThreeVectorsCudaET ); benchmark.time< Devices::Cuda >( resetAll, "cuBLAS", addThreeVectorsCublas ); #endif diff --git a/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h index 0ffbf0f861352e861cdff409cdf0dfe46791f7af..81e5d3a6d05aff53fa56e6d6eb045104f9ac3c42 100644 --- a/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h +++ b/src/Benchmarks/DistSpMV/tnl-benchmark-distributed-spmv.h @@ -268,7 +268,7 @@ struct SpmvBenchmark const int nproc = CommunicatorType::GetSize( distributedMatrix.getCommunicationGroup() ); typename VectorType::ViewType subY( &y[ Partitioner::getOffset( matrix.getRows(), rank, nproc ) ], Partitioner::getSizeForRank( matrix.getRows(), rank, nproc ) ); - TNL_ASSERT_EQ( distributedY.getLocalVectorView(), subY, "WRONG RESULT !!!" ); + TNL_ASSERT_EQ( distributedY.getLocalView(), subY, "WRONG RESULT !!!" ); #endif } }; diff --git a/src/Benchmarks/LinearSolvers/benchmarks.h b/src/Benchmarks/LinearSolvers/benchmarks.h index e244fb31d6ecdc6ba8d669bdd91acda2b5df9681..577907c78ab13253c6c46c9db4d182b00d11957e 100644 --- a/src/Benchmarks/LinearSolvers/benchmarks.h +++ b/src/Benchmarks/LinearSolvers/benchmarks.h @@ -157,7 +157,7 @@ benchmarkSolver( Benchmark& benchmark, Vector r; r.setLike( x ); matrix->vectorProduct( x, r ); - r.addVector( b, 1.0, -1.0 ); + r = b - r; const double residue_true = lpNorm( r, 2.0 ) / lpNorm( b, 2.0 ); return RowElements({ time, speedup, (double) converged, (double) iterations, diff --git a/src/Benchmarks/ODESolvers/Euler.hpp b/src/Benchmarks/ODESolvers/Euler.hpp index 1cd3c5d6f7271ba94f77e53701e1bf5b03c6521e..1066e178c2f150c97514eb04dcd19a5a30932102 100644 --- a/src/Benchmarks/ODESolvers/Euler.hpp +++ b/src/Benchmarks/ODESolvers/Euler.hpp @@ -203,7 +203,7 @@ void Euler< Problem, SolverMonitor >::computeNewTimeLevel( DofVectorPointer& u, &_k1[ gridOffset ], &_u[ gridOffset ], this->cudaBlockResidue.getData() ); - localResidue += this->cudaBlockResidue.sum(); + localResidue += sum( this->cudaBlockResidue ); cudaDeviceSynchronize(); TNL_CHECK_CUDA_DEVICE; } diff --git a/src/Benchmarks/ODESolvers/Merson.hpp b/src/Benchmarks/ODESolvers/Merson.hpp index 34337fba8e08ca2a72972a4d6601938ba9991d38..3a5cdf660b82d6f48509172fb1eee3e3fadb5760 100644 --- a/src/Benchmarks/ODESolvers/Merson.hpp +++ b/src/Benchmarks/ODESolvers/Merson.hpp @@ -466,7 +466,7 @@ void Merson< Problem, SolverMonitor >::computeNewTimeLevel( const RealType time, &_k5[ gridOffset ], &_u[ gridOffset ], this->cudaBlockResidue.getData() ); - localResidue += this->cudaBlockResidue.sum(); + localResidue += sum( this->cudaBlockResidue ); cudaDeviceSynchronize(); } this->problem->applyBoundaryConditions( time, u ); diff --git a/src/Python/pytnl/tnl/StaticVector.h b/src/Python/pytnl/tnl/StaticVector.h index 4875bdf23e85235d7bceaee70a4ba515459f9546..6b5570647fd31f7c2c8692b9c5b7322227ea7781 100644 --- a/src/Python/pytnl/tnl/StaticVector.h +++ b/src/Python/pytnl/tnl/StaticVector.h @@ -28,12 +28,20 @@ void export_StaticVector( Scope & scope, const char* name ) // .def(py::self_ns::str(py::self)) .def(py::self += py::self) .def(py::self -= py::self) + .def(py::self *= py::self) + .def(py::self /= py::self) + .def(py::self += RealType()) + .def(py::self -= RealType()) .def(py::self *= RealType()) .def(py::self /= RealType()) .def(py::self + py::self) .def(py::self - py::self) - .def(py::self * RealType()) .def(py::self * py::self) + .def(py::self / py::self) + .def(py::self + RealType()) + .def(py::self - RealType()) + .def(py::self * RealType()) + .def(py::self / RealType()) .def(py::self < py::self) .def(py::self > py::self) .def(py::self <= py::self) diff --git a/src/Python/pytnl/tnl/Vector.h b/src/Python/pytnl/tnl/Vector.h index df562f98ff73965fac3a9121925439a67bc139bc..9fdac4072b4db7cac83c4eb95739a92a6abe671d 100644 --- a/src/Python/pytnl/tnl/Vector.h +++ b/src/Python/pytnl/tnl/Vector.h @@ -9,14 +9,7 @@ namespace py = pybind11; template< typename ArrayType, typename VectorType > void export_Vector(py::module & m, const char* name) { - // function pointers for overloaded methods - void (VectorType::* _addElement1)(const typename VectorType::IndexType, - const typename VectorType::RealType &) - = &VectorType::addElement; - void (VectorType::* _addElement2)(const typename VectorType::IndexType, - const typename VectorType::RealType &, - const typename VectorType::RealType &) - = &VectorType::addElement; + using RealType = typename VectorType::RealType; py::class_(m, name) .def(py::init<>()) @@ -25,15 +18,27 @@ void export_Vector(py::module & m, const char* name) .def("getTypeVirtual", &VectorType::getTypeVirtual) .def_static("getSerializationType", &VectorType::getSerializationType) .def("getSerializationTypeVirtual", &VectorType::getSerializationTypeVirtual) - .def("addElement", _addElement1) - .def("addElement", _addElement2) .def(py::self == py::self) .def(py::self != py::self) .def(py::self += py::self) .def(py::self -= py::self) - .def(py::self *= typename VectorType::RealType()) - .def(py::self /= typename VectorType::RealType()) - .def("addVector", &VectorType::template addVector) - .def("addVectors", &VectorType::template addVectors) + .def(py::self *= py::self) + .def(py::self /= py::self) + .def(py::self += RealType()) + .def(py::self -= RealType()) + .def(py::self *= RealType()) + .def(py::self /= RealType()) + .def(py::self + py::self) + .def(py::self - py::self) + .def(py::self * py::self) + .def(py::self / py::self) + .def(py::self + RealType()) + .def(py::self - RealType()) + .def(py::self * RealType()) + .def(py::self / RealType()) + .def(py::self < py::self) + .def(py::self > py::self) + .def(py::self <= py::self) + .def(py::self >= py::self) ; } diff --git a/src/TNL/Communicators/MPITypeResolver.h b/src/TNL/Communicators/MPITypeResolver.h index 371616322494f52aff5a0ed5b1975f071ba90d6f..10dca451b8402896989111edc771d7b4be58b24e 100644 --- a/src/TNL/Communicators/MPITypeResolver.h +++ b/src/TNL/Communicators/MPITypeResolver.h @@ -100,8 +100,6 @@ template<> struct MPITypeResolver< bool > static inline MPI_Datatype getType() { return MPI_C_BOOL; }; }; #endif - - - - } // namespace Communicators + +} // namespace Communicators } // namespace TNL diff --git a/src/TNL/Communicators/MpiCommunicator.h b/src/TNL/Communicators/MpiCommunicator.h index a40b2e4bb8d2b5aecaf51c3a61feb5510498c517..926fa329a6e88b3d84406f464aa3e82057e3ef24 100644 --- a/src/TNL/Communicators/MpiCommunicator.h +++ b/src/TNL/Communicators/MpiCommunicator.h @@ -1,8 +1,8 @@ /*************************************************************************** MpiCommunicator.h - description ------------------- - begin : 2005/04/23 - copyright : (C) 2005 by Tomas Oberhuber + begin : Apr 23, 2005 + copyright : (C) 2005 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -43,34 +43,15 @@ namespace TNL { +//! \brief Namespace for TNL communicators. namespace Communicators { namespace { +//! \brief MPI communicator. class MpiCommunicator { - - public: // TODO: this was private + public: #ifdef HAVE_MPI - /*inline static MPI_Datatype MPIDataType( const signed char* ) { return MPI_CHAR; }; - inline static MPI_Datatype MPIDataType( const signed short int* ) { return MPI_SHORT; }; - inline static MPI_Datatype MPIDataType( const signed int* ) { return MPI_INT; }; - inline static MPI_Datatype MPIDataType( const signed long int* ) { return MPI_LONG; }; - inline static MPI_Datatype MPIDataType( const unsigned char *) { return MPI_UNSIGNED_CHAR; }; - inline static MPI_Datatype MPIDataType( const unsigned short int* ) { return MPI_UNSIGNED_SHORT; }; - inline static MPI_Datatype MPIDataType( const unsigned int* ) { return MPI_UNSIGNED; }; - inline static MPI_Datatype MPIDataType( const unsigned long int* ) { return MPI_UNSIGNED_LONG; }; - inline static MPI_Datatype MPIDataType( const float* ) { return MPI_FLOAT; }; - inline static MPI_Datatype MPIDataType( const double* ) { return MPI_DOUBLE; }; - inline static MPI_Datatype MPIDataType( const long double* ) { return MPI_LONG_DOUBLE; }; - - // TODO: tested with MPI_LOR and MPI_LAND, but there should probably be unit tests for all operations - inline static MPI_Datatype MPIDataType( const bool* ) - { - // sizeof(bool) is implementation-defined: https://stackoverflow.com/a/4897859 - static_assert( sizeof(bool) == 1, "The programmer did not count with systems where sizeof(bool) != 1." ); - return MPI_CHAR; - };*/ - using Request = MPI_Request; using CommunicationGroup = MPI_Comm; #else @@ -223,11 +204,11 @@ class MpiCommunicator static int GetRank(CommunicationGroup group = AllGroup ) { #ifdef HAVE_MPI - TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); - TNL_ASSERT_NE(group, NullGroup, "GetRank cannot be called with NullGroup"); - int rank; - MPI_Comm_rank(group,&rank); - return rank; + TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); + TNL_ASSERT_NE(group, NullGroup, "GetRank cannot be called with NullGroup"); + int rank; + MPI_Comm_rank(group,&rank); + return rank; #else throw Exceptions::MPISupportMissing(); #endif @@ -249,224 +230,220 @@ class MpiCommunicator #ifdef HAVE_MPI template< typename T > static MPI_Datatype getDataType( const T& t ) - { + { return MPITypeResolver< T >::getType(); } #endif - + //dim-number of dimensions, distr array of guess distr - 0 for computation //distr array will be filled by computed distribution //more information in MPI documentation static void DimsCreate(int nproc, int dim, int *distr) { #ifdef HAVE_MPI - int sum = 0, prod = 1; - for( int i = 0;i < dim; i++ ) - { - sum += distr[ i ]; - prod *= distr[ i ]; - } - if( prod != 0 && prod != GetSize( AllGroup ) ) - throw Exceptions::MPIDimsCreateError(); - if(sum==0) - { - for(int i=0;i - static void Send( const T* data, int count, int dest, int tag, CommunicationGroup group = AllGroup ) - { + template + static void Send( const T* data, int count, int dest, int tag, CommunicationGroup group = AllGroup ) + { #ifdef HAVE_MPI - TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); - TNL_ASSERT_NE(group, NullGroup, "Send cannot be called with NullGroup"); - MPI_Send( const_cast< void* >( ( const void* ) data ), count, MPITypeResolver< T >::getType(), dest, tag, group ); + TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); + TNL_ASSERT_NE(group, NullGroup, "Send cannot be called with NullGroup"); + MPI_Send( const_cast< void* >( ( const void* ) data ), count, MPITypeResolver< T >::getType(), dest, tag, group ); #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } + } - template - static void Recv( T* data, int count, int src, int tag, CommunicationGroup group = AllGroup ) - { + template + static void Recv( T* data, int count, int src, int tag, CommunicationGroup group = AllGroup ) + { #ifdef HAVE_MPI - TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); - TNL_ASSERT_NE(group, NullGroup, "Recv cannot be called with NullGroup"); - MPI_Status status; - MPI_Recv( const_cast< void* >( ( const void* ) data ), count, MPITypeResolver< T >::getType() , src, tag, group, &status ); + TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); + TNL_ASSERT_NE(group, NullGroup, "Recv cannot be called with NullGroup"); + MPI_Status status; + MPI_Recv( const_cast< void* >( ( const void* ) data ), count, MPITypeResolver< T >::getType() , src, tag, group, &status ); #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } + } - template - static Request ISend( const T* data, int count, int dest, int tag, CommunicationGroup group = AllGroup ) - { + template + static Request ISend( const T* data, int count, int dest, int tag, CommunicationGroup group = AllGroup ) + { #ifdef HAVE_MPI - TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); - TNL_ASSERT_NE(group, NullGroup, "ISend cannot be called with NullGroup"); - Request req; - MPI_Isend( const_cast< void* >( ( const void* ) data ), count, MPITypeResolver< T >::getType(), dest, tag, group, &req); - return req; + TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); + TNL_ASSERT_NE(group, NullGroup, "ISend cannot be called with NullGroup"); + Request req; + MPI_Isend( const_cast< void* >( ( const void* ) data ), count, MPITypeResolver< T >::getType(), dest, tag, group, &req); + return req; #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } + } - template - static Request IRecv( T* data, int count, int src, int tag, CommunicationGroup group = AllGroup ) - { + template + static Request IRecv( T* data, int count, int src, int tag, CommunicationGroup group = AllGroup ) + { #ifdef HAVE_MPI - TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); - TNL_ASSERT_NE(group, NullGroup, "IRecv cannot be called with NullGroup"); - Request req; - MPI_Irecv( const_cast< void* >( ( const void* ) data ), count, MPITypeResolver< T >::getType() , src, tag, group, &req); - return req; + TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); + TNL_ASSERT_NE(group, NullGroup, "IRecv cannot be called with NullGroup"); + Request req; + MPI_Irecv( const_cast< void* >( ( const void* ) data ), count, MPITypeResolver< T >::getType() , src, tag, group, &req); + return req; #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } + } - static void WaitAll(Request *reqs, int length) - { + static void WaitAll(Request *reqs, int length) + { #ifdef HAVE_MPI - TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); - MPI_Waitall(length, reqs, MPI_STATUSES_IGNORE); + TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); + MPI_Waitall(length, reqs, MPI_STATUSES_IGNORE); #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } + } - template< typename T > - static void Bcast( T* data, int count, int root, CommunicationGroup group) - { + template< typename T > + static void Bcast( T* data, int count, int root, CommunicationGroup group) + { #ifdef HAVE_MPI - TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); - TNL_ASSERT_NE(group, NullGroup, "BCast cannot be called with NullGroup"); - MPI_Bcast((void*) data, count, MPITypeResolver< T >::getType(), root, group); + TNL_ASSERT_TRUE(IsInitialized(), "Fatal Error - MPI communicator is not initialized"); + TNL_ASSERT_NE(group, NullGroup, "BCast cannot be called with NullGroup"); + MPI_Bcast((void*) data, count, MPITypeResolver< T >::getType(), root, group); #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } - - template< typename T > - static void Allreduce( const T* data, - T* reduced_data, - int count, - const MPI_Op &op, - CommunicationGroup group) - { + } + + template< typename T > + static void Allreduce( const T* data, + T* reduced_data, + int count, + const MPI_Op &op, + CommunicationGroup group) + { #ifdef HAVE_MPI - TNL_ASSERT_NE(group, NullGroup, "Allreduce cannot be called with NullGroup"); - MPI_Allreduce( const_cast< void* >( ( void* ) data ), (void*) reduced_data,count,MPITypeResolver< T >::getType(),op,group); + TNL_ASSERT_NE(group, NullGroup, "Allreduce cannot be called with NullGroup"); + MPI_Allreduce( const_cast< void* >( ( void* ) data ), (void*) reduced_data,count,MPITypeResolver< T >::getType(),op,group); #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } - - // in-place variant of Allreduce - template< typename T > - static void Allreduce( T* data, - int count, - const MPI_Op &op, - CommunicationGroup group) - { + } + + // in-place variant of Allreduce + template< typename T > + static void Allreduce( T* data, + int count, + const MPI_Op &op, + CommunicationGroup group) + { #ifdef HAVE_MPI - TNL_ASSERT_NE(group, NullGroup, "Allreduce cannot be called with NullGroup"); - MPI_Allreduce( MPI_IN_PLACE, (void*) data,count,MPITypeResolver< T >::getType(),op,group); + TNL_ASSERT_NE(group, NullGroup, "Allreduce cannot be called with NullGroup"); + MPI_Allreduce( MPI_IN_PLACE, (void*) data,count,MPITypeResolver< T >::getType(),op,group); #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } + } - template< typename T > - static void Reduce( const T* data, - T* reduced_data, - int count, - MPI_Op &op, - int root, - CommunicationGroup group) - { -#ifdef HAVE_MPI - TNL_ASSERT_NE(group, NullGroup, "Reduce cannot be called with NullGroup"); - MPI_Reduce( const_cast< void* >( ( void*) data ), (void*) reduced_data,count,MPITypeResolver< T >::getType(),op,root,group); -#else - throw Exceptions::MPISupportMissing(); -#endif - } - - template< typename T > - static void SendReceive( const T* sendData, - int sendCount, - int destination, - int sendTag, - T* receiveData, - int receiveCount, - int source, - int receiveTag, - CommunicationGroup group ) - { + template< typename T > + static void Reduce( const T* data, + T* reduced_data, + int count, + MPI_Op &op, + int root, + CommunicationGroup group) + { #ifdef HAVE_MPI - TNL_ASSERT_NE(group, NullGroup, "SendReceive cannot be called with NullGroup"); - MPI_Status status; - MPI_Sendrecv( const_cast< void* >( ( void* ) sendData ), - sendCount, - MPITypeResolver< T >::getType(), - destination, - sendTag, - ( void* ) receiveData, - receiveCount, - MPITypeResolver< T >::getType(), - source, - receiveTag, - group, - &status ); + TNL_ASSERT_NE(group, NullGroup, "Reduce cannot be called with NullGroup"); + MPI_Reduce( const_cast< void* >( ( void*) data ), (void*) reduced_data,count,MPITypeResolver< T >::getType(),op,root,group); #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } + } - template< typename T > - static void Alltoall( const T* sendData, + template< typename T > + static void SendReceive( const T* sendData, int sendCount, + int destination, + int sendTag, T* receiveData, int receiveCount, + int source, + int receiveTag, CommunicationGroup group ) - { + { #ifdef HAVE_MPI - TNL_ASSERT_NE(group, NullGroup, "SendReceive cannot be called with NullGroup"); - MPI_Alltoall( const_cast< void* >( ( void* ) sendData ), - sendCount, - MPITypeResolver< T >::getType(), - ( void* ) receiveData, - receiveCount, - MPITypeResolver< T >::getType(), - group ); + TNL_ASSERT_NE(group, NullGroup, "SendReceive cannot be called with NullGroup"); + MPI_Status status; + MPI_Sendrecv( const_cast< void* >( ( void* ) sendData ), + sendCount, + MPITypeResolver< T >::getType(), + destination, + sendTag, + ( void* ) receiveData, + receiveCount, + MPITypeResolver< T >::getType(), + source, + receiveTag, + group, + &status ); #else - throw Exceptions::MPISupportMissing(); + throw Exceptions::MPISupportMissing(); #endif - } + } + + template< typename T > + static void Alltoall( const T* sendData, + int sendCount, + T* receiveData, + int receiveCount, + CommunicationGroup group ) + { +#ifdef HAVE_MPI + TNL_ASSERT_NE(group, NullGroup, "SendReceive cannot be called with NullGroup"); + MPI_Alltoall( const_cast< void* >( ( void* ) sendData ), + sendCount, + MPITypeResolver< T >::getType(), + ( void* ) receiveData, + receiveCount, + MPITypeResolver< T >::getType(), + group ); +#else + throw Exceptions::MPISupportMissing(); +#endif + } static void writeProlog( Logger& logger ) @@ -480,14 +457,10 @@ class MpiCommunicator static void CreateNewGroup( bool meToo, int myRank, CommunicationGroup &oldGroup, CommunicationGroup &newGroup ) { #ifdef HAVE_MPI - if(meToo) - { + if(meToo) MPI_Comm_split(oldGroup, 1, myRank, &newGroup); - } - else - { + else MPI_Comm_split(oldGroup, MPI_UNDEFINED, GetRank(oldGroup), &newGroup); - } #else throw Exceptions::MPISupportMissing(); #endif @@ -502,7 +475,7 @@ class MpiCommunicator static constexpr int AllGroup = 1; static constexpr int NullGroup = 0; #endif - private : + private: static std::streambuf* psbuf; static std::streambuf* backup; static std::ofstream filestr; @@ -543,7 +516,6 @@ class MpiCommunicator TNL_CHECK_CUDA_DEVICE; //std::cout<<"Node: " << rank << " gpu: " << gpuNumber << std::endl; - #endif #endif } @@ -559,8 +531,6 @@ std::streambuf* MpiCommunicator::backup = nullptr; std::ofstream MpiCommunicator::filestr; bool MpiCommunicator::redirect = true; - } // namespace } // namespace Communicators } // namespace TNL - diff --git a/src/TNL/Communicators/NoDistrCommunicator.h b/src/TNL/Communicators/NoDistrCommunicator.h index 0e270a8436f0495c91d62a2c677ccc891391ddcc..e6af04960986e7c804bb85a1b5b1ed92dd6c0f1e 100644 --- a/src/TNL/Communicators/NoDistrCommunicator.h +++ b/src/TNL/Communicators/NoDistrCommunicator.h @@ -1,8 +1,8 @@ /*************************************************************************** NoDistrCommunicator.h - description ------------------- - begin : 2018/01/09 - copyright : (C) 2018 by Tomas Oberhuber + begin : Jan 9, 2018 + copyright : (C) 2018 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -11,42 +11,40 @@ #pragma once #include +#include #include namespace TNL { namespace Communicators { -namespace { +//! \brief Dummy communicator without any distribution support. class NoDistrCommunicator { - - public: - - typedef int Request; - typedef int CommunicationGroup; + using Request = int; + using CommunicationGroup = int; static constexpr Request NullRequest = -1; static constexpr CommunicationGroup AllGroup = 1; static constexpr CommunicationGroup NullGroup = 0; static void configSetup( Config::ConfigDescription& config, const String& prefix = "" ){}; - + static bool setup( const Config::ParameterContainer& parameters, const String& prefix = "" ) { return true; } - + static void Init(int& argc, char**& argv) {} - + static void setRedirection( bool redirect_ ) {} - + static void setupRedirection(){} static void Finalize(){} static bool IsInitialized() - { + { return true; } @@ -135,6 +133,8 @@ class NoDistrCommunicator int receiveCount, CommunicationGroup group ) { + TNL_ASSERT_EQ( sendCount, receiveCount, "sendCount must be equal to receiveCount for NoDistrCommunicator." ); + memcpy( (void*) receiveData, (const void*) sendData, sendCount * sizeof( T ) ); } static void CreateNewGroup(bool meToo, int myRank, CommunicationGroup &oldGroup, CommunicationGroup &newGroup) @@ -142,9 +142,10 @@ class NoDistrCommunicator newGroup=oldGroup; } - static void writeProlog( Logger& logger ){}; + static void writeProlog( Logger& logger ) + { + } }; -} // namespace } // namespace Communicators } // namespace TNL diff --git a/src/TNL/Containers/Algorithms/CudaReductionKernel.h b/src/TNL/Containers/Algorithms/CudaReductionKernel.h index fbe3df69a9b229f9aa4459e35128bfcc2762d21c..89e13a272dcf2253d8430dc73778257e85737174 100644 --- a/src/TNL/Containers/Algorithms/CudaReductionKernel.h +++ b/src/TNL/Containers/Algorithms/CudaReductionKernel.h @@ -10,6 +10,8 @@ #pragma once +#include // std::pair + #ifdef HAVE_CUDA #include #endif @@ -348,9 +350,10 @@ struct CudaReductionKernelLauncher template< typename Reduction, typename VolatileReduction > - Result finish( const Reduction& reduction, - const VolatileReduction& volatileReduction, - const Result& zero ) + Result + finish( const Reduction& reduction, + const VolatileReduction& volatileReduction, + const Result& zero ) { // Input is the first half of the buffer, output is the second half CudaReductionBuffer& cudaReductionBuffer = CudaReductionBuffer::getInstance(); @@ -377,10 +380,10 @@ struct CudaReductionKernelLauncher template< typename Reduction, typename VolatileReduction > - Result finishWithArgument( IndexType& argument, - const Reduction& reduction, - const VolatileReduction& volatileReduction, - const Result& zero ) + std::pair< Index, Result > + finishWithArgument( const Reduction& reduction, + const VolatileReduction& volatileReduction, + const Result& zero ) { // Input is the first half of the buffer, output is the second half CudaReductionBuffer& cudaReductionBuffer = CudaReductionBuffer::getInstance(); @@ -405,9 +408,9 @@ struct CudaReductionKernelLauncher //// // Copy result on CPU - ResultType result; - ArrayOperations< Devices::Host, Devices::Cuda >::copy( &result, output, 1 ); - ArrayOperations< Devices::Host, Devices::Cuda >::copy( &argument, idxOutput, 1 ); + std::pair< Index, Result > result; + ArrayOperations< Devices::Host, Devices::Cuda >::copy( &result.first, idxOutput, 1 ); + ArrayOperations< Devices::Host, Devices::Cuda >::copy( &result.second, output, 1 ); return result; } diff --git a/src/TNL/Containers/Algorithms/Reduction.h b/src/TNL/Containers/Algorithms/Reduction.h index 975d306b5e4f66aea67d798bd4e61fcc5d3c8644..e2c6d5295606bef5c1e1bf71f988b3a220fe39b2 100644 --- a/src/TNL/Containers/Algorithms/Reduction.h +++ b/src/TNL/Containers/Algorithms/Reduction.h @@ -12,6 +12,8 @@ #pragma once +#include // std::pair + #include #include #include @@ -21,9 +23,7 @@ namespace Containers { namespace Algorithms { template< typename Device > -class Reduction -{ -}; +class Reduction; template<> class Reduction< Devices::Host > @@ -46,9 +46,8 @@ class Reduction< Devices::Host > typename ReductionOperation, typename VolatileReductionOperation, typename DataFetcher > - static Result + static std::pair< Index, Result > reduceWithArgument( const Index size, - Index& argument, ReductionOperation& reduction, VolatileReductionOperation& volatileReduction, DataFetcher& dataFetcher, @@ -76,9 +75,8 @@ class Reduction< Devices::Cuda > typename ReductionOperation, typename VolatileReductionOperation, typename DataFetcher > - static Result + static std::pair< Index, Result > reduceWithArgument( const Index size, - Index& argument, ReductionOperation& reduction, VolatileReductionOperation& volatileReduction, DataFetcher& dataFetcher, @@ -106,14 +104,12 @@ class Reduction< Devices::MIC > typename ReductionOperation, typename VolatileReductionOperation, typename DataFetcher > - static Result + static std::pair< Index, Result > reduceWithArgument( const Index size, - Index& argument, ReductionOperation& reduction, VolatileReductionOperation& volatileReduction, DataFetcher& dataFetcher, const Result& zero ); - }; } // namespace Algorithms diff --git a/src/TNL/Containers/Algorithms/Reduction.hpp b/src/TNL/Containers/Algorithms/Reduction.hpp index 818fe963f836617a332188a0c34952ec129ca9f9..9d54fd7b1e77c404f4bbfc89dafd3d0c99d9ff24 100644 --- a/src/TNL/Containers/Algorithms/Reduction.hpp +++ b/src/TNL/Containers/Algorithms/Reduction.hpp @@ -47,11 +47,11 @@ template< typename Index, typename DataFetcher > Result Reduction< Devices::Host >:: - reduce( const Index size, - ReductionOperation& reduction, - VolatileReductionOperation& volatileReduction, - DataFetcher& dataFetcher, - const Result& zero ) +reduce( const Index size, + ReductionOperation& reduction, + VolatileReductionOperation& volatileReduction, + DataFetcher& dataFetcher, + const Result& zero ) { using IndexType = Index; using ResultType = Result; @@ -143,10 +143,9 @@ template< typename Index, typename ReductionOperation, typename VolatileReductionOperation, typename DataFetcher > -Result +std::pair< Index, Result > Reduction< Devices::Host >:: reduceWithArgument( const Index size, - Index& argument, ReductionOperation& reduction, VolatileReductionOperation& volatileReduction, DataFetcher& dataFetcher, @@ -161,20 +160,19 @@ reduceWithArgument( const Index size, #ifdef HAVE_OPENMP if( TNL::Devices::Host::isOMPEnabled() && size >= 2 * block_size ) { // global result variable - ResultType result = zero; - argument = -1; + std::pair< Index, Result > result( -1, zero ); #pragma omp parallel { // initialize array for thread-local results - ResultType r[ 4 ] = { zero, zero, zero, zero }; IndexType arg[ 4 ] = { 0, 0, 0, 0 }; - bool initialised( false ); + ResultType r[ 4 ] = { zero, zero, zero, zero }; + bool initialized( false ); #pragma omp for nowait for( int b = 0; b < blocks; b++ ) { const IndexType offset = b * block_size; for( int i = 0; i < block_size; i += 4 ) { - if( ! initialised ) { + if( ! initialized ) { arg[ 0 ] = offset + i; arg[ 1 ] = offset + i + 1; arg[ 2 ] = offset + i + 2; @@ -183,7 +181,7 @@ reduceWithArgument( const Index size, r[ 1 ] = dataFetcher( offset + i + 1 ); r[ 2 ] = dataFetcher( offset + i + 2 ); r[ 3 ] = dataFetcher( offset + i + 3 ); - initialised = true; + initialized = true; continue; } reduction( arg[ 0 ], offset + i, r[ 0 ], dataFetcher( offset + i ) ); @@ -208,9 +206,9 @@ reduceWithArgument( const Index size, // inter-thread reduction of local results #pragma omp critical { - if( argument == - 1 ) - argument = arg[ 0 ]; - reduction( argument, arg[ 0 ], result, r[ 0 ] ); + if( result.first == -1 ) + result.first = arg[ 0 ]; + reduction( result.first, arg[ 0 ], result.second, r[ 0 ] ); } } return result; @@ -219,15 +217,15 @@ reduceWithArgument( const Index size, #endif if( blocks > 1 ) { // initialize array for unrolled results - ResultType r[ 4 ] = { zero, zero, zero, zero }; IndexType arg[ 4 ] = { 0, 0, 0, 0 }; - bool initialised( false ); + ResultType r[ 4 ] = { zero, zero, zero, zero }; + bool initialized( false ); // main reduction (explicitly unrolled loop) for( int b = 0; b < blocks; b++ ) { const IndexType offset = b * block_size; for( int i = 0; i < block_size; i += 4 ) { - if( ! initialised ) + if( ! initialized ) { arg[ 0 ] = offset + i; arg[ 1 ] = offset + i + 1; @@ -237,7 +235,7 @@ reduceWithArgument( const Index size, r[ 1 ] = dataFetcher( offset + i + 1 ); r[ 2 ] = dataFetcher( offset + i + 2 ); r[ 3 ] = dataFetcher( offset + i + 3 ); - initialised = true; + initialized = true; continue; } reduction( arg[ 0 ], offset + i, r[ 0 ], dataFetcher( offset + i ) ); @@ -255,14 +253,12 @@ reduceWithArgument( const Index size, reduction( arg[ 0 ], arg[ 2 ], r[ 0 ], r[ 2 ] ); reduction( arg[ 1 ], arg[ 3 ], r[ 1 ], r[ 3 ] ); reduction( arg[ 0 ], arg[ 1 ], r[ 0 ], r[ 1 ] ); - argument = arg[ 0 ]; - return r[ 0 ]; + return std::make_pair( arg[ 0 ], r[ 0 ] ); } else { - ResultType result = dataFetcher( 0 ); - argument = 0; + std::pair< Index, Result > result( 0, dataFetcher( 0 ) ); for( IndexType i = 1; i < size; i++ ) - reduction( argument, i, result, dataFetcher( i ) ); + reduction( result.first, i, result.second, dataFetcher( i ) ); return result; } #ifdef HAVE_OPENMP @@ -277,11 +273,11 @@ template< typename Index, typename DataFetcher > Result Reduction< Devices::Cuda >:: - reduce( const Index size, - ReductionOperation& reduction, - VolatileReductionOperation& volatileReduction, - DataFetcher& dataFetcher, - const Result& zero ) +reduce( const Index size, + ReductionOperation& reduction, + VolatileReductionOperation& volatileReduction, + DataFetcher& dataFetcher, + const Result& zero ) { #ifdef HAVE_CUDA @@ -372,16 +368,15 @@ template< typename Index, typename ReductionOperation, typename VolatileReductionOperation, typename DataFetcher > -Result +std::pair< Index, Result > Reduction< Devices::Cuda >:: reduceWithArgument( const Index size, - Index& argument, ReductionOperation& reduction, VolatileReductionOperation& volatileReduction, DataFetcher& dataFetcher, const Result& zero ) { - #ifdef HAVE_CUDA +#ifdef HAVE_CUDA using IndexType = Index; using ResultType = Result; @@ -449,14 +444,13 @@ reduceWithArgument( const Index size, timer.stop(); std::cout << " Reduction of small data set on CPU took " << timer.getRealTime() << " sec. " << std::endl; #endif - argument = indexArray[ 0 ]; - return resultArray[ 0 ]; + return std::make_pair( indexArray[ 0 ], resultArray[ 0 ] ); } else { /*** * Data can't be safely reduced on host, so continue with the reduction on the CUDA device. */ - auto result = reductionLauncher.finishWithArgument( argument, reduction, volatileReduction, zero ); + auto result = reductionLauncher.finishWithArgument( reduction, volatileReduction, zero ); #ifdef CUDA_REDUCTION_PROFILING timer.stop(); diff --git a/src/TNL/Containers/Algorithms/VectorAssignment.h b/src/TNL/Containers/Algorithms/VectorAssignment.h index 26df5059f46e16c298bd1513be75f1c9d7b9d017..36829be82a70c2ff74f39d275c6a411c21e34873 100644 --- a/src/TNL/Containers/Algorithms/VectorAssignment.h +++ b/src/TNL/Containers/Algorithms/VectorAssignment.h @@ -24,7 +24,7 @@ namespace Algorithms { template< typename Vector, typename T, bool hasSubscriptOperator = HasSubscriptOperator< T >::value > -struct VectorAssignment{}; +struct VectorAssignment; /** * \brief Vector assignment with an operation: +=, -=, *=, /= @@ -33,7 +33,7 @@ template< typename Vector, typename T, bool hasSubscriptOperator = HasSubscriptOperator< T >::value, bool hasSetSizeMethod = HasSetSizeMethod< T >::value > -struct VectorAssignmentWithOperation{}; +struct VectorAssignmentWithOperation; /** * \brief Specialization of ASSIGNEMENT with subscript operator diff --git a/src/TNL/Containers/Algorithms/VectorOperations.h b/src/TNL/Containers/Algorithms/VectorOperations.h index 8eaa83c2dc03d6547b9b5acf3e82f06baca84252..a12b310e36b7d9bf2b458bceaf9db1547162863c 100644 --- a/src/TNL/Containers/Algorithms/VectorOperations.h +++ b/src/TNL/Containers/Algorithms/VectorOperations.h @@ -26,37 +26,6 @@ template<> class VectorOperations< Devices::Host > { public: - template< typename Vector > - static void addElement( Vector& v, - const typename Vector::IndexType i, - const typename Vector::RealType& value ); - - template< typename Vector, typename Scalar > - static void addElement( Vector& v, - const typename Vector::IndexType i, - const typename Vector::RealType& value, - const Scalar thisElementMultiplicator ); - - template< typename Vector, typename Scalar > - static void vectorScalarMultiplication( Vector& v, Scalar alpha ); - - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2 > - static void addVector( Vector1& y, - const Vector2& x, - const Scalar1 alpha, - const Scalar2 thisMultiplicator = 1.0 ); - - template< typename Vector1, typename Vector2, typename Vector3, typename Scalar1, typename Scalar2, typename Scalar3 > - static void addVectors( Vector1& v, - const Vector2& v1, - const Scalar1 multiplicator1, - const Vector3& v2, - const Scalar2 multiplicator2, - const Scalar3 thisMultiplicator = 1.0 ); - - template< typename Vector, typename ResultType = typename Vector::RealType > - static ResultType getVectorSum( const Vector& v ); - template< Algorithms::PrefixSumType Type, typename Vector > static void prefixSum( Vector& v, @@ -74,37 +43,6 @@ template<> class VectorOperations< Devices::Cuda > { public: - template< typename Vector > - static void addElement( Vector& v, - const typename Vector::IndexType i, - const typename Vector::RealType& value ); - - template< typename Vector, typename Scalar > - static void addElement( Vector& v, - const typename Vector::IndexType i, - const typename Vector::RealType& value, - const Scalar thisElementMultiplicator ); - - template< typename Vector, typename Scalar > - static void vectorScalarMultiplication( Vector& v, const Scalar alpha ); - - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2 > - static void addVector( Vector1& y, - const Vector2& x, - const Scalar1 alpha, - const Scalar2 thisMultiplicator = 1.0 ); - - template< typename Vector1, typename Vector2, typename Vector3, typename Scalar1, typename Scalar2, typename Scalar3 > - static void addVectors( Vector1& v, - const Vector2& v1, - const Scalar1 multiplicator1, - const Vector3& v2, - const Scalar2 multiplicator2, - const Scalar3 thisMultiplicator = 1.0 ); - - template< typename Vector, typename ResultType = typename Vector::RealType > - static ResultType getVectorSum( const Vector& v ); - template< Algorithms::PrefixSumType Type, typename Vector > static void prefixSum( Vector& v, diff --git a/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h b/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h index 2949d2b46a8c087541858495be8df7b1e1331dbf..4b53dbcf73eeb8b90a5388bbe7b1d443ff24574d 100644 --- a/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h +++ b/src/TNL/Containers/Algorithms/VectorOperationsCuda_impl.h @@ -18,186 +18,6 @@ namespace TNL { namespace Containers { namespace Algorithms { -template< typename Vector > -void -VectorOperations< Devices::Cuda >:: -addElement( Vector& v, - const typename Vector::IndexType i, - const typename Vector::RealType& value ) -{ - v[ i ] += value; -} - -template< typename Vector, typename Scalar > -void -VectorOperations< Devices::Cuda >:: -addElement( Vector& v, - const typename Vector::IndexType i, - const typename Vector::RealType& value, - const Scalar thisElementMultiplicator ) -{ - v[ i ] = thisElementMultiplicator * v[ i ] + value; -} - -#ifdef HAVE_CUDA -template< typename Real, typename Index, typename Scalar > -__global__ void -vectorScalarMultiplicationCudaKernel( Real* data, - Index size, - Scalar alpha ) -{ - Index elementIdx = blockDim.x * blockIdx.x + threadIdx.x; - const Index maxGridSize = blockDim.x * gridDim.x; - while( elementIdx < size ) - { - data[ elementIdx ] *= alpha; - elementIdx += maxGridSize; - } -} -#endif - -template< typename Vector, typename Scalar > -void -VectorOperations< Devices::Cuda >:: -vectorScalarMultiplication( Vector& v, - const Scalar alpha ) -{ - TNL_ASSERT_GT( v.getSize(), 0, "Vector size must be positive." ); - -#ifdef HAVE_CUDA - typedef typename Vector::IndexType Index; - dim3 blockSize( 0 ), gridSize( 0 ); - const Index& size = v.getSize(); - blockSize.x = 256; - Index blocksNumber = TNL::ceil( ( double ) size / ( double ) blockSize.x ); - gridSize.x = min( blocksNumber, Devices::Cuda::getMaxGridSize() ); - vectorScalarMultiplicationCudaKernel<<< gridSize, blockSize >>>( v.getData(), - size, - alpha ); - TNL_CHECK_CUDA_DEVICE; -#else - throw Exceptions::CudaSupportMissing(); -#endif -} - -template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2 > -void -VectorOperations< Devices::Cuda >:: -addVector( Vector1& _y, - const Vector2& _x, - const Scalar1 alpha, - const Scalar2 thisMultiplicator ) -{ - TNL_ASSERT_GT( _x.getSize(), 0, "Vector size must be positive." ); - TNL_ASSERT_EQ( _x.getSize(), _y.getSize(), "The vector sizes must be the same." ); - -#ifdef HAVE_CUDA - using IndexType = typename Vector1::IndexType; - using RealType = typename Vector1::RealType; - - RealType* y = _y.getData(); - const RealType* x = _x.getData(); - auto add1 = [=] __cuda_callable__ ( IndexType i ) { y[ i ] += alpha * x[ i ]; }; - auto add2 = [=] __cuda_callable__ ( IndexType i ) { y[ i ] = thisMultiplicator * y[ i ] + alpha * x[ i ]; }; - - if( thisMultiplicator == 1.0 ) - ParallelFor< Devices::Cuda >::exec( ( IndexType ) 0, _y.getSize(), add1 ); - else - ParallelFor< Devices::Cuda >::exec( ( IndexType ) 0, _y.getSize(), add2 ); - TNL_CHECK_CUDA_DEVICE; -#else - throw Exceptions::CudaSupportMissing(); -#endif -} - -#ifdef HAVE_CUDA -template< typename Real1, typename Real2, typename Real3, typename Index, - typename Scalar1, typename Scalar2, typename Scalar3 > -__global__ void -vectorAddVectorsCudaKernel( Real1* v, - const Real2* v1, - const Real3* v2, - const Index size, - const Scalar1 multiplicator1, - const Scalar2 multiplicator2, - const Scalar3 thisMultiplicator ) -{ - Index elementIdx = blockDim.x * blockIdx.x + threadIdx.x; - const Index maxGridSize = blockDim.x * gridDim.x; - if( thisMultiplicator == 1.0 ) - while( elementIdx < size ) - { - v[ elementIdx ] += multiplicator1 * v1[ elementIdx ] + - multiplicator2 * v2[ elementIdx ]; - elementIdx += maxGridSize; - } - else - while( elementIdx < size ) - { - v[ elementIdx ] = thisMultiplicator * v[ elementIdx ] + - multiplicator1 * v1[ elementIdx ] + - multiplicator2 * v2[ elementIdx ]; - elementIdx += maxGridSize; - } -} -#endif - -template< typename Vector1, typename Vector2, typename Vector3, - typename Scalar1, typename Scalar2, typename Scalar3 > -void -VectorOperations< Devices::Cuda >:: -addVectors( Vector1& v, - const Vector2& v1, - const Scalar1 multiplicator1, - const Vector3& v2, - const Scalar2 multiplicator2, - const Scalar3 thisMultiplicator ) -{ - TNL_ASSERT_GT( v.getSize(), 0, "Vector size must be positive." ); - TNL_ASSERT_EQ( v.getSize(), v1.getSize(), "The vector sizes must be the same." ); - TNL_ASSERT_EQ( v.getSize(), v2.getSize(), "The vector sizes must be the same." ); - -#ifdef HAVE_CUDA - typedef typename Vector1::IndexType Index; - - const Index& size = v.getSize(); - dim3 cudaBlockSize( 256 ); - dim3 cudaBlocks; - cudaBlocks.x = TNL::min( Devices::Cuda::getMaxGridSize(), Devices::Cuda::getNumberOfBlocks( size, cudaBlockSize.x ) ); - - vectorAddVectorsCudaKernel<<< cudaBlocks, cudaBlockSize >>>( v.getData(), - v1.getData(), - v2.getData(), - size, - multiplicator1, - multiplicator2, - thisMultiplicator); - TNL_CHECK_CUDA_DEVICE; -#else - throw Exceptions::CudaSupportMissing(); -#endif -} - -template< typename Vector, typename ResultType > -ResultType -VectorOperations< Devices::Cuda >:: -getVectorSum( const Vector& v ) -{ - TNL_ASSERT_GT( v.getSize(), 0, "Vector size must be positive." ); - - if( std::is_same< ResultType, bool >::value ) - abort(); - - using RealType = typename Vector::RealType; - using IndexType = typename Vector::IndexType; - - const auto* data = v.getData(); - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> ResultType { return data[ i ]; }; - auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a += b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a += b; }; - return Reduction< Devices::Cuda >::reduce( v.getSize(), reduction, volatileReduction, fetch, ( ResultType ) 0 ); -} - template< Algorithms::PrefixSumType Type, typename Vector > void diff --git a/src/TNL/Containers/Algorithms/VectorOperationsHost_impl.h b/src/TNL/Containers/Algorithms/VectorOperationsHost_impl.h index 916188034b0d9a37e185530c687f87e3e96fa25d..50d591b9f31d11097eeb1047bdba465dda906b95 100644 --- a/src/TNL/Containers/Algorithms/VectorOperationsHost_impl.h +++ b/src/TNL/Containers/Algorithms/VectorOperationsHost_impl.h @@ -17,132 +17,6 @@ namespace TNL { namespace Containers { namespace Algorithms { -static constexpr int OpenMPVectorOperationsThreshold = 512; // TODO: check this threshold -static constexpr int PrefetchDistance = 128; - -template< typename Vector > -void -VectorOperations< Devices::Host >:: -addElement( Vector& v, - const typename Vector::IndexType i, - const typename Vector::RealType& value ) -{ - v[ i ] += value; -} - -template< typename Vector, typename Scalar > -void -VectorOperations< Devices::Host >:: -addElement( Vector& v, - const typename Vector::IndexType i, - const typename Vector::RealType& value, - const Scalar thisElementMultiplicator ) -{ - v[ i ] = thisElementMultiplicator * v[ i ] + value; -} - - - -template< typename Vector, typename Scalar > -void -VectorOperations< Devices::Host >:: -vectorScalarMultiplication( Vector& v, - const Scalar alpha ) -{ - typedef typename Vector::IndexType Index; - - TNL_ASSERT_GT( v.getSize(), 0, "Vector size must be positive." ); - - const Index n = v.getSize(); -#ifdef HAVE_OPENMP -#pragma omp parallel for if( n > OpenMPVectorOperationsThreshold ) // TODO: check this threshold -#endif - for( Index i = 0; i < n; i ++ ) - v[ i ] *= alpha; -} - - -template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2 > -void -VectorOperations< Devices::Host >:: -addVector( Vector1& y, - const Vector2& x, - const Scalar1 alpha, - const Scalar2 thisMultiplicator ) -{ - typedef typename Vector1::IndexType Index; - - TNL_ASSERT_GT( x.getSize(), 0, "Vector size must be positive." ); - TNL_ASSERT_EQ( x.getSize(), y.getSize(), "The vector sizes must be the same." ); - - const Index n = y.getSize(); - - if( thisMultiplicator == 1.0 ) -#ifdef HAVE_OPENMP -#pragma omp parallel for if( TNL::Devices::Host::isOMPEnabled() && n > OpenMPVectorOperationsThreshold ) // TODO: check this threshold -#endif - for( Index i = 0; i < n; i ++ ) - y[ i ] += alpha * x[ i ]; - else -#ifdef HAVE_OPENMP -#pragma omp parallel for if( TNL::Devices::Host::isOMPEnabled() && n > OpenMPVectorOperationsThreshold ) // TODO: check this threshold -#endif - for( Index i = 0; i < n; i ++ ) - y[ i ] = thisMultiplicator * y[ i ] + alpha * x[ i ]; -} - -template< typename Vector1, typename Vector2, typename Vector3, - typename Scalar1, typename Scalar2, typename Scalar3 > -void -VectorOperations< Devices::Host >:: -addVectors( Vector1& v, - const Vector2& v1, - const Scalar1 multiplicator1, - const Vector3& v2, - const Scalar2 multiplicator2, - const Scalar3 thisMultiplicator ) -{ - typedef typename Vector1::IndexType Index; - - TNL_ASSERT_GT( v.getSize(), 0, "Vector size must be positive." ); - TNL_ASSERT_EQ( v.getSize(), v1.getSize(), "The vector sizes must be the same." ); - TNL_ASSERT_EQ( v.getSize(), v2.getSize(), "The vector sizes must be the same." ); - - const Index n = v.getSize(); - if( thisMultiplicator == 1.0 ) -#ifdef HAVE_OPENMP -#pragma omp parallel for if( TNL::Devices::Host::isOMPEnabled() && n > OpenMPVectorOperationsThreshold ) // TODO: check this threshold -#endif - for( Index i = 0; i < n; i ++ ) - v[ i ] += multiplicator1 * v1[ i ] + multiplicator2 * v2[ i ]; - else -#ifdef HAVE_OPENMP -#pragma omp parallel for if( TNL::Devices::Host::isOMPEnabled() && n > OpenMPVectorOperationsThreshold ) // TODO: check this threshold -#endif - for( Index i = 0; i < n; i ++ ) - v[ i ] = thisMultiplicator * v[ i ] + multiplicator1 * v1[ i ] + multiplicator2 * v2[ i ]; -} - -template< typename Vector, typename ResultType > -ResultType -VectorOperations< Devices::Host >:: -getVectorSum( const Vector& v ) -{ - TNL_ASSERT_GT( v.getSize(), 0, "Vector size must be positive." ); - - if( std::is_same< ResultType, bool >::value ) - abort(); - - using RealType = typename Vector::RealType; - using IndexType = typename Vector::IndexType; - - const auto* data = v.getData(); - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> ResultType { return data[ i ]; }; - auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a += b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a += b; }; - return Reduction< Devices::Host >::reduce( v.getSize(), reduction, volatileReduction, fetch, ( ResultType ) 0 ); -} - template< Algorithms::PrefixSumType Type, typename Vector > void VectorOperations< Devices::Host >:: diff --git a/src/TNL/Containers/Array.h b/src/TNL/Containers/Array.h index 8ba517bfa18f0a12fef95a9f0ee7669e7c05a58c..ded017ea5fb069ff6d8d103548f85b8227f2001b 100644 --- a/src/TNL/Containers/Array.h +++ b/src/TNL/Containers/Array.h @@ -116,14 +116,14 @@ class Array const AllocatorType& allocator = AllocatorType() ); /** - * \brief Copy constructor. + * \brief Copy constructor (makes a deep copy). * * \param array The array to be copied. */ explicit Array( const Array& array ); /** - * \brief Copy constructor with a specific allocator. + * \brief Copy constructor with a specific allocator (makes a deep copy). * * \param array The array to be copied. * \param allocator The allocator to be associated with this array. @@ -131,7 +131,7 @@ class Array explicit Array( const Array& array, const AllocatorType& allocator ); /** - * \brief Copy constructor. + * \brief Copy constructor (makes a deep copy). * * \param array The array to be copied. * \param begin The first index which should be copied. @@ -309,20 +309,6 @@ class Array */ ViewType getView( IndexType begin = 0, IndexType end = 0 ); - /** - * \brief Returns a non-modifiable view of the array. - * - * 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. - * \param end The end of the array sub-interval. The default value is 0 - * which is, however, replaced with the array size. - */ - ConstViewType getView( IndexType begin = 0, IndexType end = 0 ) const; - /** * \brief Returns a non-modifiable view of the array. * diff --git a/src/TNL/Containers/Array.hpp b/src/TNL/Containers/Array.hpp index 6c4ef97e693f9cf3b50621b33c0cf26e57f36be3..4d3c558e4f86c0144b85994f71bbb972f84fbf16 100644 --- a/src/TNL/Containers/Array.hpp +++ b/src/TNL/Containers/Array.hpp @@ -365,19 +365,6 @@ getView( IndexType begin, IndexType end ) return ViewType( getData() + begin, end - begin ); } -template< typename Value, - typename Device, - 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 ) - end = getSize(); - return ConstViewType( &getData()[ begin ], end - begin ); -} - template< typename Value, typename Device, typename Index, diff --git a/src/TNL/Containers/ArrayView.h b/src/TNL/Containers/ArrayView.h index f2800f4b07eab7dd3e742bb6f5e0e46edcf44219..eaaba6b2d2d36deafaacc99d70e5f91e8d9f2603 100644 --- a/src/TNL/Containers/ArrayView.h +++ b/src/TNL/Containers/ArrayView.h @@ -170,21 +170,6 @@ public: __cuda_callable__ ViewType getView( const IndexType begin = 0, IndexType end = 0 ); - /** - * \brief Returns a non-modifiable view of the array view. - * - * 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. - * \param end The end of the array view sub-interval. The default value is 0 - * which is, however, replaced with the array size. - */ - __cuda_callable__ - ConstViewType getView( const IndexType begin = 0, IndexType end = 0 ) const; - /** * \brief Returns a non-modifiable view of the array view. * diff --git a/src/TNL/Containers/ArrayView.hpp b/src/TNL/Containers/ArrayView.hpp index 6ca142e52d499c3fafe66be9e80dac14aed26de5..ea7882516cd13647e66e971dbbec11179c1ea520 100644 --- a/src/TNL/Containers/ArrayView.hpp +++ b/src/TNL/Containers/ArrayView.hpp @@ -95,18 +95,6 @@ template< typename Value, __cuda_callable__ typename ArrayView< Value, Device, Index >::ConstViewType ArrayView< Value, Device, Index >:: -getView( const IndexType begin, IndexType end ) const -{ - if( end == 0 ) - end = this->getSize(); - return ConstViewType( &getData()[ begin ], end - begin ); -} - -template< typename Value, - typename Device, - typename Index > -typename ArrayView< Value, Device, Index >::ConstViewType -ArrayView< Value, Device, Index >:: getConstView( const IndexType begin, IndexType end ) const { if( end == 0 ) diff --git a/src/TNL/Containers/DistributedArray.h b/src/TNL/Containers/DistributedArray.h index 1f011f8aa92271591a5129002424ef96ad955750..7f53c724a337ba9052520c250fbafa12c613c5f6 100644 --- a/src/TNL/Containers/DistributedArray.h +++ b/src/TNL/Containers/DistributedArray.h @@ -25,6 +25,7 @@ template< typename Value, class DistributedArray { using CommunicationGroup = typename Communicator::CommunicationGroup; + using LocalArrayType = Containers::Array< Value, Device, Index >; public: using ValueType = Value; @@ -32,9 +33,8 @@ public: using CommunicatorType = Communicator; using IndexType = Index; using LocalRangeType = Subrange< Index >; - using LocalArrayType = Containers::Array< Value, Device, Index >; - using LocalArrayViewType = Containers::ArrayView< Value, Device, Index >; - using ConstLocalArrayViewType = Containers::ArrayView< std::add_const_t< Value >, Device, Index >; + using LocalViewType = Containers::ArrayView< Value, Device, Index >; + using ConstLocalViewType = Containers::ArrayView< std::add_const_t< Value >, Device, Index >; using HostType = DistributedArray< Value, Devices::Host, Index, Communicator >; using CudaType = DistributedArray< Value, Devices::Cuda, Index, Communicator >; using ViewType = DistributedArrayView< Value, Device, Index, Communicator >; @@ -64,21 +64,7 @@ public: * \param end The end of the array view sub-interval. The default value is 0 * which is, however, replaced with the array size. */ - LocalArrayViewType getLocalArrayView(); - - /** - * \brief Returns a non-modifiable view of the local part 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 - * local part of the array view is returned. - * - * \param begin The beginning of the array view sub-interval. It is 0 by - * default. - * \param end The end of the array view sub-interval. The default value is 0 - * which is, however, replaced with the array size. - */ - ConstLocalArrayViewType getLocalArrayView() const; + LocalViewType getLocalView(); /** * \brief Returns a non-modifiable view of the local part of the array. @@ -92,9 +78,9 @@ public: * \param end The end of the array view sub-interval. The default value is 0 * which is, however, replaced with the array size. */ - ConstLocalArrayViewType getConstLocalArrayView() const; + ConstLocalViewType getConstLocalView() const; - void copyFromGlobal( ConstLocalArrayViewType globalArray ); + void copyFromGlobal( ConstLocalViewType globalArray ); static String getType(); @@ -111,11 +97,6 @@ public: */ ViewType getView(); - /** - * \brief Returns a non-modifiable view of the array. - */ - ConstViewType getView() const; - /** * \brief Returns a non-modifiable view of the array. */ @@ -165,7 +146,9 @@ public: // Copy-assignment operator DistributedArray& operator=( const DistributedArray& array ); - template< typename Array > + template< typename Array, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > DistributedArray& operator=( const Array& array ); // Comparison operators @@ -193,4 +176,4 @@ protected: } // namespace Containers } // namespace TNL -#include "DistributedArray_impl.h" +#include "DistributedArray.hpp" diff --git a/src/TNL/Containers/DistributedArray_impl.h b/src/TNL/Containers/DistributedArray.hpp similarity index 89% rename from src/TNL/Containers/DistributedArray_impl.h rename to src/TNL/Containers/DistributedArray.hpp index 3be71d87bed445dc92b07afeb1a5527991602869..b8c65552785ba857563436d89ba6611a0e777b6f 100644 --- a/src/TNL/Containers/DistributedArray_impl.h +++ b/src/TNL/Containers/DistributedArray.hpp @@ -72,9 +72,9 @@ template< typename Value, typename Device, typename Index, typename Communicator > -typename DistributedArray< Value, Device, Index, Communicator >::LocalArrayViewType +typename DistributedArray< Value, Device, Index, Communicator >::LocalViewType DistributedArray< Value, Device, Index, Communicator >:: -getLocalArrayView() +getLocalView() { return localData.getView(); } @@ -83,20 +83,9 @@ template< typename Value, typename Device, typename Index, typename Communicator > -typename DistributedArray< Value, Device, Index, Communicator >::ConstLocalArrayViewType +typename DistributedArray< Value, Device, Index, Communicator >::ConstLocalViewType DistributedArray< Value, Device, Index, Communicator >:: -getLocalArrayView() const -{ - return localData.getConstView(); -} - -template< typename Value, - typename Device, - typename Index, - typename Communicator > -typename DistributedArray< Value, Device, Index, Communicator >::ConstLocalArrayViewType -DistributedArray< Value, Device, Index, Communicator >:: -getConstLocalArrayView() const +getConstLocalView() const { return localData.getConstView(); } @@ -108,12 +97,12 @@ template< typename Value, typename Communicator > void DistributedArray< Value, Device, Index, Communicator >:: -copyFromGlobal( ConstLocalArrayViewType globalArray ) +copyFromGlobal( ConstLocalViewType globalArray ) { TNL_ASSERT_EQ( getSize(), globalArray.getSize(), "given global array has different size than the distributed array" ); - LocalArrayViewType localView( localData ); + LocalViewType localView( localData ); const LocalRangeType localRange = getLocalRange(); auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable @@ -137,18 +126,7 @@ typename DistributedArray< Value, Device, Index, Communicator >::ViewType DistributedArray< Value, Device, Index, Communicator >:: getView() { - return ViewType( getLocalRange(), getSize(), getCommunicationGroup(), getLocalArrayView() ); -} - -template< typename Value, - typename Device, - typename Index, - typename Communicator > -typename DistributedArray< Value, Device, Index, Communicator >::ConstViewType -DistributedArray< Value, Device, Index, Communicator >:: -getView() const -{ - return ConstViewType( getLocalRange(), getSize(), getCommunicationGroup(), getLocalArrayView() ); + return ViewType( getLocalRange(), getSize(), getCommunicationGroup(), getLocalView() ); } template< typename Value, @@ -159,7 +137,7 @@ typename DistributedArray< Value, Device, Index, Communicator >::ConstViewType DistributedArray< Value, Device, Index, Communicator >:: getConstView() const { - return ConstViewType( getLocalRange(), getSize(), getCommunicationGroup(), getLocalArrayView() ); + return ConstViewType( getLocalRange(), getSize(), getCommunicationGroup(), getConstLocalView() ); } template< typename Value, @@ -221,7 +199,7 @@ setLike( const Array& array ) localRange = array.getLocalRange(); globalSize = array.getSize(); group = array.getCommunicationGroup(); - localData.setLike( array.getLocalArrayView() ); + localData.setLike( array.getConstLocalView() ); } template< typename Value, @@ -330,7 +308,7 @@ DistributedArray< Value, Device, Index, Communicator >:: operator=( const DistributedArray& array ) { setLike( array ); - localData = array.getLocalArrayView(); + localData = array.getConstLocalView(); return *this; } @@ -338,13 +316,13 @@ template< typename Value, typename Device, typename Index, typename Communicator > - template< typename Array > + template< typename Array, typename..., typename > DistributedArray< Value, Device, Index, Communicator >& DistributedArray< Value, Device, Index, Communicator >:: operator=( const Array& array ) { setLike( array ); - localData = array.getLocalArrayView(); + localData = array.getConstLocalView(); return *this; } @@ -363,7 +341,7 @@ operator==( const Array& array ) const const bool localResult = localRange == array.getLocalRange() && globalSize == array.getSize() && - localData == array.getLocalArrayView(); + localData == array.getConstLocalView(); bool result = true; if( group != CommunicatorType::NullGroup ) CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, group ); diff --git a/src/TNL/Containers/DistributedArrayView.h b/src/TNL/Containers/DistributedArrayView.h index d882ad36cdda39b65ee6b994faea4d4578e0d79c..82a662e39cebecc50735444888ba4c065a5a4287 100644 --- a/src/TNL/Containers/DistributedArrayView.h +++ b/src/TNL/Containers/DistributedArrayView.h @@ -32,8 +32,8 @@ public: using CommunicatorType = Communicator; using IndexType = Index; using LocalRangeType = Subrange< Index >; - using LocalArrayViewType = Containers::ArrayView< Value, Device, Index >; - using ConstLocalArrayViewType = Containers::ArrayView< std::add_const_t< Value >, Device, Index >; + using LocalViewType = Containers::ArrayView< Value, Device, Index >; + using ConstLocalViewType = Containers::ArrayView< std::add_const_t< Value >, Device, Index >; using HostType = DistributedArrayView< Value, Devices::Host, Index, Communicator >; using CudaType = DistributedArrayView< Value, Devices::Cuda, Index, Communicator >; using ViewType = DistributedArrayView< Value, Device, Index, Communicator >; @@ -41,7 +41,7 @@ public: // Initialization by raw data __cuda_callable__ - DistributedArrayView( const LocalRangeType& localRange, IndexType globalSize, CommunicationGroup group, LocalArrayViewType localData ) + DistributedArrayView( const LocalRangeType& localRange, IndexType globalSize, CommunicationGroup group, LocalViewType localData ) : localRange(localRange), globalSize(globalSize), group(group), localData(localData) {} @@ -91,7 +91,9 @@ public: // must match (i.e. copy-assignment cannot resize). DistributedArrayView& operator=( const DistributedArrayView& view ); - template< typename Array > + template< typename Array, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > DistributedArrayView& operator=( const Array& array ); @@ -99,11 +101,11 @@ public: CommunicationGroup getCommunicationGroup() const; - LocalArrayViewType getLocalArrayView(); + LocalViewType getLocalView(); - ConstLocalArrayViewType getLocalArrayView() const; + ConstLocalViewType getConstLocalView() const; - void copyFromGlobal( ConstLocalArrayViewType globalArray ); + void copyFromGlobal( ConstLocalViewType globalArray ); static String getType(); @@ -158,10 +160,10 @@ protected: LocalRangeType localRange; IndexType globalSize = 0; CommunicationGroup group = Communicator::NullGroup; - LocalArrayViewType localData; + LocalViewType localData; }; } // namespace Containers } // namespace TNL -#include "DistributedArrayView_impl.h" +#include "DistributedArrayView.hpp" diff --git a/src/TNL/Containers/DistributedArrayView_impl.h b/src/TNL/Containers/DistributedArrayView.hpp similarity index 95% rename from src/TNL/Containers/DistributedArrayView_impl.h rename to src/TNL/Containers/DistributedArrayView.hpp index 23b3695a1db50d21a89be093347d62cb3f5d3487..5cb9c10ed0e5ce4155f9b48f20226baa9106e1a1 100644 --- a/src/TNL/Containers/DistributedArrayView_impl.h +++ b/src/TNL/Containers/DistributedArrayView.hpp @@ -28,7 +28,7 @@ DistributedArrayView( const DistributedArrayView< Value_, Device, Index, Communi : localRange( view.getLocalRange() ), globalSize( view.getSize() ), group( view.getCommunicationGroup() ), - localData( view.getLocalArrayView() ) + localData( view.getConstLocalView() ) {} template< typename Value, @@ -43,7 +43,7 @@ bind( DistributedArrayView view ) localRange = view.getLocalRange(); globalSize = view.getSize(); group = view.getCommunicationGroup(); - localData.bind( view.getLocalArrayView() ); + localData.bind( view.getLocalView() ); } template< typename Value, @@ -96,7 +96,7 @@ operator=( const DistributedArrayView& view ) TNL_ASSERT_EQ( getSize(), view.getSize(), "The sizes of the array views must be equal, views are not resizable." ); TNL_ASSERT_EQ( getLocalRange(), view.getLocalRange(), "The local ranges must be equal, views are not resizable." ); TNL_ASSERT_EQ( getCommunicationGroup(), view.getCommunicationGroup(), "The communication groups of the array views must be equal." ); - localData = view.getLocalArrayView(); + localData = view.getConstLocalView(); return *this; } @@ -104,7 +104,7 @@ template< typename Value, typename Device, typename Index, typename Communicator > - template< typename Array > + template< typename Array, typename..., typename > DistributedArrayView< Value, Device, Index, Communicator >& DistributedArrayView< Value, Device, Index, Communicator >:: operator=( const Array& array ) @@ -112,7 +112,7 @@ operator=( const Array& array ) TNL_ASSERT_EQ( getSize(), array.getSize(), "The global sizes must be equal, views are not resizable." ); TNL_ASSERT_EQ( getLocalRange(), array.getLocalRange(), "The local ranges must be equal, views are not resizable." ); TNL_ASSERT_EQ( getCommunicationGroup(), array.getCommunicationGroup(), "The communication groups must be equal." ); - localData = array.getLocalArrayView(); + localData = array.getConstLocalView(); return *this; } @@ -143,9 +143,9 @@ template< typename Value, typename Device, typename Index, typename Communicator > -typename DistributedArrayView< Value, Device, Index, Communicator >::LocalArrayViewType +typename DistributedArrayView< Value, Device, Index, Communicator >::LocalViewType DistributedArrayView< Value, Device, Index, Communicator >:: -getLocalArrayView() +getLocalView() { return localData; } @@ -154,9 +154,9 @@ template< typename Value, typename Device, typename Index, typename Communicator > -typename DistributedArrayView< Value, Device, Index, Communicator >::ConstLocalArrayViewType +typename DistributedArrayView< Value, Device, Index, Communicator >::ConstLocalViewType DistributedArrayView< Value, Device, Index, Communicator >:: -getLocalArrayView() const +getConstLocalView() const { return localData; } @@ -167,12 +167,12 @@ template< typename Value, typename Communicator > void DistributedArrayView< Value, Device, Index, Communicator >:: -copyFromGlobal( ConstLocalArrayViewType globalArray ) +copyFromGlobal( ConstLocalViewType globalArray ) { TNL_ASSERT_EQ( getSize(), globalArray.getSize(), "given global array has different size than the distributed array view" ); - LocalArrayViewType localView( localData ); + LocalViewType localView( localData ); const LocalRangeType localRange = getLocalRange(); auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable @@ -315,7 +315,7 @@ operator==( const Array& array ) const const bool localResult = localRange == array.getLocalRange() && globalSize == array.getSize() && - localData == array.getLocalArrayView(); + localData == array.getConstLocalView(); bool result = true; if( group != CommunicatorType::NullGroup ) CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, group ); diff --git a/src/TNL/Containers/DistributedVector.h b/src/TNL/Containers/DistributedVector.h index 642fadebb928ed4c91d9ef9ccd13ec4fa52c51ad..75f204dccba363da9b5d079091680bd4272f03df 100644 --- a/src/TNL/Containers/DistributedVector.h +++ b/src/TNL/Containers/DistributedVector.h @@ -32,8 +32,8 @@ public: using DeviceType = Device; using CommunicatorType = Communicator; using IndexType = Index; - using LocalVectorViewType = Containers::VectorView< Real, Device, Index >; - using ConstLocalVectorViewType = Containers::VectorView< std::add_const_t< Real >, Device, Index >; + using LocalViewType = Containers::VectorView< Real, Device, Index >; + using ConstLocalViewType = Containers::VectorView< std::add_const_t< Real >, Device, Index >; using HostType = DistributedVector< Real, Devices::Host, Index, Communicator >; using CudaType = DistributedVector< Real, Devices::Cuda, Index, Communicator >; using ViewType = DistributedVectorView< Real, Device, Index, Communicator >; @@ -44,19 +44,15 @@ public: using BaseType::operator=; // we return only the view so that the user cannot resize it - LocalVectorViewType getLocalVectorView(); + LocalViewType getLocalView(); - ConstLocalVectorViewType getLocalVectorView() const; - - ConstLocalVectorViewType getConstLocalVectorView() const; + ConstLocalViewType getConstLocalView() const; /** * \brief Returns a modifiable view of the vector. */ ViewType getView(); - ConstViewType getView() const; - /** * \brief Returns a non-modifiable view of the vector. */ @@ -81,46 +77,55 @@ public: /* * Usual Vector methods follow below. */ - void addElement( IndexType i, - RealType value ); - - template< typename Scalar > - void addElement( IndexType i, - RealType value, - Scalar thisElementMultiplicator ); - - template< typename Vector > - DistributedVector& operator-=( const Vector& vector ); - - template< typename Vector > - DistributedVector& operator+=( const Vector& vector ); - - template< typename Scalar > + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > + DistributedVector& operator=( Scalar c ); + + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > + DistributedVector& operator+=( Scalar c ); + + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > + DistributedVector& operator-=( Scalar c ); + + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > DistributedVector& operator*=( Scalar c ); - template< typename Scalar > + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > DistributedVector& operator/=( Scalar c ); - template< typename ResultType = RealType > - ResultType sum() const; + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVector& operator=( const Vector& vector ); - //! Computes scalar dot product - template< typename Vector > - Real scalarProduct( const Vector& v ) const; + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVector& operator+=( const Vector& vector ); + + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVector& operator-=( const Vector& vector ); - //! Computes this = thisMultiplicator * this + alpha * x. - template< typename Vector, typename Scalar1 = Real, typename Scalar2 = Real > - void addVector( const Vector& x, - Scalar1 alpha = 1.0, - Scalar2 thisMultiplicator = 1.0 ); + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVector& operator*=( const Vector& vector ); - //! Computes this = thisMultiplicator * this + multiplicator1 * v1 + multiplicator2 * v2. - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2, typename Scalar3 = Real > - void addVectors( const Vector1& v1, - Scalar1 multiplicator1, - const Vector2& v2, - Scalar2 multiplicator2, - Scalar3 thisMultiplicator = 1.0 ); + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVector& operator/=( const Vector& vector ); void computePrefixSum(); @@ -134,5 +139,5 @@ public: } // namespace Containers } // namespace TNL -#include +#include #include diff --git a/src/TNL/Containers/DistributedVector_impl.h b/src/TNL/Containers/DistributedVector.hpp similarity index 65% rename from src/TNL/Containers/DistributedVector_impl.h rename to src/TNL/Containers/DistributedVector.hpp index ff37b53074101b7e2d80b6a7527dc8fb993aa129..73781c90640eebe0270082174e0a871b1fce511d 100644 --- a/src/TNL/Containers/DistributedVector_impl.h +++ b/src/TNL/Containers/DistributedVector.hpp @@ -23,33 +23,22 @@ template< typename Real, typename Device, typename Index, typename Communicator > -typename DistributedVector< Real, Device, Index, Communicator >::LocalVectorViewType +typename DistributedVector< Real, Device, Index, Communicator >::LocalViewType DistributedVector< Real, Device, Index, Communicator >:: -getLocalVectorView() +getLocalView() { - return this->getLocalArrayView(); + return BaseType::getLocalView(); } template< typename Real, typename Device, typename Index, typename Communicator > -typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType +typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalViewType DistributedVector< Real, Device, Index, Communicator >:: -getLocalVectorView() const +getConstLocalView() const { - return this->getLocalArrayView(); -} - -template< typename Real, - typename Device, - typename Index, - typename Communicator > -typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType -DistributedVector< Real, Device, Index, Communicator >:: -getConstLocalVectorView() const -{ - return this->getLocalArrayView(); + return BaseType::getConstLocalView(); } template< typename Value, @@ -60,18 +49,7 @@ typename DistributedVector< Value, Device, Index, Communicator >::ViewType DistributedVector< Value, Device, Index, Communicator >:: getView() { - return ViewType( this->getLocalRange(), this->getSize(), this->getCommunicationGroup(), this->getLocalVectorView() ); -} - -template< typename Value, - typename Device, - typename Index, - typename Communicator > -typename DistributedVector< Value, Device, Index, Communicator >::ConstViewType -DistributedVector< Value, Device, Index, Communicator >:: -getView() const -{ - return ConstViewType( this->getLocalRange(), this->getSize(), this->getCommunicationGroup(), this->getLocalVectorView() ); + return ViewType( this->getLocalRange(), this->getSize(), this->getCommunicationGroup(), this->getLocalView() ); } template< typename Value, @@ -82,7 +60,7 @@ typename DistributedVector< Value, Device, Index, Communicator >::ConstViewType DistributedVector< Value, Device, Index, Communicator >:: getConstView() const { - return ConstViewType( this->getLocalRange(), this->getSize(), this->getCommunicationGroup(), this->getLocalVectorView() ); + return ConstViewType( this->getLocalRange(), this->getSize(), this->getCommunicationGroup(), this->getConstLocalView() ); } template< typename Value, @@ -142,41 +120,45 @@ template< typename Real, typename Device, typename Index, typename Communicator > -void + template< typename Vector, typename..., typename > +DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: -addElement( IndexType i, - RealType value ) +operator=( const Vector& vector ) { + this->setLike( vector ); if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - const IndexType li = this->getLocalRange().getLocalIndex( i ); - LocalVectorViewType view = getLocalVectorView(); - view.addElement( li, value ); + getLocalView() = vector.getConstLocalView(); } + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Scalar > -void + template< typename Vector, typename..., typename > +DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: -addElement( IndexType i, - RealType value, - Scalar thisElementMultiplicator ) +operator+=( const Vector& vector ) { + TNL_ASSERT_EQ( this->getSize(), vector.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), vector.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), vector.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - const IndexType li = this->getLocalRange().getLocalIndex( i ); - LocalVectorViewType view = getLocalVectorView(); - view.addElement( li, value, thisElementMultiplicator ); + getLocalView() += vector.getConstLocalView(); } + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector > + template< typename Vector, typename..., typename > DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: operator-=( const Vector& vector ) @@ -189,7 +171,7 @@ operator-=( const Vector& vector ) "Multiary operations are supported only on vectors within the same communication group." ); if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView() -= vector.getLocalVectorView(); + getLocalView() -= vector.getConstLocalView(); } return *this; } @@ -198,10 +180,10 @@ template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector > + template< typename Vector, typename..., typename > DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: -operator+=( const Vector& vector ) +operator*=( const Vector& vector ) { TNL_ASSERT_EQ( this->getSize(), vector.getSize(), "Vector sizes must be equal." ); @@ -211,7 +193,7 @@ operator+=( const Vector& vector ) "Multiary operations are supported only on vectors within the same communication group." ); if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView() += vector.getLocalVectorView(); + getLocalView() *= vector.getConstLocalView(); } return *this; } @@ -220,13 +202,20 @@ template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Scalar > + template< typename Vector, typename..., typename > DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: -operator*=( Scalar c ) +operator/=( const Vector& vector ) { + TNL_ASSERT_EQ( this->getSize(), vector.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), vector.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), vector.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView() *= c; + getLocalView() /= vector.getConstLocalView(); } return *this; } @@ -235,13 +224,13 @@ template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Scalar > + template< typename Scalar, typename..., typename > DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: -operator/=( Scalar c ) +operator=( Scalar c ) { if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView() /= c; + getLocalView() = c; } return *this; } @@ -250,94 +239,60 @@ template< typename Real, typename Device, typename Index, typename Communicator > - template< typename ResultType > -ResultType + template< typename Scalar, typename..., typename > +DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: -sum() const +operator+=( Scalar c ) { - const auto group = this->getCommunicationGroup(); - ResultType result = Containers::Algorithms::ParallelReductionSum< Real, ResultType >::initialValue(); - if( group != CommunicatorType::NullGroup ) { - const ResultType localResult = getLocalVectorView().sum(); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalView() += c; } - return result; + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector > -Real + template< typename Scalar, typename..., typename > +DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: -scalarProduct( const Vector& v ) const +operator-=( Scalar c ) { - const auto group = this->getCommunicationGroup(); - Real result = Containers::Algorithms::ParallelReductionScalarProduct< Real, typename Vector::RealType >::initialValue(); - if( group != CommunicatorType::NullGroup ) { - const Real localResult = getLocalVectorView().scalarProduct( v.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalView() -= c; } - return result; + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector, typename Scalar1, typename Scalar2 > -void + template< typename Scalar, typename..., typename > +DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: -addVector( const Vector& x, - Scalar1 alpha, - Scalar2 thisMultiplicator ) +operator*=( Scalar c ) { - TNL_ASSERT_EQ( this->getSize(), x.getSize(), - "Vector sizes must be equal." ); - TNL_ASSERT_EQ( this->getLocalRange(), x.getLocalRange(), - "Multiary operations are supported only on vectors which are distributed the same way." ); - TNL_ASSERT_EQ( this->getCommunicationGroup(), x.getCommunicationGroup(), - "Multiary operations are supported only on vectors within the same communication group." ); - if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView().addVector( x.getLocalVectorView(), alpha, thisMultiplicator ); + getLocalView() *= c; } + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2, typename Scalar3 > -void + template< typename Scalar, typename..., typename > +DistributedVector< Real, Device, Index, Communicator >& DistributedVector< Real, Device, Index, Communicator >:: -addVectors( const Vector1& v1, - Scalar1 multiplicator1, - const Vector2& v2, - Scalar2 multiplicator2, - Scalar3 thisMultiplicator ) +operator/=( Scalar c ) { - TNL_ASSERT_EQ( this->getSize(), v1.getSize(), - "Vector sizes must be equal." ); - TNL_ASSERT_EQ( this->getLocalRange(), v1.getLocalRange(), - "Multiary operations are supported only on vectors which are distributed the same way." ); - TNL_ASSERT_EQ( this->getCommunicationGroup(), v1.getCommunicationGroup(), - "Multiary operations are supported only on vectors within the same communication group." ); - TNL_ASSERT_EQ( this->getSize(), v2.getSize(), - "Vector sizes must be equal." ); - TNL_ASSERT_EQ( this->getLocalRange(), v2.getLocalRange(), - "Multiary operations are supported only on vectors which are distributed the same way." ); - TNL_ASSERT_EQ( this->getCommunicationGroup(), v2.getCommunicationGroup(), - "Multiary operations are supported only on vectors within the same communication group." ); - if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView().addVectors( v1.getLocalVectorView(), - multiplicator1, - v2.getLocalVectorView(), - multiplicator2, - thisMultiplicator ); + getLocalView() /= c; } + return *this; } template< typename Real, diff --git a/src/TNL/Containers/DistributedVectorExpressions.h b/src/TNL/Containers/DistributedVectorExpressions.h index 3b2e030df6b4214f22eea36297201058d5a5c91b..ef33100dcd0d17043601cc2700308cc4d944411f 100644 --- a/src/TNL/Containers/DistributedVectorExpressions.h +++ b/src/TNL/Containers/DistributedVectorExpressions.h @@ -2,7 +2,7 @@ DistributedVectorExpressions.h - description ------------------- begin : Jul 1, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,14 +10,9 @@ #pragma once -#include -#include -#include #include -#include -#include -#include -#include + +#include "DistributedVector.h" namespace TNL { namespace Containers { @@ -29,8 +24,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto operator+( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Expressions::Addition, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Expressions::Addition >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -38,35 +32,28 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto operator+( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using ConstView = typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Expressions::Addition, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Expressions::Addition >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator+( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Addition >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator+( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Addition >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator+( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Addition >( a, b ); } //// @@ -76,8 +63,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto operator-( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Expressions::Subtraction, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Expressions::Subtraction >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -85,35 +71,28 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto operator-( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using ConstView = typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Expressions::Subtraction, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Expressions::Subtraction >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator-( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Subtraction >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator-( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Subtraction >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator-( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Subtraction >( a, b ); } //// @@ -123,8 +102,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto operator*( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Expressions::Multiplication, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Expressions::Multiplication >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -132,35 +110,28 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto operator*( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using ConstView = typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Expressions::Multiplication, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Expressions::Multiplication >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator*( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Multiplication >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator*( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Multiplication >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator*( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Multiplication >( a, b ); } //// @@ -170,8 +141,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto operator/( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Expressions::Division, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Expressions::Division >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -179,314 +149,262 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto operator/( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using ConstView = typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Expressions::Division, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Expressions::Division >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator/( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Division >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator/( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Division >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator/( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Division >( a, b ); } //// // Comparison operations - operator == template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator==( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator==( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template EQ< Communicator >( a.getLocalVectorView(), b, a.getCommunicatorGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::EQ( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator==( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template EQ< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index1, typename Index2, typename Communicator > -bool operator==( const DistributedVector< Real1, Device1, Index1, Communicator >& a, const DistributedVector< Real2, Device2, Index2, Communicator >& b ) -{ - if( a.getCommunicationGroup() != b.getCommunicationGroup() ) - return false; - const bool localResult = - a.getLocalRange() == b.getLocalRange() && - a.getSize() == b.getSize() && - a.getLocalArrayView() == b.getLocalArrayView(); - bool result = true; - if( a.getCommunicationGroup() != Communicator::NullGroup ) - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); - return result; -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index1, typename Index2, typename Communicator > -bool operator==( const DistributedVectorView< Real1, Device1, Index1, Communicator >& a, const DistributedVector< Real2, Device2, Index2, Communicator >& b ) -{ - if( a.getCommunicationGroup() != b.getCommunicationGroup() ) - return false; - const bool localResult = - a.getLocalRange() == b.getLocalRange() && - a.getSize() == b.getSize() && - a.getLocalArrayView() == b.getLocalArrayView(); - bool result = true; - if( a.getCommunicationGroup() != Communicator::NullGroup ) - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); - return result; -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index1, typename Index2, typename Communicator > -bool operator==( const DistributedVector< Real1, Device1, Index1, Communicator >& a, const DistributedVectorView< Real2, Device2, Index2, Communicator >& b ) -{ - if( a.getCommunicationGroup() != b.getCommunicationGroup() ) - return false; - const bool localResult = - a.getLocalRange() == b.getLocalRange() && - a.getSize() == b.getSize() && - a.getLocalArrayView() == b.getLocalArrayView(); - bool result = true; - if( a.getCommunicationGroup() != Communicator::NullGroup ) - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); - return result; +bool +operator==( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) +{ + return Expressions::DistributedComparison< ET, std::decay_t >::EQ( a, b ); +} + +template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > +bool +operator==( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b ) +{ + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); +} + +template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > +bool +operator==( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b ) +{ + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); +} + +template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > +bool +operator==( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b ) +{ + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); } //// // Comparison operations - operator != template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator!=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator!=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template NE< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::NE( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator!=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) +bool +operator!=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template NE< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::NE( a, b ); } template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool operator!=( const DistributedVector< Real1, Device1, Index >& a, const DistributedVector< Real2, Device2, Index >& b ) +bool +operator!=( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b ) { - return ! operator==( a, b ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool operator!=( const DistributedVectorView< Real1, Device1, Index >& a, const DistributedVector< Real2, Device2, Index >& b ) +bool +operator!=( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b ) { - return ! operator==( a, b ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool operator!=( const DistributedVector< Real1, Device1, Index >& a, const DistributedVectorView< Real2, Device2, Index >& b ) +bool +operator!=( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b ) { - return ! operator==( a, b ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } //// // Comparison operations - operator < template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator<( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator<( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template LT< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::LT( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator<( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) +bool +operator<( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LT< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::LT( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) +bool +operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LT< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) +bool +operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LT< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) +bool +operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LT< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } //// // Comparison operations - operator <= template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator<=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator<=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template LE< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::LE( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator<=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) +bool +operator<=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LE< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::LE( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) +bool +operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LE< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) +bool +operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LE< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) +bool +operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LE< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } //// // Comparison operations - operator > template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator>( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator>( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template GT< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::GT( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator>( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) +bool +operator>( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GT< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::GT( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) +bool +operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GT< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) +bool +operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GT< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) +bool +operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GT< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } //// // Comparison operations - operator >= template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator>=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator>=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template GE< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::GE( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator>=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) +bool +operator>=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GE< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::GE( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) +bool +operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GE< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) +bool +operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GE< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) +bool +operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GE< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } //// @@ -495,86 +413,52 @@ template< typename Real, typename Device, typename Index, typename Communicator auto operator-( const DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedUnaryExpressionTemplate< ConstView, Expressions::Minus, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Expressions::Minus >( a ); } //// // Scalar product template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -auto +Real operator,( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using CommunicatorType = typename DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = TNL::sum( a.getLocalVectorView() * b ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return Expressions::DistributedExpressionSum( a * b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -auto +Real operator,( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) { - using CommunicatorType = typename DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = TNL::sum( a * b.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return Expressions::DistributedExpressionSum( a * b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator,( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using CommunicatorType = typename DistributedVector< Real1, Device, Index, Communicator >::CommunicatorType; - using Real = decltype( TNL::sum( a.getLocalVectorView() * b.getLocalVectorView() ) ); - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = TNL::sum( a.getLocalVectorView() * b.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return Expressions::DistributedExpressionSum( a * b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator,( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) { - using CommunicatorType = typename DistributedVector< Real1, Device, Index, Communicator >::CommunicatorType; - using Real = decltype( TNL::sum( a.getLocalVectorView() * b.getLocalVectorView() ) ); - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = TNL::sum( a.getLocalVectorView() * b.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return Expressions::DistributedExpressionSum( a * b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator,( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using CommunicatorType = typename DistributedVector< Real1, Device, Index, Communicator >::CommunicatorType; - using Real = decltype( TNL::sum( a.getLocalVectorView() * b.getLocalVectorView() ) ); - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = TNL::sum( a.getLocalVectorView() * b.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return Expressions::DistributedExpressionSum( a * b ); } -} // namespace Containers +} //namespace Containers -///// -// Functions are supposed to be in namespace TNL +//// +// All functions are supposed to be in namespace TNL //// // Min @@ -583,8 +467,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto min( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Min, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Containers::Expressions::Min >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -592,35 +475,28 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto min( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Min, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto min( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename Containers::DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename Containers::DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto min( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename Containers::DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename Containers::DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto min( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename Containers::DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename Containers::DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } //// @@ -630,8 +506,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto max( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Max, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Containers::Expressions::Max >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -639,35 +514,28 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto max( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Max, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto max( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename Containers::DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename Containers::DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto max( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename Containers::DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename Containers::DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto max( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename Containers::DistributedVector< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename Containers::DistributedVector< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } //// @@ -677,7 +545,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto dot( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) { - return ( a, b ); + return (a, b); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -685,28 +553,28 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto dot( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b ) { - return ( a, b ); + return (a, b); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto dot( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) { - return ( a, b ); + return (a, b); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto dot( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) { - return ( a, b ); + return (a, b); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto dot( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - return ( a, b ); + return (a, b); } @@ -716,98 +584,97 @@ template< typename Real, typename Device, typename Index, typename Communicator auto abs( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Abs, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Abs >( a ); } //// -// Sine +// Power +template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType > +auto +pow( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ExpType& exp ) +{ + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ExpType, Containers::Expressions::Pow >( a, exp ); +} + +//// +// Exp template< typename Real, typename Device, typename Index, typename Communicator > auto -sin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +exp( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Sin, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Exp >( a ); } //// -// Cosine +// Sqrt template< typename Real, typename Device, typename Index, typename Communicator > auto -cos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +sqrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Cos, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sqrt >( a ); } //// -// Tangent +// Cbrt template< typename Real, typename Device, typename Index, typename Communicator > auto -tan( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +cbrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Tan, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cbrt >( a ); } //// -// Sqrt +// Log template< typename Real, typename Device, typename Index, typename Communicator > auto -sqrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +log( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Sqrt, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log >( a ); } //// -// Cbrt +// Log10 template< typename Real, typename Device, typename Index, typename Communicator > auto -cbrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +log10( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Cbrt, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log10 >( a ); } //// -// Power -template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType > +// Log2 +template< typename Real, typename Device, typename Index, typename Communicator > auto -pow( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ExpType& exp ) +log2( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Pow, ExpType, Communicator >( a.getLocalVectorView(), exp, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log2 >( a ); } //// -// Floor +// Sine template< typename Real, typename Device, typename Index, typename Communicator > auto -floor( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +sin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Floor, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sin >( a ); } //// -// Ceil +// Cosine template< typename Real, typename Device, typename Index, typename Communicator > auto -ceil( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +cos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Ceil, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cos >( a ); } //// -// Acos +// Tangent template< typename Real, typename Device, typename Index, typename Communicator > auto -acos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +tan( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Acos, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tan >( a ); } //// @@ -816,8 +683,16 @@ template< typename Real, typename Device, typename Index, typename Communicator auto asin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Asin, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asin >( a ); +} + +//// +// Acos +template< typename Real, typename Device, typename Index, typename Communicator > +auto +acos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acos >( a ); } //// @@ -826,8 +701,16 @@ template< typename Real, typename Device, typename Index, typename Communicator auto atan( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Atan, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atan >( a ); +} + +//// +// Sinh +template< typename Real, typename Device, typename Index, typename Communicator > +auto +sinh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sinh >( a ); } //// @@ -836,8 +719,7 @@ template< typename Real, typename Device, typename Index, typename Communicator auto cosh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Cosh, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cosh >( a ); } //// @@ -846,48 +728,52 @@ template< typename Real, typename Device, typename Index, typename Communicator auto tanh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Tanh, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tanh >( a ); } //// -// Log +// Asinh template< typename Real, typename Device, typename Index, typename Communicator > auto -log( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +asinh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Log, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asinh >( a ); } //// -// Log10 +// Acosh template< typename Real, typename Device, typename Index, typename Communicator > auto -log10( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +acosh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Log10, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acosh >( a ); } //// -// Log2 +// Atanh template< typename Real, typename Device, typename Index, typename Communicator > auto -log2( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +atanh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Log2, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atanh >( a ); } //// -// Exp +// Floor template< typename Real, typename Device, typename Index, typename Communicator > auto -exp( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +floor( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Exp, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Floor >( a ); +} + +//// +// Ceil +template< typename Real, typename Device, typename Index, typename Communicator > +auto +ceil( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Ceil >( a ); } //// @@ -896,8 +782,18 @@ template< typename Real, typename Device, typename Index, typename Communicator auto sign( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVector< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Sign, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sign >( a ); +} + +//// +// Cast +template< typename ResultType, typename Real, typename Device, typename Index, typename Communicator, + // workaround: templated type alias cannot be declared at block level + template class Operation = Containers::Expressions::Cast< ResultType >::template Operation > +auto +cast( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Operation >( a ); } //// @@ -905,66 +801,73 @@ sign( const Containers::DistributedVector< Real, Device, Index, Communicator >& template< typename Real, typename Device, typename Index, typename Communicator > -auto +Real min( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::max(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionMin( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionMin( a ); +} + +template< typename Real, + typename Device, + typename Index, typename Communicator > +std::pair< Index, std::decay_t< Real > > +argMin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedExpressionArgMin( a ); +} + +template< typename Real, + typename Device, + typename Index, typename Communicator > +Real +max( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedExpressionMax( a ); +} + +template< typename Real, + typename Device, + typename Index, typename Communicator > +std::pair< Index, std::decay_t< Real > > +argMax( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedExpressionArgMax( a ); } template< typename Real, typename Device, typename Index, typename Communicator > auto -argMin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, Index& arg ) +sum( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - throw Exceptions::NotImplementedError( "agrMin for distributed vector view is not implemented yet." ); - return Containers::Expressions::ExpressionArgMin( a.getLocalVectorView(), arg ); + return Containers::Expressions::DistributedExpressionSum( a ); } template< typename Real, typename Device, typename Index, typename Communicator > auto -max( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +maxNorm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::min(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionMax( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, a.getCommunicationGroup() ); - } - return result; + return max( abs( a ) ); } template< typename Real, typename Device, typename Index, typename Communicator > auto -argMax( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, Index& arg ) +l1Norm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - throw Exceptions::NotImplementedError( "agrMax for distributed vector view is not implemented yet." ); - return Containers::Expressions::ExpressionArgMax( a.getLocalVectorView(), arg ); + return Containers::Expressions::DistributedExpressionL1Norm( a ); } template< typename Real, typename Device, typename Index, typename Communicator > auto -sum( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) +l2Norm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionSum( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return TNL::sqrt( Containers::Expressions::DistributedExpressionL2Norm( a ) ); } template< typename Real, @@ -973,15 +876,14 @@ template< typename Real, typename Real2 > auto lpNorm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const Real2& p ) --> decltype( TNL::pow( Containers::Expressions::ExpressionLpNorm( a.getLocalVectorView(), p ), p ) ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { - using CommunicatorType = typename Containers::DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - Real result = ( Real ) 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionLpNorm( a.getLocalVectorView(), p ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return TNL::pow( result, 1.0 / p ); + if( p == 1.0 ) + return l1Norm( a ); + if( p == 2.0 ) + return l2Norm( a ); + return TNL::pow( Containers::Expressions::DistributedExpressionLpNorm( a, p ), 1.0 / p ); } template< typename Real, @@ -990,13 +892,7 @@ template< typename Real, auto product( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - Real result = ( Real ) 1.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionProduct( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_PROD, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionProduct( a ); } template< typename Real, @@ -1005,13 +901,7 @@ template< typename Real, auto logicalOr( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - bool result = false; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionLogicalOr( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LOR, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionLogicalOr( a ); } template< typename Real, @@ -1020,13 +910,7 @@ template< typename Real, auto binaryOr( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - Real result = ( Real ) 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionBinaryOr( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_BOR, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionBinaryOr( a ); } template< typename Real, @@ -1035,13 +919,7 @@ template< typename Real, auto logicalAnd( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::max(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionLogicalAnd( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionLogicalAnd( a ); } template< typename Real, @@ -1050,13 +928,7 @@ template< typename Real, auto binaryAnd( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVector< Real, Device, Index, Communicator >::CommunicatorType; - bool result = true; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionBinaryAnd( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_BAND, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionBinaryAnd( a ); } } // namespace TNL diff --git a/src/TNL/Containers/DistributedVectorView.h b/src/TNL/Containers/DistributedVectorView.h index 0f4aee49177b7eec02385f6ff4bcee0c1f09cf73..0ab9232001f84c7ea954f02dd21d55830b414cad 100644 --- a/src/TNL/Containers/DistributedVectorView.h +++ b/src/TNL/Containers/DistributedVectorView.h @@ -33,8 +33,8 @@ public: using DeviceType = Device; using CommunicatorType = Communicator; using IndexType = Index; - using LocalVectorViewType = Containers::VectorView< Real, Device, Index >; - using ConstLocalVectorViewType = Containers::VectorView< std::add_const_t< Real >, Device, Index >; + using LocalViewType = Containers::VectorView< Real, Device, Index >; + using ConstLocalViewType = Containers::VectorView< std::add_const_t< Real >, Device, Index >; using HostType = DistributedVectorView< Real, Devices::Host, Index, Communicator >; using CudaType = DistributedVectorView< Real, Devices::Cuda, Index, Communicator >; using ViewType = DistributedVectorView< Real, Device, Index, Communicator >; @@ -56,11 +56,9 @@ public: DistributedVectorView( const Containers::DistributedArrayView< Real_, Device, Index, Communicator >& view ) : BaseType( view ) {} - LocalVectorViewType getLocalVectorView(); + LocalViewType getLocalView(); - ConstLocalVectorViewType getLocalVectorView() const; - - ConstLocalVectorViewType getConstLocalVectorView() const; + ConstLocalViewType getConstLocalView() const; /** * \brief Returns a modifiable view of the array view. @@ -68,13 +66,6 @@ public: __cuda_callable__ ViewType getView(); - /** - * \brief Returns a modifiable view of the array view. - */ - __cuda_callable__ - ConstViewType getView() const; - - /** * \brief Returns a non-modifiable view of the array view. */ @@ -86,46 +77,55 @@ public: /* * Usual Vector methods follow below. */ - void addElement( IndexType i, - RealType value ); - - template< typename Scalar > - void addElement( IndexType i, - RealType value, - Scalar thisElementMultiplicator ); - - template< typename Vector > - DistributedVectorView& operator-=( const Vector& vector ); - - template< typename Vector > - DistributedVectorView& operator+=( const Vector& vector ); - - template< typename Scalar > + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > + DistributedVectorView& operator=( Scalar c ); + + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > + DistributedVectorView& operator+=( Scalar c ); + + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > + DistributedVectorView& operator-=( Scalar c ); + + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > DistributedVectorView& operator*=( Scalar c ); - template< typename Scalar > + template< typename Scalar, + typename..., + typename = std::enable_if_t< ! HasSubscriptOperator::value > > DistributedVectorView& operator/=( Scalar c ); - template< typename ResultType = NonConstReal > - ResultType sum() const; + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVectorView& operator=( const Vector& vector ); - //! Computes scalar dot product - template< typename Vector > - NonConstReal scalarProduct( const Vector& v ) const; + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVectorView& operator+=( const Vector& vector ); + + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVectorView& operator-=( const Vector& vector ); - //! Computes this = thisMultiplicator * this + alpha * x. - template< typename Vector, typename Scalar1 = Real, typename Scalar2 = Real > - void addVector( const Vector& x, - Scalar1 alpha = 1.0, - Scalar2 thisMultiplicator = 1.0 ); + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVectorView& operator*=( const Vector& vector ); - //! Computes this = thisMultiplicator * this + multiplicator1 * v1 + multiplicator2 * v2. - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2, typename Scalar3 = Real > - void addVectors( const Vector1& v1, - Scalar1 multiplicator1, - const Vector2& v2, - Scalar2 multiplicator2, - Scalar3 thisMultiplicator = 1.0 ); + template< typename Vector, + typename..., + typename = std::enable_if_t< HasSubscriptOperator::value > > + DistributedVectorView& operator/=( const Vector& vector ); void computePrefixSum(); @@ -139,5 +139,5 @@ public: } // namespace Containers } // namespace TNL -#include +#include #include diff --git a/src/TNL/Containers/DistributedVectorView_impl.h b/src/TNL/Containers/DistributedVectorView.hpp similarity index 64% rename from src/TNL/Containers/DistributedVectorView_impl.h rename to src/TNL/Containers/DistributedVectorView.hpp index 6dcaf9cb6fdfb2f728b623e23d51d06015bea849..38715161cc46f25b2aa705b3cdb6c302aa1cad38 100644 --- a/src/TNL/Containers/DistributedVectorView_impl.h +++ b/src/TNL/Containers/DistributedVectorView.hpp @@ -23,33 +23,22 @@ template< typename Real, typename Device, typename Index, typename Communicator > -typename DistributedVectorView< Real, Device, Index, Communicator >::LocalVectorViewType +typename DistributedVectorView< Real, Device, Index, Communicator >::LocalViewType DistributedVectorView< Real, Device, Index, Communicator >:: -getLocalVectorView() +getLocalView() { - return this->getLocalArrayView(); + return BaseType::getLocalView(); } template< typename Real, typename Device, typename Index, typename Communicator > -typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType +typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalViewType DistributedVectorView< Real, Device, Index, Communicator >:: -getLocalVectorView() const +getConstLocalView() const { - return this->getLocalArrayView(); -} - -template< typename Real, - typename Device, - typename Index, - typename Communicator > -typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType -DistributedVectorView< Real, Device, Index, Communicator >:: -getConstLocalVectorView() const -{ - return this->getLocalArrayView(); + return BaseType::getConstLocalView(); } template< typename Value, @@ -64,18 +53,6 @@ getView() return *this; } -template< typename Value, - typename Device, - typename Index, - typename Communicator > -__cuda_callable__ -typename DistributedVectorView< Value, Device, Index, Communicator >::ConstViewType -DistributedVectorView< Value, Device, Index, Communicator >:: -getView() const -{ - return *this; -} - template< typename Value, typename Device, typename Index, @@ -113,41 +90,51 @@ template< typename Real, typename Device, typename Index, typename Communicator > -void + template< typename Vector, typename..., typename > +DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: -addElement( IndexType i, - RealType value ) +operator=( const Vector& vector ) { + TNL_ASSERT_EQ( this->getSize(), vector.getSize(), + "The sizes of the array views must be equal, views are not resizable." ); + TNL_ASSERT_EQ( this->getLocalRange(), vector.getLocalRange(), + "The local ranges must be equal, views are not resizable." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), vector.getCommunicationGroup(), + "The communication groups of the array views must be equal." ); + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - const IndexType li = this->getLocalRange().getLocalIndex( i ); - LocalVectorViewType view = getLocalVectorView(); - view.addElement( li, value ); + getLocalView() = vector.getConstLocalView(); } + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Scalar > -void + template< typename Vector, typename..., typename > +DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: -addElement( IndexType i, - RealType value, - Scalar thisElementMultiplicator ) +operator+=( const Vector& vector ) { + TNL_ASSERT_EQ( this->getSize(), vector.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), vector.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), vector.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - const IndexType li = this->getLocalRange().getLocalIndex( i ); - LocalVectorViewType view = getLocalVectorView(); - view.addElement( li, value, thisElementMultiplicator ); + getLocalView() += vector.getConstLocalView(); } + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector > + template< typename Vector, typename..., typename > DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: operator-=( const Vector& vector ) @@ -160,7 +147,7 @@ operator-=( const Vector& vector ) "Multiary operations are supported only on vectors within the same communication group." ); if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView() -= vector.getLocalVectorView(); + getLocalView() -= vector.getConstLocalView(); } return *this; } @@ -169,10 +156,10 @@ template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector > + template< typename Vector, typename..., typename > DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: -operator+=( const Vector& vector ) +operator*=( const Vector& vector ) { TNL_ASSERT_EQ( this->getSize(), vector.getSize(), "Vector sizes must be equal." ); @@ -182,7 +169,7 @@ operator+=( const Vector& vector ) "Multiary operations are supported only on vectors within the same communication group." ); if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView() += vector.getLocalVectorView(); + getLocalView() *= vector.getConstLocalView(); } return *this; } @@ -191,13 +178,20 @@ template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Scalar > + template< typename Vector, typename..., typename > DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: -operator*=( Scalar c ) +operator/=( const Vector& vector ) { + TNL_ASSERT_EQ( this->getSize(), vector.getSize(), + "Vector sizes must be equal." ); + TNL_ASSERT_EQ( this->getLocalRange(), vector.getLocalRange(), + "Multiary operations are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( this->getCommunicationGroup(), vector.getCommunicationGroup(), + "Multiary operations are supported only on vectors within the same communication group." ); + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView() *= c; + getLocalView() /= vector.getConstLocalView(); } return *this; } @@ -206,13 +200,13 @@ template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Scalar > + template< typename Scalar, typename..., typename > DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: -operator/=( Scalar c ) +operator=( Scalar c ) { if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView() /= c; + getLocalView() = c; } return *this; } @@ -221,94 +215,60 @@ template< typename Real, typename Device, typename Index, typename Communicator > - template< typename ResultType > -ResultType + template< typename Scalar, typename..., typename > +DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: -sum() const +operator+=( Scalar c ) { - const auto group = this->getCommunicationGroup(); - ResultType result = Containers::Algorithms::ParallelReductionSum< Real, ResultType >::initialValue(); - if( group != CommunicatorType::NullGroup ) { - const ResultType localResult = getLocalVectorView().sum(); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalView() += c; } - return result; + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector > -typename DistributedVectorView< Real, Device, Index, Communicator >::NonConstReal + template< typename Scalar, typename..., typename > +DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: -scalarProduct( const Vector& v ) const +operator-=( Scalar c ) { - const auto group = this->getCommunicationGroup(); - NonConstReal result = Containers::Algorithms::ParallelReductionScalarProduct< Real, typename Vector::RealType >::initialValue(); - if( group != CommunicatorType::NullGroup ) { - const Real localResult = getLocalVectorView().scalarProduct( v.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, group ); + if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { + getLocalView() -= c; } - return result; + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector, typename Scalar1, typename Scalar2 > -void + template< typename Scalar, typename..., typename > +DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: -addVector( const Vector& x, - Scalar1 alpha, - Scalar2 thisMultiplicator ) +operator*=( Scalar c ) { - TNL_ASSERT_EQ( this->getSize(), x.getSize(), - "Vector sizes must be equal." ); - TNL_ASSERT_EQ( this->getLocalRange(), x.getLocalRange(), - "Multiary operations are supported only on vectors which are distributed the same way." ); - TNL_ASSERT_EQ( this->getCommunicationGroup(), x.getCommunicationGroup(), - "Multiary operations are supported only on vectors within the same communication group." ); - if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView().addVector( x.getLocalVectorView(), alpha, thisMultiplicator ); + getLocalView() *= c; } + return *this; } template< typename Real, typename Device, typename Index, typename Communicator > - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2, typename Scalar3 > -void + template< typename Scalar, typename..., typename > +DistributedVectorView< Real, Device, Index, Communicator >& DistributedVectorView< Real, Device, Index, Communicator >:: -addVectors( const Vector1& v1, - Scalar1 multiplicator1, - const Vector2& v2, - Scalar2 multiplicator2, - Scalar3 thisMultiplicator ) +operator/=( Scalar c ) { - TNL_ASSERT_EQ( this->getSize(), v1.getSize(), - "Vector sizes must be equal." ); - TNL_ASSERT_EQ( this->getLocalRange(), v1.getLocalRange(), - "Multiary operations are supported only on vectors which are distributed the same way." ); - TNL_ASSERT_EQ( this->getCommunicationGroup(), v1.getCommunicationGroup(), - "Multiary operations are supported only on vectors within the same communication group." ); - TNL_ASSERT_EQ( this->getSize(), v2.getSize(), - "Vector sizes must be equal." ); - TNL_ASSERT_EQ( this->getLocalRange(), v2.getLocalRange(), - "Multiary operations are supported only on vectors which are distributed the same way." ); - TNL_ASSERT_EQ( this->getCommunicationGroup(), v2.getCommunicationGroup(), - "Multiary operations are supported only on vectors within the same communication group." ); - if( this->getCommunicationGroup() != CommunicatorType::NullGroup ) { - getLocalVectorView().addVectors( v1.getLocalVectorView(), - multiplicator1, - v2.getLocalVectorView(), - multiplicator2, - thisMultiplicator ); + getLocalView() /= c; } + return *this; } template< typename Real, diff --git a/src/TNL/Containers/DistributedVectorViewExpressions.h b/src/TNL/Containers/DistributedVectorViewExpressions.h index 73b319dc1b39c7e1f80f48543103686893b033ec..e22d82980612b0472c757bc23c2528b829f372c9 100644 --- a/src/TNL/Containers/DistributedVectorViewExpressions.h +++ b/src/TNL/Containers/DistributedVectorViewExpressions.h @@ -1,8 +1,8 @@ /*************************************************************************** DistributedVectorViewExpressions.h - description ------------------- - begin : Apr 27, 2019 - copyright : (C) 2019 by Tomas Oberhuber + begin : Jun 28, 2019 + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,14 +10,10 @@ #pragma once -#include -#include #include -#include -#include -#include #include -#include + +#include "DistributedVectorView.h" namespace TNL { namespace Containers { @@ -29,8 +25,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto operator+( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Expressions::Addition, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Expressions::Addition >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -38,17 +33,14 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto operator+( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using ConstView = typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Expressions::Addition, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Expressions::Addition >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator+( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVectorView< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVectorView< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Addition >( a, b ); } //// @@ -58,8 +50,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto operator-( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Expressions::Subtraction, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Expressions::Subtraction >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -67,17 +58,14 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto operator-( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using ConstView = typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Expressions::Subtraction, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Expressions::Subtraction >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator-( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVectorView< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVectorView< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Subtraction >( a, b ); } //// @@ -87,8 +75,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto operator*( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Expressions::Multiplication, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Expressions::Multiplication >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -96,17 +83,14 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto operator*( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using ConstView = typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Expressions::Multiplication, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Expressions::Multiplication >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator*( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVectorView< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVectorView< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Multiplication >( a, b ); } //// @@ -116,8 +100,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto operator/( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Expressions::Division, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Expressions::Division >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -125,190 +108,164 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto operator/( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using ConstView = typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Expressions::Division, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Expressions::Division >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator/( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename DistributedVectorView< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename DistributedVectorView< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Expressions::Division >( a, b ); } //// // Comparison operations - operator == template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator==( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator==( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template EQ< Communicator >( a.getLocalVectorView(), b, a.getCommunicatorGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::EQ( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator==( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) +bool +operator==( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template EQ< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::EQ( a, b ); } -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index1, typename Index2, typename Communicator > -bool operator==( const DistributedVectorView< Real1, Device1, Index1, Communicator >& a, const DistributedVectorView< Real2, Device2, Index2, Communicator >& b ) +template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > +bool +operator==( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b ) { - if( a.getCommunicationGroup() != b.getCommunicationGroup() ) - return false; - const bool localResult = - a.getLocalRange() == b.getLocalRange() && - a.getSize() == b.getSize() && - a.getLocalArrayView() == b.getLocalArrayView(); - bool result = true; - if( a.getCommunicationGroup() != Communicator::NullGroup ) - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); - return result; + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); } //// // Comparison operations - operator != template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator!=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator!=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template NE< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::NE( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator!=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) +bool +operator!=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template NE< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::NE( a, b ); } template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool operator!=( const DistributedVectorView< Real1, Device1, Index >& a, const DistributedVectorView< Real2, Device2, Index >& b ) +bool +operator!=( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b ) { - return ! operator==( a, b ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } //// // Comparison operations - operator < template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator<( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator<( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template LT< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::LT( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator<( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) +bool +operator<( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LT< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::LT( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) +bool +operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LT< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } //// // Comparison operations - operator <= template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator<=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator<=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template LE< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::LE( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator<=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) +bool +operator<=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LE< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::LE( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) +bool +operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template LE< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } //// // Comparison operations - operator > template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator>( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator>( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template GT< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::GT( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator>( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) +bool +operator>( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GT< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::GT( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) +bool +operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GT< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } //// // Comparison operations - operator >= template< typename Real, typename Device, typename Index, typename Communicator, typename ET, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator>=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) +bool +operator>=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using Left = DistributedVectorView< Real, Device, Index, Communicator >; - using Right = ET; - return Expressions::DistributedComparison< Left, Right >::template GE< Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, ET >::GE( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > -bool operator>=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) +bool +operator>=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using Left = ET; - using Right = DistributedVectorView< Real, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GE< Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< ET, std::decay_t >::GE( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) +bool +operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using Left = DistributedVectorView< Real1, Device, Index, Communicator >; - using Right = DistributedVectorView< Real2, Device, Index, Communicator >; - return Expressions::DistributedComparison< Left, Right >::template GE< Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Expressions::DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } //// @@ -317,8 +274,7 @@ template< typename Real, typename Device, typename Index, typename Communicator auto operator-( const DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Expressions::DistributedUnaryExpressionTemplate< ConstView, Expressions::Minus, void, Communicator >( a.getLocalVectorView() ); + return Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Expressions::Minus >( a ); } //// @@ -328,47 +284,28 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto operator,( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using CommunicatorType = typename DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = TNL::sum( a.getLocalVectorView() * b ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return Expressions::DistributedExpressionSum( a * b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, typename..., typename = std::enable_if_t< Expressions::IsNumericExpression::value > > auto -operator,( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) +operator,( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using CommunicatorType = typename DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = TNL::sum( a * b.getLocalVectorView(), b.getCommunicationGroup() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return Expressions::DistributedExpressionSum( a * b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto operator,( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using CommunicatorType = typename DistributedVectorView< Real1, Device, Index, Communicator >::CommunicatorType; - using Real = decltype( TNL::sum( a.getLocalVectorView() * b.getLocalVectorView() ) ); - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = TNL::sum( a.getLocalVectorView() * b.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return Expressions::DistributedExpressionSum( a * b ); } } // namespace Containers //// -// Functions are supposed to be in namespace TNL +// All functions are supposed to be in namespace TNL //// // Min @@ -377,8 +314,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto min( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Min, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Containers::Expressions::Min >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -386,17 +322,14 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto min( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Min, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto min( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename Containers::DistributedVectorView< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename Containers::DistributedVectorView< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } //// @@ -406,8 +339,7 @@ template< typename Real, typename Device, typename Index, typename Communicator, auto max( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Max, Communicator >( a.getLocalVectorView(), b, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, ET, Containers::Expressions::Max >( a, b ); } template< typename ET, typename Real, typename Device, typename Index, typename Communicator, @@ -415,57 +347,67 @@ template< typename ET, typename Real, typename Device, typename Index, typename auto max( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Max, Communicator >( a, b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > auto max( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) { - using ConstView1 = typename Containers::DistributedVectorView< Real1, Device, Index, Communicator >::ConstLocalVectorViewType; - using ConstView2 = typename Containers::DistributedVectorView< Real2, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedBinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max, Communicator >( a.getLocalVectorView(), b.getLocalVectorView(), b.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } //// -// Abs -template< typename Real, typename Device, typename Index, typename Communicator > +// Dot product - the same as scalar product, just for convenience +template< typename Real, typename Device, typename Index, typename Communicator, typename ET, + typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression::value > > auto -abs( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +dot( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Abs, void, Communicator >( a.getLocalVectorView(), a.getCommunicationGroup() ); + return (a, b); +} + +template< typename ET, typename Real, typename Device, typename Index, typename Communicator, + typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression::value > > +auto +dot( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b ) +{ + return (a, b); +} + +template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2, typename Communicator > +auto +dot( const Containers::DistributedVectorView< Real1, Device, Index1, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index2, Communicator >& b ) +{ + return (a, b); } //// -// Sine +// Abs template< typename Real, typename Device, typename Index, typename Communicator > auto -sin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +abs( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Sin, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Abs >( a ); } + //// -// Cosine -template< typename Real, typename Device, typename Index, typename Communicator > +// Power +template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType > auto -cos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +pow( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ExpType& exp ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Cos, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< Containers::DistributedVectorView< Real, Device, Index, Communicator >, ExpType, Containers::Expressions::Pow >( a, exp ); } //// -// Tangent +// Exp template< typename Real, typename Device, typename Index, typename Communicator > auto -tan( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +exp( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Tan, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Exp >( a ); } //// @@ -474,8 +416,7 @@ template< typename Real, typename Device, typename Index, typename Communicator auto sqrt( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Sqrt, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sqrt >( a ); } //// @@ -484,48 +425,61 @@ template< typename Real, typename Device, typename Index, typename Communicator auto cbrt( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Cbrt, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cbrt >( a ); } //// -// Power -template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType > +// Log +template< typename Real, typename Device, typename Index, typename Communicator > auto -pow( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ExpType& exp ) +log( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Pow, ExpType, Communicator >( a.getLocalVectorView(), exp ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log >( a ); } //// -// Floor +// Log10 template< typename Real, typename Device, typename Index, typename Communicator > auto -floor( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +log10( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Floor, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log10 >( a ); } //// -// Ceil +// Log2 template< typename Real, typename Device, typename Index, typename Communicator > auto -ceil( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +log2( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Ceil, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log2 >( a ); } //// -// Acos +// Sine template< typename Real, typename Device, typename Index, typename Communicator > auto -acos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +sin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Acos, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sin >( a ); +} + +//// +// Cosine +template< typename Real, typename Device, typename Index, typename Communicator > +auto +cos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cos >( a ); +} + +//// +// Tangent +template< typename Real, typename Device, typename Index, typename Communicator > +auto +tan( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tan >( a ); } //// @@ -534,8 +488,16 @@ template< typename Real, typename Device, typename Index, typename Communicator auto asin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Asin, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asin >( a ); +} + +//// +// Acos +template< typename Real, typename Device, typename Index, typename Communicator > +auto +acos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acos >( a ); } //// @@ -544,8 +506,16 @@ template< typename Real, typename Device, typename Index, typename Communicator auto atan( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Atan, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atan >( a ); +} + +//// +// Sinh +template< typename Real, typename Device, typename Index, typename Communicator > +auto +sinh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sinh >( a ); } //// @@ -554,8 +524,7 @@ template< typename Real, typename Device, typename Index, typename Communicator auto cosh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Cosh, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cosh >( a ); } //// @@ -564,48 +533,52 @@ template< typename Real, typename Device, typename Index, typename Communicator auto tanh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Tanh, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tanh >( a ); } //// -// Log +// Asinh template< typename Real, typename Device, typename Index, typename Communicator > auto -log( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +asinh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Log, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asinh >( a ); } //// -// Log10 +// Acosh template< typename Real, typename Device, typename Index, typename Communicator > auto -log10( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +acosh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Log10, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acosh >( a ); } //// -// Log2 +// Atanh template< typename Real, typename Device, typename Index, typename Communicator > auto -log2( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +atanh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Log2, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atanh >( a ); } //// -// Exp +// Floor template< typename Real, typename Device, typename Index, typename Communicator > auto -exp( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +floor( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Exp, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Floor >( a ); +} + +//// +// Ceil +template< typename Real, typename Device, typename Index, typename Communicator > +auto +ceil( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Ceil >( a ); } //// @@ -614,192 +587,130 @@ template< typename Real, typename Device, typename Index, typename Communicator auto sign( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using ConstView = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::ConstLocalVectorViewType; - return Containers::Expressions::DistributedUnaryExpressionTemplate< ConstView, Containers::Expressions::Sign, void, Communicator >( a.getLocalVectorView() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sign >( a ); } //// -// Vertical operations - min -template< typename Real, - typename Device, - typename Index, typename Communicator > +// Cast +template< typename ResultType, typename Real, typename Device, typename Index, typename Communicator, + // workaround: templated type alias cannot be declared at block level + template class Operation = Containers::Expressions::Cast< ResultType >::template Operation > auto +cast( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Operation >( a ); +} + +//// +// Vertical operations - min +template< typename Real, typename Device, typename Index, typename Communicator > +Real min( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::max(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionMin( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionMin( a ); } -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -argMin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, Index& arg ) +template< typename Real, typename Device, typename Index, typename Communicator > +std::pair< Index, std::decay_t< Real > > +argMin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - throw Exceptions::NotImplementedError( "agrMin for distributed vector view is not implemented yet." ); - return Containers::Expressions::ExpressionArgMin( a.getLocalVectorView(), arg ); + return Containers::Expressions::DistributedExpressionArgMin( a ); } -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto +template< typename Real, typename Device, typename Index, typename Communicator > +Real max( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::min(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionMax( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionMax( a ); } -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -argMax( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, Index& arg ) +template< typename Real, typename Device, typename Index, typename Communicator > +std::pair< Index, std::decay_t< Real > > +argMax( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - throw Exceptions::NotImplementedError( "agrMax for distributed vector view is not implemented yet." ); - return Containers::Expressions::ExpressionArgMax( a.getLocalVectorView(), arg ); + return Containers::Expressions::DistributedExpressionArgMax( a ); } -template< typename Real, - typename Device, - typename Index, typename Communicator > +template< typename Real, typename Device, typename Index, typename Communicator > auto sum( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionSum( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionSum( a ); } template< typename Real, typename Device, - typename Index, typename Communicator, - typename Real2 > + typename Index, typename Communicator > auto -lpNorm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const Real2& p ) --> decltype( TNL::pow( Containers::Expressions::ExpressionLpNorm( a.getLocalVectorView(), p ), p ) ) +maxNorm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - Real result = ( Real ) 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionLpNorm( a.getLocalVectorView(), p ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return TNL::pow( result, 1.0 / p ); + return max( abs( a ) ); } template< typename Real, typename Device, typename Index, typename Communicator > auto -product( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +l1Norm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - Real result = ( Real ) 1.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionProduct( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_PROD, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionL1Norm( a ); } template< typename Real, typename Device, typename Index, typename Communicator > auto -logicalOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +l2Norm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - bool result = false; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionLogicalOr( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LOR, a.getCommunicationGroup() ); - } - return result; + return TNL::sqrt( Containers::Expressions::DistributedExpressionL2Norm( a ) ); } -template< typename Real, - typename Device, - typename Index, typename Communicator > +template< typename Real, typename Device, typename Index, typename Communicator, typename Real2 > auto -binaryOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +lpNorm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const Real2& p ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { - using CommunicatorType = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - Real result = ( Real ) 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionBinaryOr( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_BOR, a.getCommunicationGroup() ); - } - return result; + if( p == 1.0 ) + return l1Norm( a ); + if( p == 2.0 ) + return l2Norm( a ); + return TNL::pow( Containers::Expressions::DistributedExpressionLpNorm( a, p ), 1.0 / p ); } -template< typename Real, - typename Device, - typename Index, typename Communicator > +template< typename Real, typename Device, typename Index, typename Communicator > auto -logicalAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +product( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::max(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionLogicalAnd( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionProduct( a ); } -template< typename Real, - typename Device, - typename Index, typename Communicator > +template< typename Real, typename Device, typename Index, typename Communicator > auto -binaryAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) +logicalOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - using CommunicatorType = typename Containers::DistributedVectorView< Real, Device, Index, Communicator >::CommunicatorType; - bool result = true; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionBinaryAnd( a.getLocalVectorView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_BAND, a.getCommunicationGroup() ); - } - return result; + return Containers::Expressions::DistributedExpressionLogicalOr( a ); } -//// -// Dot product - the same as scalar product, just for convenience -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression::value > > +template< typename Real, typename Device, typename Index, typename Communicator > auto -dot( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) +binaryOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - return ( a, b ); + return Containers::Expressions::DistributedExpressionBinaryOr( a ); } -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression::value > > +template< typename Real, typename Device, typename Index, typename Communicator > auto -dot( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b ) +logicalAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - return ( a, b ); + return Containers::Expressions::DistributedExpressionLogicalAnd( a ); } -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > +template< typename Real, typename Device, typename Index, typename Communicator > auto -dot( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) +binaryAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) { - return ( a, b ); + return Containers::Expressions::DistributedExpressionBinaryAnd( a ); } } // namespace TNL diff --git a/src/TNL/Containers/Expressions/Comparison.h b/src/TNL/Containers/Expressions/Comparison.h index a1affe76f3b936b34e8d5a9700d51144803cad5a..ff533e7813028f22914a129575fbe31bccebae14 100644 --- a/src/TNL/Containers/Expressions/Comparison.h +++ b/src/TNL/Containers/Expressions/Comparison.h @@ -2,7 +2,7 @@ Comparison.h - description ------------------- begin : Apr 19, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include @@ -27,42 +27,44 @@ template< typename T1, typename T2, ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > -struct Comparison -{ -}; +struct Comparison; template< typename T1, typename T2, bool BothAreVectors = IsArrayType< T1 >::value && IsArrayType< T2 >::value > struct VectorComparison; -template< typename T1, - typename T2 > +// If both operands are vectors we compare them using array operations. +// It allows to compare vectors on different devices +template< typename T1, typename T2 > struct VectorComparison< T1, T2, true > { - // If both operands are vectors we compare them using array operations. - // It allows to compare vectors on different devices - static bool EQ( const T1& a, const T2& b ) { + if( a.getSize() != b.getSize() ) + return false; + if( a.getSize() == 0 ) + return true; return Algorithms::ArrayOperations< typename T1::DeviceType, typename T2::DeviceType >::compare( a.getData(), b.getData(), a.getSize() ); } }; -template< typename T1, - typename T2 > +// If both operands are not vectors we compare them parallel reduction +template< typename T1, typename T2 > struct VectorComparison< T1, T2, false > { - // If both operands are not vectors we compare them parallel reduction - static bool EQ( const T1& a, const T2& b ) { + if( ! std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value ) + throw std::runtime_error( "Cannot compare two expressions with different DeviceType." ); + + if( a.getSize() != b.getSize() ) + return false; + using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - if( ! std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value ) - throw std::runtime_error( "Cannot compare two expressions allocated on different devices." ); - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] == b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] == b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); @@ -77,10 +79,6 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > { static bool EQ( const T1& a, const T2& b ) { - if( a.getSize() != b.getSize() ) - return false; - if( a.getSize() == 0 ) - return true; return VectorComparison< T1, T2 >::EQ( a, b ); } @@ -91,12 +89,14 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > static bool GT( const T1& a, const T2& b ) { + if( ! std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value ) + throw std::runtime_error( "Cannot compare two expressions with different DeviceType." ); TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] > b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] > b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); @@ -104,12 +104,14 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > static bool GE( const T1& a, const T2& b ) { + if( ! std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value ) + throw std::runtime_error( "Cannot compare two expressions with different DeviceType." ); TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] >= b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] >= b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); @@ -117,12 +119,14 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > static bool LT( const T1& a, const T2& b ) { + if( ! std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value ) + throw std::runtime_error( "Cannot compare two expressions with different DeviceType." ); TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] < b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] < b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); @@ -130,12 +134,14 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > static bool LE( const T1& a, const T2& b ) { + if( ! std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value ) + throw std::runtime_error( "Cannot compare two expressions with different DeviceType." ); TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] <= b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] <= b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); @@ -148,14 +154,12 @@ template< typename T1, typename T2 > struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > { - - static bool EQ( const T1& a, const T2& b ) { using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a == b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a == b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), reduction, volatileReduction, fetch, true ); @@ -171,7 +175,7 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a > b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a > b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), reduction, volatileReduction, fetch, true ); @@ -182,7 +186,7 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a >= b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a >= b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), reduction, volatileReduction, fetch, true ); @@ -193,7 +197,7 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a < b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a < b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), reduction, volatileReduction, fetch, true ); @@ -204,7 +208,7 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a <= b[ i ] ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a <= b[ i ]; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), reduction, volatileReduction, fetch, true ); @@ -217,14 +221,12 @@ template< typename T1, typename T2 > struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > { - - static bool EQ( const T1& a, const T2& b ) { using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] == b ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] == b; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); @@ -240,7 +242,7 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] > b ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] > b; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); @@ -251,7 +253,7 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] >= b ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] >= b; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); @@ -262,7 +264,7 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] < b ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] < b; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); @@ -273,14 +275,13 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] <= b ); }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] <= b; }; auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); } }; - - } //namespace Expressions - } // namespace Containers +} // namespace Expressions +} // namespace Containers } // namespace TNL diff --git a/src/TNL/Containers/Expressions/DistributedComparison.h b/src/TNL/Containers/Expressions/DistributedComparison.h index 1341cb990cadd32172ba29d37f818e8d5a180921..7a7d5c5bebf24fca09a2f1837561483d27f8f9b8 100644 --- a/src/TNL/Containers/Expressions/DistributedComparison.h +++ b/src/TNL/Containers/Expressions/DistributedComparison.h @@ -2,7 +2,7 @@ DistributedComparison.h - description ------------------- begin : Jul 4, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,12 +10,13 @@ #pragma once -#include +#include #include +#include namespace TNL { - namespace Containers { - namespace Expressions { +namespace Containers { +namespace Expressions { //// // Non-static comparison @@ -23,9 +24,7 @@ template< typename T1, typename T2, ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > -struct DistributedComparison -{ -}; +struct DistributedComparison; ///// // Distributed comparison of two vector expressions @@ -33,85 +32,84 @@ template< typename T1, typename T2 > struct DistributedComparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > { - template< typename Communicator > - static bool EQ( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool EQ( const T1& a, const T2& b ) { - if( a.getSize() != b.getSize() ) + // we can't run allreduce if the communication groups are different + if( a.getCommunicationGroup() != b.getCommunicationGroup() ) return false; - if( a.getSize() == 0 ) - return true; - - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] == b[ i ] ); }; - auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; - bool localResult = Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); - - bool result = localResult; - if( communicationGroup != Communicator::NullGroup ) { - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, communicationGroup ); - } + const bool localResult = + a.getLocalRange() == b.getLocalRange() && + a.getSize() == b.getSize() && + a.getConstLocalView() == b.getConstLocalView(); + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); return result; } - template< typename Communicator > - static bool NE( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool NE( const T1& a, const T2& b ) { - return ! EQ< Communicator >( a, b, communicationGroup ); + return ! DistributedComparison::EQ( a, b ); } - template< typename Communicator > - static bool GT( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool LT( const T1& a, const T2& b ) { - TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); + TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not match." ); + TNL_ASSERT_EQ( a.getLocalRange(), b.getLocalRange(), "Local ranges of expressions to be compared do not match." ); - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] > b[ i ] ); }; - auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; - bool localResult = Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); - - bool result = localResult; - if( communicationGroup != Communicator::NullGroup ) { - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, communicationGroup ); - } + // we can't run allreduce if the communication groups are different + if( a.getCommunicationGroup() != b.getCommunicationGroup() ) + return false; + const bool localResult = a.getConstLocalView() < b.getConstLocalView(); + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); return result; } - template< typename Communicator > - static bool LE( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool LE( const T1& a, const T2& b ) { - return ! GT( a, b, communicationGroup ); + TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not match." ); + TNL_ASSERT_EQ( a.getLocalRange(), b.getLocalRange(), "Local ranges of expressions to be compared do not match." ); + + // we can't run allreduce if the communication groups are different + if( a.getCommunicationGroup() != b.getCommunicationGroup() ) + return false; + const bool localResult = a.getConstLocalView() <= b.getConstLocalView(); + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); + return result; } - template< typename Communicator > - static bool LT( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool GT( const T1& a, const T2& b ) { - TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); - - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; + TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not match." ); + TNL_ASSERT_EQ( a.getLocalRange(), b.getLocalRange(), "Local ranges of expressions to be compared do not match." ); - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] < b[ i ] ); }; - auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; - bool localResult = Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); - - bool result = localResult; - if( communicationGroup != Communicator::NullGroup ) { - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, communicationGroup ); - } + // we can't run allreduce if the communication groups are different + if( a.getCommunicationGroup() != b.getCommunicationGroup() ) + return false; + const bool localResult = a.getConstLocalView() > b.getConstLocalView(); + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); return result; } - template< typename Communicator > - static bool GE( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool GE( const T1& a, const T2& b ) { - return ! LT( a, b, communicationGroup ); + TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not match." ); + TNL_ASSERT_EQ( a.getLocalRange(), b.getLocalRange(), "Local ranges of expressions to be compared do not match." ); + + // we can't run allreduce if the communication groups are different + if( a.getCommunicationGroup() != b.getCommunicationGroup() ) + return false; + const bool localResult = a.getConstLocalView() >= b.getConstLocalView(); + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); + return result; } }; @@ -121,77 +119,54 @@ template< typename T1, typename T2 > struct DistributedComparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > { - - template< typename Communicator > - static bool EQ( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool EQ( const T1& a, const T2& b ) { - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a == b[ i ] ); }; - auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; - bool localResult = Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); - - bool result = localResult; - if( communicationGroup != Communicator::NullGroup ) { - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, communicationGroup ); - } + const bool localResult = a == b.getConstLocalView(); + bool result = true; + if( b.getCommunicationGroup() != T2::CommunicatorType::NullGroup ) + T2::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, b.getCommunicationGroup() ); return result; } - template< typename Communicator > - static bool NE( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool NE( const T1& a, const T2& b ) { - return ! EQ( a, b, communicationGroup ); + return ! DistributedComparison::EQ( a, b ); } - template< typename Communicator > - static bool GT( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool LT( const T1& a, const T2& b ) { - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a > b[ i ] ); }; - auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; - bool localResult = Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); - - bool result = localResult; - if( communicationGroup != Communicator::NullGroup ) { - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, communicationGroup ); - } + const bool localResult = a < b.getConstLocalView(); + bool result = true; + if( b.getCommunicationGroup() != T2::CommunicatorType::NullGroup ) + T2::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, b.getCommunicationGroup() ); return result; } - template< typename Communicator > - static bool LE( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool LE( const T1& a, const T2& b ) { - return ! GT( a, b, communicationGroup ); + const bool localResult = a <= b.getConstLocalView(); + bool result = true; + if( b.getCommunicationGroup() != T2::CommunicatorType::NullGroup ) + T2::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, b.getCommunicationGroup() ); + return result; } - template< typename Communicator > - static bool LT( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool GT( const T1& a, const T2& b ) { - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a < b[ i ] ); }; - auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; - bool localResult = Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); - - bool result = localResult; - if( communicationGroup != Communicator::NullGroup ) { - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, communicationGroup ); - } + const bool localResult = a > b.getConstLocalView(); + bool result = true; + if( b.getCommunicationGroup() != T2::CommunicatorType::NullGroup ) + T2::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, b.getCommunicationGroup() ); return result; } - template< typename Communicator > - static bool GE( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool GE( const T1& a, const T2& b ) { - return ! LT( a, b, communicationGroup ); + const bool localResult = a >= b.getConstLocalView(); + bool result = true; + if( b.getCommunicationGroup() != T2::CommunicatorType::NullGroup ) + T2::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, b.getCommunicationGroup() ); + return result; } }; @@ -201,80 +176,57 @@ template< typename T1, typename T2 > struct DistributedComparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > { - - template< typename Communicator > - static bool EQ( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool EQ( const T1& a, const T2& b ) { - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] == b ); }; - auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; - bool localResult = Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); - - bool result = localResult; - if( communicationGroup != Communicator::NullGroup ) { - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, communicationGroup ); - } + const bool localResult = a.getConstLocalView() == b; + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); return result; } - template< typename Communicator > - static bool NE( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool NE( const T1& a, const T2& b ) { - return ! EQ( a, b, communicationGroup ); + return ! DistributedComparison::EQ( a, b ); } - template< typename Communicator > - static bool GT( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool LT( const T1& a, const T2& b ) { - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] > b ); }; - auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; - bool localResult = Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); - - bool result = localResult; - if( communicationGroup != Communicator::NullGroup ) { - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, communicationGroup ); - } + const bool localResult = a.getConstLocalView() < b; + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); return result; } - template< typename Communicator > - static bool LE( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool LE( const T1& a, const T2& b ) { - return ! GT( a, b, communicationGroup ); + const bool localResult = a.getConstLocalView() <= b; + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); + return result; } - template< typename Communicator > - static bool LT( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool GT( const T1& a, const T2& b ) { - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return ( a[ i ] < b ); }; - auto reduction = [=] __cuda_callable__ ( bool& a, const bool& b ) { a &= b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile bool& a, volatile bool& b ) { a &= b; }; - bool localResult = Algorithms::Reduction< DeviceType >::reduce( a.getSize(), reduction, volatileReduction, fetch, true ); - - bool result = localResult; - if( communicationGroup != Communicator::NullGroup ) { - Communicator::Allreduce( &localResult, &result, 1, MPI_LAND, communicationGroup ); - } + const bool localResult = a.getConstLocalView() > b; + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); return result; } - template< typename Communicator > - static bool GE( const T1& a, const T2& b, const typename Communicator::CommunicationGroup& communicationGroup ) + static bool GE( const T1& a, const T2& b ) { - return ! LT( a, b, communicationGroup ); + const bool localResult = a.getConstLocalView() >= b; + bool result = true; + if( a.getCommunicationGroup() != T1::CommunicatorType::NullGroup ) + T1::CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); + return result; } }; - } //namespace Expressions - } // namespace Containers +} // namespace Expressions +} // namespace Containers } // namespace TNL diff --git a/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h b/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h index e8d83edd206fd63db1bad24657eb0525d2c4ae9c..405b0014ac77a5287bff0680c78b671c8104ab51 100644 --- a/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h +++ b/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h @@ -2,26 +2,18 @@ DistributedExpressionTemplates.h - description ------------------- begin : Jun 28, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ /* See Copyright Notice in tnl/Copyright */ #pragma once +#include -#include - -#include -#include -#include -#include +#include #include - -#include - -#include -#include +#include namespace TNL { namespace Containers { @@ -31,18 +23,14 @@ namespace Expressions { // Distributed unary expression template template< typename T1, template< typename > class Operation, - typename Parameter, - typename Communicator, ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value > struct DistributedUnaryExpressionTemplate {}; template< typename T1, template< typename > class Operation, - typename Parameter, - typename Communicator, ExpressionVariableType T1Type > -struct IsExpressionTemplate< DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator, T1Type > > +struct IsExpressionTemplate< DistributedUnaryExpressionTemplate< T1, Operation, T1Type > > : std::true_type {}; @@ -51,7 +39,6 @@ struct IsExpressionTemplate< DistributedUnaryExpressionTemplate< T1, Operation, template< typename T1, typename T2, template< typename, typename > class Operation, - typename Communicator, ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > struct DistributedBinaryExpressionTemplate @@ -60,299 +47,271 @@ struct DistributedBinaryExpressionTemplate template< typename T1, typename T2, template< typename, typename > class Operation, - typename Communicator, ExpressionVariableType T1Type, ExpressionVariableType T2Type > -struct IsExpressionTemplate< DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator, T1Type, T2Type > > +struct IsExpressionTemplate< DistributedBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > > : std::true_type {}; template< typename T1, typename T2, - template< typename, typename > class Operation, - typename Communicator > -struct DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator, VectorExpressionVariable, VectorExpressionVariable > + template< typename, typename > class Operation > +struct DistributedBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, VectorExpressionVariable > { - using RealType = typename std::remove_const< typename T1::RealType >::type; + using RealType = decltype( Operation< typename T1::RealType, typename T2::RealType >:: + evaluate( std::declval()[0], std::declval()[0] ) ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - using CommunicatorType = Communicator; //Communicators::MpiCommunicator; + using CommunicatorType = typename T1::CommunicatorType; using CommunicationGroup = typename CommunicatorType::CommunicationGroup; - - static_assert( std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value, "Attempt to mix operands allocated on different device types." ); - static_assert( IsStaticArrayType< T1 >::value == IsStaticArrayType< T2 >::value, "Attempt to mix static and non-static operands in binary expression templates." ); - - DistributedBinaryExpressionTemplate( const T1& a, const T2& b, const CommunicationGroup& group ) - : op1( a ), op2( b ), communicationGroup( group ) {} - - static DistributedBinaryExpressionTemplate evaluate( const T1& a, const T2& b ) + using LocalRangeType = typename T1::LocalRangeType; + using ConstLocalViewType = BinaryExpressionTemplate< typename T1::ConstLocalViewType, + typename T2::ConstLocalViewType, + Operation >; + + static_assert( std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value, + "Attempt to mix operands which have different DeviceType." ); + static_assert( IsStaticArrayType< T1 >::value == IsStaticArrayType< T2 >::value, + "Attempt to mix static and non-static operands in binary expression templates." ); + + DistributedBinaryExpressionTemplate( const T1& a, const T2& b ) + : op1( a ), op2( b ) { - return DistributedBinaryExpressionTemplate( a, b ); + TNL_ASSERT_EQ( op1.getSize(), op2.getSize(), + "Attempt to mix operands with different sizes." ); + TNL_ASSERT_EQ( op1.getLocalRange(), op2.getLocalRange(), + "Distributed expressions are supported only on vectors which are distributed the same way." ); + TNL_ASSERT_EQ( op1.getCommunicationGroup(), op2.getCommunicationGroup(), + "Distributed expressions are supported only on vectors within the same communication group." ); } RealType getElement( const IndexType i ) const { - return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1.getElement( i ), op2.getElement( i ) ); + return getConstLocalView().getElement( i ); } - __cuda_callable__ + // this is actually never executed, but needed for proper ExpressionVariableTypeGetter + // selection via HasSubscriptOperator type trait RealType operator[]( const IndexType i ) const { - return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1[ i ], op2[ i ] ); + return getConstLocalView()[ i ]; + } + + IndexType getSize() const + { + return op1.getSize(); } - __cuda_callable__ - int getSize() const + LocalRangeType getLocalRange() const { - return op1.getSize(); + return op1.getLocalRange(); } CommunicationGroup getCommunicationGroup() const { - return communicationGroup; + return op1.getCommunicationGroup(); + } + + ConstLocalViewType getConstLocalView() const + { + return ConstLocalViewType( op1.getConstLocalView(), op2.getConstLocalView() ); } - protected: - const T1 op1; - const T2 op2; - CommunicationGroup communicationGroup; - //typename OperandType< T1, DeviceType >::type op1; - //typename OperandType< T2, DeviceType >::type op2; +protected: + const T1& op1; + const T2& op2; }; template< typename T1, typename T2, - template< typename, typename > class Operation, - typename Communicator > -struct DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator, VectorExpressionVariable, ArithmeticVariable > + template< typename, typename > class Operation > +struct DistributedBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, ArithmeticVariable > { - using RealType = typename std::remove_const< typename T1::RealType >::type; + using RealType = decltype( Operation< typename T1::RealType, T2 >:: + evaluate( std::declval()[0], std::declval() ) ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - using CommunicatorType = Communicator; + using CommunicatorType = typename T1::CommunicatorType; using CommunicationGroup = typename CommunicatorType::CommunicationGroup; + using LocalRangeType = typename T1::LocalRangeType; + using ConstLocalViewType = BinaryExpressionTemplate< typename T1::ConstLocalViewType, T2, Operation >; - DistributedBinaryExpressionTemplate( const T1& a, const T2& b, const CommunicationGroup& group ) - : op1( a ), op2( b ), communicationGroup( group ){} + DistributedBinaryExpressionTemplate( const T1& a, const T2& b ) + : op1( a ), op2( b ) {} - DistributedBinaryExpressionTemplate evaluate( const T1& a, const T2& b ) + RealType getElement( const IndexType i ) const { - return DistributedBinaryExpressionTemplate( a, b ); + return getConstLocalView().getElement( i ); } - RealType getElement( const IndexType i ) const + // this is actually never executed, but needed for proper ExpressionVariableTypeGetter + // selection via HasSubscriptOperator type trait + RealType operator[]( const IndexType i ) const { - return Operation< typename T1::RealType, T2 >::evaluate( op1.getElement( i ), op2 ); + return getConstLocalView()[ i ]; } - __cuda_callable__ - RealType operator[]( const IndexType i ) const + IndexType getSize() const { - return Operation< typename T1::RealType, T2 >::evaluate( op1[ i ], op2 ); + return op1.getSize(); } - __cuda_callable__ - int getSize() const + LocalRangeType getLocalRange() const { - return op1.getSize(); + return op1.getLocalRange(); } CommunicationGroup getCommunicationGroup() const { - return communicationGroup; + return op1.getCommunicationGroup(); + } + + ConstLocalViewType getConstLocalView() const + { + return ConstLocalViewType( op1.getConstLocalView(), op2 ); } - protected: - const T1 op1; - const T2 op2; - CommunicationGroup communicationGroup; - //typename OperandType< T1, DeviceType >::type op1; - //typename OperandType< T2, DeviceType >::type op2; +protected: + const T1& op1; + const T2& op2; }; template< typename T1, typename T2, - template< typename, typename > class Operation, - typename Communicator > -struct DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator, ArithmeticVariable, VectorExpressionVariable > + template< typename, typename > class Operation > +struct DistributedBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorExpressionVariable > { - using RealType = typename std::remove_const< typename T2::RealType >::type; + using RealType = decltype( Operation< T1, typename T2::RealType >:: + evaluate( std::declval(), std::declval()[0] ) ); using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - using CommunicatorType = Communicator; + using CommunicatorType = typename T2::CommunicatorType; using CommunicationGroup = typename CommunicatorType::CommunicationGroup; + using LocalRangeType = typename T2::LocalRangeType; + using ConstLocalViewType = BinaryExpressionTemplate< T1, typename T2::ConstLocalViewType, Operation >; - DistributedBinaryExpressionTemplate( const T1& a, const T2& b, const CommunicationGroup& group ) - : op1( a ), op2( b ), communicationGroup( group ){} + DistributedBinaryExpressionTemplate( const T1& a, const T2& b ) + : op1( a ), op2( b ) {} - DistributedBinaryExpressionTemplate evaluate( const T1& a, const T2& b ) + RealType getElement( const IndexType i ) const { - return DistributedBinaryExpressionTemplate( a, b ); + return getConstLocalView().getElement( i ); } - RealType getElement( const IndexType i ) const + // this is actually never executed, but needed for proper ExpressionVariableTypeGetter + // selection via HasSubscriptOperator type trait + RealType operator[]( const IndexType i ) const { - return Operation< T1, typename T2::RealType >::evaluate( op1, op2.getElement( i ) ); + return getConstLocalView()[ i ]; } - __cuda_callable__ - RealType operator[]( const IndexType i ) const + IndexType getSize() const { - return Operation< T1, typename T2::RealType >::evaluate( op1, op2[ i ] ); + return op2.getSize(); } - __cuda_callable__ - int getSize() const + LocalRangeType getLocalRange() const { - return op2.getSize(); + return op2.getLocalRange(); } CommunicationGroup getCommunicationGroup() const { - return communicationGroup; + return op2.getCommunicationGroup(); } - protected: - const T1 op1; - const T2 op2; - CommunicationGroup communicationGroup; - //typename OperandType< T1, DeviceType >::type op1; - //typename OperandType< T2, DeviceType >::type op2; + ConstLocalViewType getConstLocalView() const + { + return ConstLocalViewType( op1, op2.getConstLocalView() ); + } + +protected: + const T1& op1; + const T2& op2; }; //// // Distributed unary expression template -// -// Parameter type serves mainly for pow( base, exp ). Here exp is parameter we need -// to pass to pow. template< typename T1, - template< typename > class Operation, - typename Parameter, - typename Communicator > -struct DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator, VectorExpressionVariable > + template< typename > class Operation > +struct DistributedUnaryExpressionTemplate< T1, Operation, VectorExpressionVariable > { - using RealType = typename std::remove_const< typename T1::RealType >::type; + using RealType = decltype( Operation< typename T1::RealType >:: + evaluate( std::declval()[0] ) ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - using CommunicatorType = Communicator; + using CommunicatorType = typename T1::CommunicatorType; using CommunicationGroup = typename CommunicatorType::CommunicationGroup; + using LocalRangeType = typename T1::LocalRangeType; + using ConstLocalViewType = UnaryExpressionTemplate< typename T1::ConstLocalViewType, Operation >; - DistributedUnaryExpressionTemplate( const T1& a, const Parameter& p, const CommunicationGroup& group ) - : operand( a ), parameter( p ), communicationGroup( group ) {} - - static DistributedUnaryExpressionTemplate evaluate( const T1& a ) - { - return DistributedUnaryExpressionTemplate( a ); - } + DistributedUnaryExpressionTemplate( const T1& a ) + : operand( a ) {} RealType getElement( const IndexType i ) const { - return Operation< typename T1::RealType >::evaluate( operand.getElement( i ), parameter ); + return getConstLocalView().getElement( i ); } - __cuda_callable__ + // this is actually never executed, but needed for proper ExpressionVariableTypeGetter + // selection via HasSubscriptOperator type trait RealType operator[]( const IndexType i ) const { - return Operation< typename T1::RealType >::evaluate( operand[ i ], parameter ); + return getConstLocalView()[ i ]; } - __cuda_callable__ - int getSize() const + IndexType getSize() const { - return operand.getSize(); + return operand.getSize(); } - void set( const Parameter& p ) { parameter = p; } - - const Parameter& get() { return parameter; } - - CommunicationGroup getCommunicationGroup() const + LocalRangeType getLocalRange() const { - return communicationGroup; + return operand.getLocalRange(); } - protected: - const T1 operand; - //typename OperandType< T1, DeviceType >::type operand; - Parameter parameter; - CommunicationGroup communicationGroup; -}; - -//// -// Distributed unary expression template with no parameter -template< typename T1, - template< typename > class Operation, - typename Communicator > -struct DistributedUnaryExpressionTemplate< T1, Operation, void, Communicator, VectorExpressionVariable > -{ - using RealType = typename std::remove_const< typename T1::RealType >::type; - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - using CommunicatorType = Communicator; - using CommunicationGroup = typename CommunicatorType::CommunicationGroup; - - DistributedUnaryExpressionTemplate( const T1& a, const CommunicationGroup& group ) - : operand( a ), communicationGroup( group ){} - - static DistributedUnaryExpressionTemplate evaluate( const T1& a ) - { - return DistributedUnaryExpressionTemplate( a ); - } - - RealType getElement( const IndexType i ) const - { - return Operation< typename T1::RealType >::evaluate( operand.getElement( i ) ); - } - - __cuda_callable__ - RealType operator[]( const IndexType i ) const + CommunicationGroup getCommunicationGroup() const { - return Operation< typename T1::RealType >::evaluate( operand[ i ] ); + return operand.getCommunicationGroup(); } - __cuda_callable__ - int getSize() const + ConstLocalViewType getConstLocalView() const { - return operand.getSize(); + return ConstLocalViewType( operand.getConstLocalView() ); } - CommunicationGroup getCommunicationGroup() const - { - return communicationGroup; - } - - protected: - const T1 operand; // TODO: fix - //typename std::add_const< typename OperandType< T1, DeviceType >::type >::type operand; - CommunicationGroup communicationGroup; +protected: + const T1& operand; }; //// // Output stream template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > -std::ostream& operator<<( std::ostream& str, const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& expression ) + template< typename, typename > class Operation > +std::ostream& operator<<( std::ostream& str, const DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression ) { str << "[ "; - for( int i = 0; i < expression.getLocalSize() - 1; i++ ) + for( int i = 0; i < expression.getSize() - 1; i++ ) str << expression.getElement( i ) << ", "; - str << expression.getElement( expression.getLocalSize() - 1 ) << " ]"; + str << expression.getElement( expression.getSize() - 1 ) << " ]"; return str; } template< typename T, - template< typename > class Operation, - typename Parameter, typename Communicator > -std::ostream& operator<<( std::ostream& str, const DistributedUnaryExpressionTemplate< T, Operation, Parameter, Communicator >& expression ) + template< typename > class Operation > +std::ostream& operator<<( std::ostream& str, const DistributedUnaryExpressionTemplate< T, Operation >& expression ) { str << "[ "; - for( int i = 0; i < expression.getLocalSize() - 1; i++ ) + for( int i = 0; i < expression.getSize() - 1; i++ ) str << expression.getElement( i ) << ", "; - str << expression.getElement( expression.getLocalSize() - 1 ) << " ]"; + str << expression.getElement( expression.getSize() - 1 ) << " ]"; return str; } +//// +// Operators are supposed to be in the same namespace as the expression templates + //// // Binary expressions addition template< typename L1, @@ -360,112 +319,85 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, - typename Communicator > + template< typename, typename > class ROperation > auto -operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Addition, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, - typename Communicator > + template< typename, typename > class Operation > auto -operator+( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator+( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - Addition, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -operator+( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator+( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return DistributedBinaryExpressionTemplate< - typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - Addition, Communicator >( a, b, b.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -operator+( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator+( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - Addition, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -operator+( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator+( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - return DistributedBinaryExpressionTemplate< - typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - Addition, Communicator >( a, b, b.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename L1, template< typename > class LOperation, - typename Parameter, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -operator+( const DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator+( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >, - DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Addition, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, typename Parameter, typename Communicator > + template< typename > class ROperation > auto -operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation, Parameter, Communicator >& b ) +operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - DistributedUnaryExpressionTemplate< R1, ROperation, Parameter, Communicator >, - Addition, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, - template< typename > class ROperation, typename RParameter, typename Communicator > + template< typename > class ROperation > auto -operator+( const DistributedUnaryExpressionTemplate< L1,LOperation, LParameter, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator+( const DistributedUnaryExpressionTemplate< L1,LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >, - Addition, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } //// @@ -475,109 +407,85 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Subtraction, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -operator-( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator-( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - Subtraction, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -operator-( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator-( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return DistributedBinaryExpressionTemplate< - typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - Subtraction, Communicator >( a, b, b.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -operator-( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator-( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - Subtraction, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -operator-( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator-( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - return DistributedBinaryExpressionTemplate< - typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - Subtraction, Communicator >( a, b, b.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -operator-( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator-( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Subtraction, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, typename Parameter, typename Communicator > + template< typename > class ROperation > auto -operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation, Parameter, Communicator >& b ) +operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - DistributedUnaryExpressionTemplate< R1, ROperation, Parameter, Communicator >, - Subtraction, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, - template< typename > class ROperation, typename RParameter, typename Communicator > + template< typename > class ROperation > auto -operator-( const DistributedUnaryExpressionTemplate< L1,LOperation, LParameter, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator-( const DistributedUnaryExpressionTemplate< L1,LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >, - Subtraction, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } //// @@ -587,109 +495,85 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Multiplication, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -operator*( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator*( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - Multiplication, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -operator*( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator*( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return DistributedBinaryExpressionTemplate< - typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - Multiplication, Communicator >( a, b, b.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -operator*( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator*( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - Multiplication, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -operator*( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator*( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - return DistributedBinaryExpressionTemplate< - typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - Multiplication, Communicator >( a, b, b.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -operator*( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator*( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Multiplication, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, typename Parameter, typename Communicator > + template< typename > class ROperation > auto -operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation, Parameter, Communicator >& b ) +operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - DistributedUnaryExpressionTemplate< R1, ROperation, Parameter, Communicator >, - Multiplication, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, - template< typename > class ROperation, typename RParameter, typename Communicator > + template< typename > class ROperation > auto -operator*( const DistributedUnaryExpressionTemplate< L1,LOperation, LParameter, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator*( const DistributedUnaryExpressionTemplate< L1,LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >, - Multiplication, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } //// @@ -699,109 +583,85 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Division, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -operator/( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator/( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - Division, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -operator/( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator/( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return DistributedBinaryExpressionTemplate< - typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - Division, Communicator >( a, b, b.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -operator/( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator/( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - Division, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -operator/( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator/( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - return DistributedBinaryExpressionTemplate< - typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - Division, Communicator >( a, b, b.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -operator/( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator/( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Division, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, typename Parameter, typename Communicator > + template< typename > class ROperation > auto -operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, Parameter, Communicator >& b ) +operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - DistributedUnaryExpressionTemplate< R1, ROperation, Parameter, Communicator >, - Division, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, - template< typename > class ROperation, typename RParameter, typename Communicator > + template< typename > class ROperation > auto -operator/( const DistributedUnaryExpressionTemplate< L1,LOperation, LParameter, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator/( const DistributedUnaryExpressionTemplate< L1,LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return DistributedBinaryExpressionTemplate< - DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >, - Division, Communicator >( a, b, a.getCommunicationGroup() ); + return DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } //// @@ -811,93 +671,74 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template EQ< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator==( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator==( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - using Right = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - return DistributedComparison< Left, Right >::template EQ< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator==( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator==( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - using Right = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - return DistributedComparison< Left, Right >::template EQ< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator==( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator==( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - using Right = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - return DistributedComparison< Left, Right >::template EQ< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator==( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator==( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - using Right = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - return DistributedComparison< Left, Right >::template EQ< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator==( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator==( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template EQ< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter, - typename Communicator > + template< typename > class ROperation > bool -operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >; - return DistributedComparison< Left, Right >::template EQ< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::EQ( a, b ); } //// @@ -907,107 +748,85 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template NE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator!=( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator!=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - using Right = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - return DistributedComparison< Left, Right >::template NE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter, typename Communicator > + template< typename > class ROperation > bool -operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >& b ) +operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) { - using Left = DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >; - using Right = DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >; - return DistributedComparison< Left, Right >::template NE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator!=( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator!=( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - using Right = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - return DistributedComparison< Left, Right >::template NE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator!=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator!=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - using Right = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - return DistributedComparison< Left, Right >::template NE< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator!=( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator!=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - using Right = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - return DistributedComparison< Left, Right >::template NE< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template NE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter, typename Communicator > + template< typename > class ROperation > bool -operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >; - return DistributedComparison< Left, Right >::template NE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::NE( a, b ); } //// @@ -1017,107 +836,85 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template LT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator<( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator<( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - using Right = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - return DistributedComparison< Left, Right >::template LT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter, typename Communicator > + template< typename > class ROperation > bool -operator<( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >& b ) +operator<( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) { - using Left = DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >; - using Right = DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >; - return DistributedComparison< Left, Right >::template LT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator<( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator<( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - using Right = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - return DistributedComparison< Left, Right >::template LT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator<( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator<( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - using Right = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - return DistributedComparison< Left, Right >::template LT< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator<( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator<( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - using Right = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - return DistributedComparison< Left, Right >::template LT< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator<( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator<( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template LT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter, typename Communicator > + template< typename > class ROperation > bool -operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >; - return DistributedComparison< Left, Right >::template LT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LT( a, b ); } //// @@ -1127,107 +924,85 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template LE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator<=( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator<=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - using Right = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - return DistributedComparison< Left, Right >::template LE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter, typename Communicator > + template< typename > class ROperation > bool -operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >& b ) +operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) { - using Left = DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >; - using Right = DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >; - return DistributedComparison< Left, Right >::template LE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator<=( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator<=( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - using Right = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - return DistributedComparison< Left, Right >::template LE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator<=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator<=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - using Right = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - return DistributedComparison< Left, Right >::template LE< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator<=( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator<=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - using Right = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - return DistributedComparison< Left, Right >::template LE< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template LE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter, typename Communicator > + template< typename > class ROperation > bool -operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >; - return DistributedComparison< Left, Right >::template LE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::LE( a, b ); } //// @@ -1237,92 +1012,74 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template GT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator>( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator>( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - using Right = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - return DistributedComparison< Left, Right >::template GT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator>( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator>( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - using Right = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - return DistributedComparison< Left, Right >::template GT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator>( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator>( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - using Right = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - return DistributedComparison< Left, Right >::template GT< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator>( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator>( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - using Right = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - return DistributedComparison< Left, Right >::template GT< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator>( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator>( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template GT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter, typename Communicator > + template< typename > class ROperation > bool -operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >; - return DistributedComparison< Left, Right >::template GT< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GT( a, b ); } //// @@ -1332,115 +1089,96 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template GE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator>=( const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +operator>=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - using Right = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - return DistributedComparison< Left, Right >::template GE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator>=( const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +operator>=( const DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - using Right = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - return DistributedComparison< Left, Right >::template GE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > bool -operator>=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +operator>=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType; - using Right = DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >; - return DistributedComparison< Left, Right >::template GE< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter, typename Communicator > + template< typename > class Operation > bool -operator>=( const typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +operator>=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType; - using Right = DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >; - return DistributedComparison< Left, Right >::template GE< typename Left::CommunicatorType >( a, b, b.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > bool -operator>=( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator>=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >; - using Right = DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >; - return DistributedComparison< Left, Right >::template GE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter, typename Communicator > + template< typename > class ROperation > bool -operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >; - using Right = DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >; - return DistributedComparison< Left, Right >::template GE< typename Left::CommunicatorType >( a, b, a.getCommunicationGroup() ); + return DistributedComparison< std::decay_t, std::decay_t >::GE( a, b ); } //// -// Unary minus +// Unary operations + +//// +// Minus template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return DistributedUnaryExpressionTemplate< - DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Minus, void, Communicator >( a, a.getCommunicationGroup() ); + return DistributedUnaryExpressionTemplate< std::decay_t, Minus >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -operator-( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +operator-( const DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return DistributedUnaryExpressionTemplate< - DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Minus, void, Communicator >( a, a.getCommunicationGroup() ); + return DistributedUnaryExpressionTemplate< std::decay_t, Minus >( a ); } //// @@ -1450,55 +1188,54 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return TNL::sum( a * b ); + return DistributedExpressionSum( a * b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter, - typename Communicator > + template< typename > class ROperation > auto -operator,( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >& b ) +operator,( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) { - return TNL::sum( a * b ); + return DistributedExpressionSum( a * b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -operator,( const DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +operator,( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return TNL::sum( a * b ); + return DistributedExpressionSum( a * b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, typename Parameter, typename Communicator > + template< typename > class ROperation > auto -operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation, Parameter, Communicator >& b ) +operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return TNL::sum( a * b ); + return DistributedExpressionSum( a * b ); } } // namespace Expressions } // namespace Containers +//// +// All operations are supposed to be in namespace TNL //// // Binary expression min @@ -1507,109 +1244,85 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Containers::Expressions::Min, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -min( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +min( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - Containers::Expressions::Min, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -min( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +min( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - Containers::Expressions::Min, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -min( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +min( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - Containers::Expressions::Min, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -min( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +min( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - Containers::Expressions::Min, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const typename Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const typename Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Containers::Expressions::Min, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, typename RParameter, typename Communicator > + template< typename > class ROperation > auto -min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >& b ) +min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >, - Containers::Expressions::Min, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, - template< typename > class ROperation, typename RParameter, typename Communicator > + template< typename > class ROperation > auto -min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation, LParameter, Communicator >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation >& a, + const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >, - Containers::Expressions::Min, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } //// @@ -1619,895 +1332,803 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Containers::Expressions::Max, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -max( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& a, - const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& b ) +max( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, + const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - Containers::Expressions::Max, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, typename T2, - template< typename, typename > class Operation, typename Communicator > + template< typename, typename > class Operation > auto -max( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& b ) +max( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, + const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >::RealType, - Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >, - Containers::Expressions::Max, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -max( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& a, - const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& b ) +max( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& a, + const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - Containers::Expressions::Max, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, - template< typename > class Operation, typename Parameter, typename Communicator > + template< typename > class Operation > auto -max( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& b ) +max( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, + const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >::RealType, - Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >, - Containers::Expressions::Max, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >, - Containers::Expressions::Max, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, typename RParameter, typename Communicator > + template< typename > class ROperation > auto -max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >, - Containers::Expressions::Max, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, - template< typename > class ROperation, typename RParameter, typename Communicator > + template< typename > class ROperation > auto -max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation, LParameter, Communicator >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation >& a, + const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::DistributedBinaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >, - Containers::Expressions::Max, Communicator >( a, b ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } - //// // Abs template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -abs( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +abs( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Abs, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Abs >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -abs( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +abs( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Abs, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Abs >( a ); } //// -// Sin +// Pow template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation, + typename Real > auto -sin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +pow( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Sin, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, Real, Containers::Expressions::Pow >( a, exp ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation, + typename Real > auto -sin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +pow( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, const Real& exp ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Sin, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t, Real, Containers::Expressions::Pow >( a, exp ); } //// -// Cos +// Exp template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -cos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +exp( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Cos, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Exp >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -cos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +exp( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Cos, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Exp >( a ); } //// -// Tan +// Sqrt template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -tan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +sqrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Tan, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sqrt >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -tan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +sqrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Tan, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sqrt >( a ); } //// -// Sqrt +// Cbrt template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -sqrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +cbrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Sqrt, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cbrt >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -sqrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +cbrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Sqrt, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cbrt >( a ); } //// -// Cbrt +// Log template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -cbrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +log( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Cbrt, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -cbrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +log( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Cbrt, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log >( a ); } //// -// Pow +// Log10 template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Real, typename Communicator > + template< typename, typename > class LOperation > auto -pow( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, const Real& exp ) +log10( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - auto e = Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Pow, Real, Communicator >( a, a.getCommunicationGroup() ); - e.parameter.set( exp ); - return e; + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log10 >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, - typename Real, typename Communicator > + template< typename > class LOperation > auto -pow( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, const Real& exp ) +log10( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - auto e = Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Pow, Real, Communicator >( a, a.getCommunicationGroup() ); - e.parameter.set( exp ); - return e; + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log10 >( a ); } //// -// Floor +// Log2 template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -floor( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +log2( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Floor, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log2 >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -floor( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +log2( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Floor, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log2 >( a ); } //// -// Ceil +// Sin +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +sin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sin >( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +sin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sin >( a ); +} + +//// +// Cos +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +cos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cos >( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +cos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cos >( a ); +} + +//// +// Tan template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -ceil( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +tan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Ceil, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tan >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -ceil( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +tan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Ceil, void, Communicator>( a ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tan >( a ); } //// // Asin template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -asin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +asin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Asin, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asin >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -asin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +asin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Asin, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asin >( a ); } //// // Acos template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -acos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +acos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Acos, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acos >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -acos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +acos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Acos, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acos >( a ); } //// // Atan template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -atan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +atan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Atan, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atan >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -atan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +atan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Atan, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atan >( a ); } //// // Sinh template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -sinh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +sinh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Sinh, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sinh >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -sinh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +sinh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Sinh, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sinh >( a ); } //// // Cosh template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -cosh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +cosh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Cosh, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cosh >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -cosh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +cosh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Cosh, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cosh >( a ); } //// // Tanh template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -tanh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +tanh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Tanh, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tanh >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -tanh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +tanh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Tanh, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tanh >( a ); } //// -// Log +// Asinh template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -log( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +asinh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Log, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asinh >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -log( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +asinh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Log, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asinh >( a ); } //// -// Log10 +// Acosh template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -log10( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +acosh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Log10, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acosh >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -log10( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +acosh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Log10, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acosh >( a ); } //// -// Log2 +// Atanh template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -log2( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +atanh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Log2, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atanh >( a ); } template< typename L1, - template< typename > class LOperation, typename LParameter, typename Communicator > + template< typename > class LOperation > auto -log2( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a ) +atanh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >, - Containers::Expressions::Log2, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atanh >( a ); } //// -// Exp +// Floor +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +floor( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Floor >( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +floor( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Floor >( a ); +} + +//// +// Ceil +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +ceil( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Ceil >( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +ceil( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Ceil >( a ); +} + +//// +// Sign template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -exp( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +sign( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >, - Containers::Expressions::Exp, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sign >( a ); } template< typename L1, + template< typename > class LOperation > +auto +sign( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sign >( a ); +} + +//// +// Cast +template< typename ResultType, + typename L1, + typename L2, + template< typename, typename > class LOperation, + // workaround: templated type alias cannot be declared at block level + template class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > +auto +cast( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, CastOperation >( a ); +} + +template< typename ResultType, + typename L1, template< typename > class LOperation, - typename Parameter, typename Communicator > + // workaround: templated type alias cannot be declared at block level + template class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > auto -exp( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a ) +cast( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::DistributedUnaryExpressionTemplate< - Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >, - Containers::Expressions::Exp, void, Communicator >( a, a.getCommunicationGroup() ); + return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t, CastOperation >( a ); } //// // Vertical operations - min template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - using CommunicatorType = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::CommunicatorType; - using Real = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::RealType; - Real result = std::numeric_limits< Real >::max(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionMin( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_MIN, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionMin( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, - typename Communicator > + template< typename > class LOperation > auto -min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a ) +min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - using CommunicatorType = Communicator; - using Real = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::RealType; - Real result = std::numeric_limits< Real >::max(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionMin( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_MIN, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionMin( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Communicator, - typename Index > + template< typename, typename > class LOperation > auto -argMin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, Index& arg ) -> decltype( ExpressionArgMin( a, arg ) ) +argMin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - throw Exceptions::NotImplementedError( "agrMin for distributed vector view is not implemented yet." ); - return ExpressionArgMin( a, arg ); + return DistributedExpressionArgMin( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, - typename Communicator, - typename Index > + template< typename > class LOperation > auto -argMin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a, Index& arg ) -> decltype( ExpressionMin( a, arg ) ) +argMin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - throw Exceptions::NotImplementedError( "agrMin for distributed vector view is not implemented yet." ); - return ExpressionArgMin( a ); + return DistributedExpressionArgMin( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::min(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionMax( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_MAX, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionMax( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, typename Communicator > + template< typename > class LOperation > auto -max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a ) +max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::min(); - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - Real localResult = Containers::Expressions::ExpressionMax( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_MAX, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionMax( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Communicator, - typename Index > + template< typename, typename > class LOperation > auto -argMax( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, Index& arg ) -> decltype( ExpressionArgMax( a, arg ) ) +argMax( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - throw Exceptions::NotImplementedError( "agrMax for distributed vector view is not implemented yet." ); - return ExpressionArgMax( a, arg ); + return DistributedExpressionArgMax( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, - typename Communicator, - typename Index > + template< typename > class LOperation > auto -argMax( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a, Index& arg ) -> decltype( ExpressionMax( a, arg ) ) +argMax( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - throw Exceptions::NotImplementedError( "agrMax for distributed vector view is not implemented yet." ); - return ExpressionArgMax( a ); + return DistributedExpressionArgMax( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Communicator > + template< typename, typename > class LOperation > auto -sum( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +sum( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::RealType; - using CommunicatorType = Communicator; //typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::CommunicatorType; - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionSum( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionSum( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, typename Communicator > + template< typename > class LOperation > auto -sum( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a ) +sum( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::CommunicatorType; - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionSum( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionSum( a ); +} + +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +maxNorm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return max( abs( a ) ); +} + +template< typename L1, + template< typename > class LOperation > +auto +maxNorm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return max( abs( a ) ); +} + +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +l1Norm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return DistributedExpressionL1Norm( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +l1Norm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return DistributedExpressionL1Norm( a ); +} + +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +l2Norm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return TNL::sqrt( DistributedExpressionL2Norm( a ) ); +} + +template< typename L1, + template< typename > class LOperation > +auto +l2Norm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return TNL::sqrt( DistributedExpressionL2Norm( a ) ); } template< typename L1, typename L2, template< typename, typename > class LOperation, - typename Communicator, typename Real > auto -lpNorm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, const Real& p ) +lpNorm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { - using CommunicatorType = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::CommunicatorType; - Real result = ( Real ) 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionLpNorm( a, p ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return TNL::pow( result, 1.0 / p ); + if( p == 1.0 ) + return l1Norm( a ); + if( p == 2.0 ) + return l2Norm( a ); + return TNL::pow( DistributedExpressionLpNorm( a, p ), 1.0 / p ); } template< typename L1, template< typename > class LOperation, - typename Parameter, - typename Communicator, typename Real > auto -lpNorm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a, const Real& p ) +lpNorm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, const Real& p ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { - using CommunicatorType = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::CommunicatorType; - Real result = ( Real ) 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = TNL::pow( Containers::Expressions::ExpressionLpNorm( a, p ), p ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_SUM, a.getCommunicationGroup() ); - } - return TNL::pow( result, 1.0 / p ); + if( p == 1.0 ) + return l1Norm( a ); + if( p == 2.0 ) + return l2Norm( a ); + return TNL::pow( DistributedExpressionLpNorm( a, p ), 1.0 / p ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -product( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +product( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::CommunicatorType; - Real result = ( Real ) 1.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionProduct( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_PROD, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionProduct( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, typename Communicator > + template< typename > class LOperation > auto -product( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a ) +product( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::CommunicatorType; - Real result = ( Real ) 1.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionProduct( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_PROD, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionProduct( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -logicalOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +logicalOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::CommunicatorType; - Real result = 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionLogicalOr( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_LOR, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionLogicalOr( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, typename Communicator > + template< typename > class LOperation > auto -logicalOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a ) +logicalOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::CommunicatorType; - bool result = false; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionLogicalOr( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_LOR, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionLogicalOr( a ); } - template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -logicalAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +logicalAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - using CommunicatorType = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::CommunicatorType; - bool result = false; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const bool localResult = Containers::Expressions::ExpressionLogicalAnd( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionLogicalAnd( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, typename Communicator > + template< typename > class LOperation > auto -logicalAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a ) +logicalAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - using CommunicatorType = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::CommunicatorType; - bool result = false; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const bool localResult = Containers::Expressions::ExpressionLogicalAnd( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_LAND, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionLogicalAnd( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -binaryOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +binaryOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::CommunicatorType; - Real result = ( Real ) 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionBinaryOr( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_BOR, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionBinaryOr( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, typename Communicator > + template< typename > class LOperation > auto -binaryOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a ) +binaryOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::CommunicatorType; - Real result = ( Real ) 0.0; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionBinaryOr( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_BOR, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionBinaryOr( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, typename Communicator > + template< typename, typename > class LOperation > auto -binaryAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a ) +binaryAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::max; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionBinaryAnd( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_BAND, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionBinaryAnd( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, typename Communicator > + template< typename > class LOperation > auto -binaryAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >& a ) +binaryAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) { - using Real = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::RealType; - using CommunicatorType = typename Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, Parameter, Communicator >::CommunicatorType; - Real result = std::numeric_limits< Real >::max; - if( a.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const Real localResult = Containers::Expressions::ExpressionBinaryAnd( a ); - CommunicatorType::template Allreduce< Real >( &localResult, &result, 1, MPI_BAND, a.getCommunicationGroup() ); - } - return result; + return DistributedExpressionBinaryAnd( a ); } template< typename L1, @@ -2515,50 +2136,47 @@ template< typename L1, template< typename, typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter, - typename Communicator > + template< typename > class ROperation > auto -dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation, RParameter, Communicator >& b ) +dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } template< typename L1, - template< typename > class LOperation, typename LParameter, + template< typename > class LOperation, typename R1, typename R2, - template< typename, typename > class ROperation, typename Communicator > + template< typename, typename > class ROperation > auto -dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation, LParameter, Communicator >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation, Communicator >& b ) +dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, + const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, typename RParameter, typename Communicator > + template< typename > class ROperation > auto -dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation, Communicator >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation, RParameter, Communicator >& b ) +dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, + const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } @@ -2568,12 +2186,11 @@ template< typename Vector, typename T1, typename T2, template< typename, typename > class Operation, - typename Communicator, typename Reduction, typename VolatileReduction, typename Result > Result evaluateAndReduce( Vector& lhs, - const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& expression, + const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression, Reduction& reduction, VolatileReduction& volatileReduction, const Result& zero ) @@ -2584,19 +2201,17 @@ Result evaluateAndReduce( Vector& lhs, RealType* lhs_data = lhs.getData(); auto fetch = [=] __cuda_callable__ ( IndexType i ) -> RealType { return ( lhs_data[ i ] = expression[ i ] ); }; - return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getLocalSize(), reduction, volatileReduction, fetch, zero ); + return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getSize(), reduction, volatileReduction, fetch, zero ); } template< typename Vector, typename T1, template< typename > class Operation, - typename Parameter, - typename Communicator, typename Reduction, typename VolatileReduction, typename Result > Result evaluateAndReduce( Vector& lhs, - const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& expression, + const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& expression, Reduction& reduction, VolatileReduction& volatileReduction, const Result& zero ) @@ -2607,7 +2222,7 @@ Result evaluateAndReduce( Vector& lhs, RealType* lhs_data = lhs.getData(); auto fetch = [=] __cuda_callable__ ( IndexType i ) -> RealType { return ( lhs_data[ i ] = expression[ i ] ); }; - return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getLocalSize(), reduction, volatileReduction, fetch, zero ); + return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getSize(), reduction, volatileReduction, fetch, zero ); } //// @@ -2616,12 +2231,11 @@ template< typename Vector, typename T1, typename T2, template< typename, typename > class Operation, - typename Communicator, typename Reduction, typename VolatileReduction, typename Result > Result addAndReduce( Vector& lhs, - const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& expression, + const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression, Reduction& reduction, VolatileReduction& volatileReduction, const Result& zero ) @@ -2636,19 +2250,17 @@ Result addAndReduce( Vector& lhs, lhs_data[ i ] += aux; return aux; }; - return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getLocalSize(), reduction, volatileReduction, fetch, zero ); + return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getSize(), reduction, volatileReduction, fetch, zero ); } template< typename Vector, typename T1, template< typename > class Operation, - typename Parameter, - typename Communicator, typename Reduction, typename VolatileReduction, typename Result > Result addAndReduce( Vector& lhs, - const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& expression, + const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& expression, Reduction& reduction, VolatileReduction& volatileReduction, const Result& zero ) @@ -2663,7 +2275,7 @@ Result addAndReduce( Vector& lhs, lhs_data[ i ] += aux; return aux; }; - return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getLocalSize(), reduction, volatileReduction, fetch, zero ); + return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getSize(), reduction, volatileReduction, fetch, zero ); } //// @@ -2672,12 +2284,11 @@ template< typename Vector, typename T1, typename T2, template< typename, typename > class Operation, - typename Communicator, typename Reduction, typename VolatileReduction, typename Result > Result addAndReduceAbs( Vector& lhs, - const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation, Communicator >& expression, + const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression, Reduction& reduction, VolatileReduction& volatileReduction, const Result& zero ) @@ -2692,19 +2303,17 @@ Result addAndReduceAbs( Vector& lhs, lhs_data[ i ] += aux; return TNL::abs( aux ); }; - return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getLocalSize(), reduction, volatileReduction, fetch, zero ); + return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getSize(), reduction, volatileReduction, fetch, zero ); } template< typename Vector, typename T1, template< typename > class Operation, - typename Parameter, - typename Communicator, typename Reduction, typename VolatileReduction, typename Result > Result addAndReduceAbs( Vector& lhs, - const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation, Parameter, Communicator >& expression, + const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& expression, Reduction& reduction, VolatileReduction& volatileReduction, const Result& zero ) @@ -2719,7 +2328,7 @@ Result addAndReduceAbs( Vector& lhs, lhs_data[ i ] += aux; return TNL::abs( aux ); }; - return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getLocalSize(), reduction, volatileReduction, fetch, zero ); + return Containers::Algorithms::Reduction< DeviceType >::reduce( lhs.getSize(), reduction, volatileReduction, fetch, zero ); } } // namespace TNL diff --git a/src/TNL/Containers/Expressions/DistributedVerticalOperations.h b/src/TNL/Containers/Expressions/DistributedVerticalOperations.h new file mode 100644 index 0000000000000000000000000000000000000000..4e569a45d46ea5db0a7bb24e9418ae064e30d5ac --- /dev/null +++ b/src/TNL/Containers/Expressions/DistributedVerticalOperations.h @@ -0,0 +1,284 @@ +/*************************************************************************** + DistributedVerticalOperations.h - description + ------------------- + begin : Aug 6, 2019 + copyright : (C) 2019 by Tomas Oberhuber et al. + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#include +#include + +namespace TNL { +namespace Containers { +namespace Expressions { + +//// +// Vertical operations +template< typename Expression > +auto DistributedExpressionMin( const Expression& expression ) -> std::decay_t< decltype( expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] ) >; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = std::numeric_limits< ResultType >::max(); + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionMin( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MIN, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression > +auto DistributedExpressionArgMin( const Expression& expression ) +-> std::pair< typename Expression::IndexType, std::decay_t< decltype( expression[0] ) > > +{ + using RealType = std::decay_t< decltype( expression[0] ) >; + using IndexType = typename Expression::IndexType; + using ResultType = std::pair< IndexType, RealType >; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result( -1, std::numeric_limits< RealType >::max() ); + const auto group = expression.getCommunicationGroup(); + if( group != CommunicatorType::NullGroup ) { + // compute local argMin + ResultType localResult = ExpressionArgMin( expression.getConstLocalView() ); + // transform local index to global index + localResult.first += expression.getLocalRange().getBegin(); + + // scatter local result to all processes and gather their results + const int nproc = CommunicatorType::GetSize( group ); + ResultType dataForScatter[ nproc ]; + for( int i = 0; i < nproc; i++ ) dataForScatter[ i ] = localResult; + ResultType gatheredResults[ nproc ]; + // NOTE: exchanging general data types does not work with MPI + //CommunicatorType::Alltoall( dataForScatter, 1, gatheredResults, 1, group ); + CommunicatorType::Alltoall( (char*) dataForScatter, sizeof(ResultType), (char*) gatheredResults, sizeof(ResultType), group ); + + // reduce the gathered data + const auto* _data = gatheredResults; // workaround for nvcc which does not allow to capture variable-length arrays (even in pure host code!) + auto fetch = [_data] ( IndexType i ) { return _data[ i ].second; }; + auto reduction = [] ( IndexType& aIdx, const IndexType& bIdx, RealType& a, const RealType& b ) { + if( a > b ) { + a = b; + aIdx = bIdx; + } + else if( a == b && bIdx < aIdx ) + aIdx = bIdx; + }; + auto volatileReduction = [] ( volatile IndexType& aIdx, volatile IndexType& bIdx, volatile RealType& a, volatile RealType& b ) { + if( a > b ) { + a = b; + aIdx = bIdx; + } + else if( a == b && bIdx < aIdx ) + aIdx = bIdx; + }; + result = Algorithms::Reduction< Devices::Host >::reduceWithArgument( (IndexType) nproc, reduction, volatileReduction, fetch, std::numeric_limits< RealType >::max() ); + result.first = gatheredResults[ result.first ].first; + } + return result; +} + +template< typename Expression > +auto DistributedExpressionMax( const Expression& expression ) -> std::decay_t< decltype( expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] ) >; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = std::numeric_limits< ResultType >::lowest(); + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionMax( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_MAX, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression > +auto DistributedExpressionArgMax( const Expression& expression ) +-> std::pair< typename Expression::IndexType, std::decay_t< decltype( expression[0] ) > > +{ + using RealType = std::decay_t< decltype( expression[0] ) >; + using IndexType = typename Expression::IndexType; + using ResultType = std::pair< IndexType, RealType >; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result( -1, std::numeric_limits< RealType >::lowest() ); + const auto group = expression.getCommunicationGroup(); + if( group != CommunicatorType::NullGroup ) { + // compute local argMax + ResultType localResult = ExpressionArgMax( expression.getConstLocalView() ); + // transform local index to global index + localResult.first += expression.getLocalRange().getBegin(); + + // scatter local result to all processes and gather their results + const int nproc = CommunicatorType::GetSize( group ); + ResultType dataForScatter[ nproc ]; + for( int i = 0; i < nproc; i++ ) dataForScatter[ i ] = localResult; + ResultType gatheredResults[ nproc ]; + // NOTE: exchanging general data types does not work with MPI + //CommunicatorType::Alltoall( dataForScatter, 1, gatheredResults, 1, group ); + CommunicatorType::Alltoall( (char*) dataForScatter, sizeof(ResultType), (char*) gatheredResults, sizeof(ResultType), group ); + + // reduce the gathered data + const auto* _data = gatheredResults; // workaround for nvcc which does not allow to capture variable-length arrays (even in pure host code!) + auto fetch = [_data] ( IndexType i ) { return _data[ i ].second; }; + auto reduction = [] ( IndexType& aIdx, const IndexType& bIdx, RealType& a, const RealType& b ) { + if( a < b ) { + a = b; + aIdx = bIdx; + } + else if( a == b && bIdx < aIdx ) + aIdx = bIdx; + }; + auto volatileReduction = [] ( volatile IndexType& aIdx, volatile IndexType& bIdx, volatile RealType& a, volatile RealType& b ) { + if( a < b ) { + a = b; + aIdx = bIdx; + } + else if( a == b && bIdx < aIdx ) + aIdx = bIdx; + }; + result = Algorithms::Reduction< Devices::Host >::reduceWithArgument( (IndexType) nproc, reduction, volatileReduction, fetch, std::numeric_limits< RealType >::lowest() ); + result.first = gatheredResults[ result.first ].first; + } + return result; +} + +template< typename Expression > +auto DistributedExpressionSum( const Expression& expression ) -> std::decay_t< decltype( expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] ) >; + using IndexType = typename Expression::IndexType; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = 0; + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionSum( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression > +auto DistributedExpressionL1Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] ) >; + using IndexType = typename Expression::IndexType; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = 0; + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionL1Norm( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression > +auto DistributedExpressionL2Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >; + using IndexType = typename Expression::IndexType; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = 0; + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionL2Norm( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression, typename Real > +auto DistributedExpressionLpNorm( const Expression& expression, const Real& p ) -> std::decay_t< decltype( TNL::pow( expression[0], p ) ) > +{ + using ResultType = std::decay_t< decltype( TNL::pow( expression[0], p ) ) >; + using IndexType = typename Expression::IndexType; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = 0; + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionLpNorm( expression.getConstLocalView(), p ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression > +auto DistributedExpressionProduct( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] ) >; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = 1; + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionProduct( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_PROD, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression > +auto DistributedExpressionLogicalAnd( const Expression& expression ) -> std::decay_t< decltype( expression[0] && expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] && expression[0] ) >; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = std::numeric_limits< ResultType >::max(); + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionLogicalAnd( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LAND, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression > +auto DistributedExpressionLogicalOr( const Expression& expression ) -> std::decay_t< decltype( expression[0] || expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] || expression[0] ) >; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = 0; + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionLogicalOr( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_LOR, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression > +auto DistributedExpressionBinaryAnd( const Expression& expression ) -> std::decay_t< decltype( expression[0] | expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] & expression[0] ) >; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = std::numeric_limits< ResultType >::max(); + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionLogicalBinaryAnd( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_BAND, expression.getCommunicationGroup() ); + } + return result; +} + +template< typename Expression > +auto DistributedExpressionBinaryOr( const Expression& expression ) -> std::decay_t< decltype( expression[0] | expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] | expression[0] ) >; + using CommunicatorType = typename Expression::CommunicatorType; + + ResultType result = 0; + if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { + const ResultType localResult = ExpressionBinaryOr( expression.getConstLocalView() ); + CommunicatorType::Allreduce( &localResult, &result, 1, MPI_BOR, expression.getCommunicationGroup() ); + } + return result; +} + +} // namespace Expressions +} // namespace Containers +} // namespace TNL diff --git a/src/TNL/Containers/Expressions/ExpressionTemplates.h b/src/TNL/Containers/Expressions/ExpressionTemplates.h index 60fbf2aab9b173d0a0a024d9ca1a73bd5753e0bd..5a069b0b9958bf794b204e1236f530201dd4748b 100644 --- a/src/TNL/Containers/Expressions/ExpressionTemplates.h +++ b/src/TNL/Containers/Expressions/ExpressionTemplates.h @@ -2,7 +2,7 @@ ExpressionTemplates.h - description ------------------- begin : Apr 18, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,13 +10,15 @@ #pragma once -#include +#include +#include #include #include -#include #include #include +#include +#include namespace TNL { namespace Containers { @@ -26,16 +28,14 @@ namespace Expressions { // Non-static unary expression template template< typename T1, template< typename > class Operation, - typename Parameter = void, ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value > struct UnaryExpressionTemplate {}; template< typename T1, template< typename > class Operation, - typename Parameter, ExpressionVariableType T1Type > -struct IsExpressionTemplate< UnaryExpressionTemplate< T1, Operation, Parameter, T1Type > > +struct IsExpressionTemplate< UnaryExpressionTemplate< T1, Operation, T1Type > > : std::true_type {}; @@ -63,42 +63,43 @@ template< typename T1, template< typename, typename > class Operation > struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, VectorExpressionVariable > { - using RealType = typename T1::RealType; + using RealType = decltype( Operation< typename T1::RealType, typename T2::RealType >:: + evaluate( std::declval()[0], std::declval()[0] ) ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - static_assert( std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value, "Attempt to mix operands allocated on different device types." ); - static_assert( IsStaticArrayType< T1 >::value == IsStaticArrayType< T2 >::value, "Attempt to mix static and non-static operands in binary expression templates." ); + static_assert( std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value, + "Attempt to mix operands which have different DeviceType." ); + static_assert( IsStaticArrayType< T1 >::value == IsStaticArrayType< T2 >::value, + "Attempt to mix static and non-static operands in binary expression templates." ); - BinaryExpressionTemplate( const T1& a, const T2& b ): op1( a ), op2( b ){} - - static BinaryExpressionTemplate evaluate( const T1& a, const T2& b ) + BinaryExpressionTemplate( const T1& a, const T2& b ) + : op1( a ), op2( b ) { - return BinaryExpressionTemplate( a, b ); + TNL_ASSERT_EQ( op1.getSize(), op2.getSize(), + "Attempt to mix operands with different sizes." ); } RealType getElement( const IndexType i ) const { - return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1.getElement( i ), op2.getElement( i ) ); + return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1.getElement( i ), op2.getElement( i ) ); } __cuda_callable__ RealType operator[]( const IndexType i ) const { - return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1[ i ], op2[ i ] ); + return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1[ i ], op2[ i ] ); } __cuda_callable__ - int getSize() const + IndexType getSize() const { - return op1.getSize(); + return op1.getSize(); } - protected: - const T1 op1; - const T2 op2; - //typename OperandType< T1, DeviceType >::type op1; - //typename OperandType< T2, DeviceType >::type op2; +protected: + const T1 op1; + const T2 op2; }; template< typename T1, @@ -106,39 +107,34 @@ template< typename T1, template< typename, typename > class Operation > struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, ArithmeticVariable > { - using RealType = typename T1::RealType; + using RealType = decltype( Operation< typename T1::RealType, T2 >:: + evaluate( std::declval()[0], std::declval() ) ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - BinaryExpressionTemplate( const T1& a, const T2& b ): op1( a ), op2( b ){} - - BinaryExpressionTemplate evaluate( const T1& a, const T2& b ) - { - return BinaryExpressionTemplate( a, b ); - } + BinaryExpressionTemplate( const T1& a, const T2& b ) + : op1( a ), op2( b ) {} RealType getElement( const IndexType i ) const { - return Operation< typename T1::RealType, T2 >::evaluate( op1.getElement( i ), op2 ); + return Operation< typename T1::RealType, T2 >::evaluate( op1.getElement( i ), op2 ); } __cuda_callable__ RealType operator[]( const IndexType i ) const { - return Operation< typename T1::RealType, T2 >::evaluate( op1[ i ], op2 ); + return Operation< typename T1::RealType, T2 >::evaluate( op1[ i ], op2 ); } __cuda_callable__ - int getSize() const + IndexType getSize() const { - return op1.getSize(); + return op1.getSize(); } - protected: - const T1 op1; - const T2 op2; - //typename OperandType< T1, DeviceType >::type op1; - //typename OperandType< T2, DeviceType >::type op2; +protected: + const T1 op1; + const T2 op2; }; template< typename T1, @@ -146,127 +142,69 @@ template< typename T1, template< typename, typename > class Operation > struct BinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorExpressionVariable > { - using RealType = typename T2::RealType; + using RealType = decltype( Operation< T1, typename T2::RealType >:: + evaluate( std::declval(), std::declval()[0] ) ); using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - BinaryExpressionTemplate( const T1& a, const T2& b ): op1( a ), op2( b ){} - - BinaryExpressionTemplate evaluate( const T1& a, const T2& b ) - { - return BinaryExpressionTemplate( a, b ); - } + BinaryExpressionTemplate( const T1& a, const T2& b ) + : op1( a ), op2( b ) {} RealType getElement( const IndexType i ) const { - return Operation< T1, typename T2::RealType >::evaluate( op1, op2.getElement( i ) ); + return Operation< T1, typename T2::RealType >::evaluate( op1, op2.getElement( i ) ); } __cuda_callable__ RealType operator[]( const IndexType i ) const { - return Operation< T1, typename T2::RealType >::evaluate( op1, op2[ i ] ); + return Operation< T1, typename T2::RealType >::evaluate( op1, op2[ i ] ); } __cuda_callable__ - int getSize() const + IndexType getSize() const { - return op2.getSize(); + return op2.getSize(); } - protected: - const T1 op1; - const T2 op2; - //typename OperandType< T1, DeviceType >::type op1; - //typename OperandType< T2, DeviceType >::type op2; +protected: + const T1 op1; + const T2 op2; }; //// // Non-static unary expression template -// -// Parameter type serves mainly for pow( base, exp ). Here exp is parameter we need -// to pass to pow. -template< typename T1, - template< typename > class Operation, - typename Parameter > -struct UnaryExpressionTemplate< T1, Operation, Parameter, VectorExpressionVariable > -{ - using RealType = typename T1::RealType; - using DeviceType = typename T1::DeviceType; - using IndexType = typename T1::IndexType; - - UnaryExpressionTemplate( const T1& a, const Parameter& p ) - : operand( a ), parameter( p ) {} - - static UnaryExpressionTemplate evaluate( const T1& a ) - { - return UnaryExpressionTemplate( a ); - } - - RealType getElement( const IndexType i ) const - { - return Operation< typename T1::RealType >::evaluate( operand.getElement( i ), parameter ); - } - - __cuda_callable__ - RealType operator[]( const IndexType i ) const - { - return Operation< typename T1::RealType >::evaluate( operand[ i ], parameter ); - } - - __cuda_callable__ - int getSize() const - { - return operand.getSize(); - } - - void set( const Parameter& p ) { parameter = p; } - - const Parameter& get() { return parameter; } - - protected: - const T1 operand; - //typename OperandType< T1, DeviceType >::type operand; - Parameter parameter; -}; - -//// -// Non-static unary expression template with no parameter template< typename T1, template< typename > class Operation > -struct UnaryExpressionTemplate< T1, Operation, void, VectorExpressionVariable > +struct UnaryExpressionTemplate< T1, Operation, VectorExpressionVariable > { - using RealType = typename T1::RealType; + using RealType = decltype( Operation< typename T1::RealType >:: + evaluate( std::declval()[0] ) ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - UnaryExpressionTemplate( const T1& a ): operand( a ){} - - static UnaryExpressionTemplate evaluate( const T1& a ) - { - return UnaryExpressionTemplate( a ); - } + UnaryExpressionTemplate( const T1& a ) + : operand( a ) {} RealType getElement( const IndexType i ) const { - return Operation< typename T1::RealType >::evaluate( operand.getElement( i ) ); + return Operation< typename T1::RealType >::evaluate( operand.getElement( i ) ); } __cuda_callable__ RealType operator[]( const IndexType i ) const { - return Operation< typename T1::RealType >::evaluate( operand[ i ] ); + return Operation< typename T1::RealType >::evaluate( operand[ i ] ); } __cuda_callable__ - int getSize() const + IndexType getSize() const { - return operand.getSize(); + return operand.getSize(); } - protected: - const T1 operand; // TODO: fix - //typename std::add_const< typename OperandType< T1, DeviceType >::type >::type operand; +protected: + const T1 operand; }; //// @@ -284,9 +222,8 @@ std::ostream& operator<<( std::ostream& str, const BinaryExpressionTemplate< T1, } template< typename T, - template< typename > class Operation, - typename Parameter > -std::ostream& operator<<( std::ostream& str, const UnaryExpressionTemplate< T, Operation, Parameter >& expression ) + template< typename > class Operation > +std::ostream& operator<<( std::ostream& str, const UnaryExpressionTemplate< T, Operation >& expression ) { str << "[ "; for( int i = 0; i < expression.getSize() - 1; i++ ) @@ -310,10 +247,7 @@ auto operator+( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< L1, L2, LOperation >, - BinaryExpressionTemplate< R1, R2, ROperation >, - Addition >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, @@ -323,10 +257,7 @@ auto operator+( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< T1, T2, Operation >, - typename BinaryExpressionTemplate< T1, T2, Operation >::RealType, - Addition >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, @@ -336,10 +267,7 @@ auto operator+( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - return BinaryExpressionTemplate< - typename BinaryExpressionTemplate< T1, T2, Operation >::RealType, - BinaryExpressionTemplate< T1, T2, Operation >, - Addition >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, @@ -348,10 +276,7 @@ auto operator+( const UnaryExpressionTemplate< T1, Operation >& a, const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< T1, Operation >, - typename UnaryExpressionTemplate< T1, Operation >::RealType, - Addition >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, @@ -360,10 +285,7 @@ auto operator+( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, const UnaryExpressionTemplate< T1, Operation >& b ) { - return BinaryExpressionTemplate< - typename UnaryExpressionTemplate< T1, Operation >::RealType, - UnaryExpressionTemplate< T1, Operation >, - Addition >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename L1, @@ -375,10 +297,7 @@ auto operator+( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< L1, LOperation >, - BinaryExpressionTemplate< R1, R2, ROperation >, - Addition >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename L1, @@ -390,10 +309,7 @@ auto operator+( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const UnaryExpressionTemplate< R1,ROperation >& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< L1, L2, LOperation >, - UnaryExpressionTemplate< R1, ROperation >, - Addition >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename L1, @@ -404,10 +320,7 @@ auto operator+( const UnaryExpressionTemplate< L1,LOperation >& a, const UnaryExpressionTemplate< R1,ROperation >& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< L1, LOperation >, - UnaryExpressionTemplate< R1, ROperation >, - Addition >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } //// @@ -422,10 +335,7 @@ auto operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< L1, L2, LOperation >, - BinaryExpressionTemplate< R1, R2, ROperation >, - Subtraction >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, @@ -435,10 +345,7 @@ auto operator-( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< T1, T2, Operation >, - typename BinaryExpressionTemplate< T1, T2, Operation >::RealType, - Subtraction >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, @@ -448,10 +355,7 @@ auto operator-( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - return BinaryExpressionTemplate< - typename BinaryExpressionTemplate< T1, T2, Operation >::RealType, - BinaryExpressionTemplate< T1, T2, Operation >, - Subtraction >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, @@ -460,10 +364,7 @@ auto operator-( const UnaryExpressionTemplate< T1, Operation >& a, const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< T1, Operation >, - typename UnaryExpressionTemplate< T1, Operation >::RealType, - Subtraction >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, @@ -472,10 +373,7 @@ auto operator-( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, const UnaryExpressionTemplate< T1, Operation >& b ) { - return BinaryExpressionTemplate< - typename UnaryExpressionTemplate< T1, Operation >::RealType, - UnaryExpressionTemplate< T1, Operation >, - Subtraction >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename L1, @@ -487,10 +385,7 @@ auto operator-( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< L1, LOperation >, - BinaryExpressionTemplate< R1, R2, ROperation >, - Subtraction >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename L1, @@ -502,10 +397,7 @@ auto operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const UnaryExpressionTemplate< R1,ROperation >& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< L1, L2, LOperation >, - UnaryExpressionTemplate< R1, ROperation >, - Subtraction >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename L1, @@ -516,10 +408,7 @@ auto operator-( const UnaryExpressionTemplate< L1,LOperation >& a, const UnaryExpressionTemplate< R1,ROperation >& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< L1, LOperation >, - UnaryExpressionTemplate< R1, ROperation >, - Subtraction >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } //// @@ -534,10 +423,7 @@ auto operator*( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< L1, L2, LOperation >, - BinaryExpressionTemplate< R1, R2, ROperation >, - Multiplication >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, @@ -547,10 +433,7 @@ auto operator*( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< T1, T2, Operation >, - typename BinaryExpressionTemplate< T1, T2, Operation >::RealType, - Multiplication >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, @@ -560,10 +443,7 @@ auto operator*( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - return BinaryExpressionTemplate< - typename BinaryExpressionTemplate< T1, T2, Operation >::RealType, - BinaryExpressionTemplate< T1, T2, Operation >, - Multiplication >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, @@ -572,10 +452,7 @@ auto operator*( const UnaryExpressionTemplate< T1, Operation >& a, const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< T1, Operation >, - typename UnaryExpressionTemplate< T1, Operation >::RealType, - Multiplication >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, @@ -584,10 +461,7 @@ auto operator*( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, const UnaryExpressionTemplate< T1, Operation >& b ) { - return BinaryExpressionTemplate< - typename UnaryExpressionTemplate< T1, Operation >::RealType, - UnaryExpressionTemplate< T1, Operation >, - Multiplication >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename L1, @@ -599,10 +473,7 @@ auto operator*( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< L1, LOperation >, - BinaryExpressionTemplate< R1, R2, ROperation >, - Multiplication >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename L1, @@ -614,10 +485,7 @@ auto operator*( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const UnaryExpressionTemplate< R1, ROperation >& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< L1, L2, LOperation >, - UnaryExpressionTemplate< R1, ROperation >, - Multiplication >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename L1, @@ -628,10 +496,7 @@ auto operator*( const UnaryExpressionTemplate< L1,LOperation >& a, const UnaryExpressionTemplate< R1,ROperation >& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< L1, LOperation >, - UnaryExpressionTemplate< R1, ROperation >, - Multiplication >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } //// @@ -646,10 +511,7 @@ auto operator/( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< L1, L2, LOperation >, - BinaryExpressionTemplate< R1, R2, ROperation >, - Division >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, @@ -659,10 +521,7 @@ auto operator/( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< T1, T2, Operation >, - typename BinaryExpressionTemplate< T1, T2, Operation >::RealType, - Division >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, @@ -672,10 +531,7 @@ auto operator/( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - return BinaryExpressionTemplate< - typename BinaryExpressionTemplate< T1, T2, Operation >::RealType, - BinaryExpressionTemplate< T1, T2, Operation >, - Division >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, @@ -684,10 +540,7 @@ auto operator/( const UnaryExpressionTemplate< T1, Operation >& a, const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< T1, Operation >, - typename UnaryExpressionTemplate< T1, Operation >::RealType, - Division >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, @@ -696,10 +549,7 @@ auto operator/( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, const UnaryExpressionTemplate< T1, Operation >& b ) { - return BinaryExpressionTemplate< - typename UnaryExpressionTemplate< T1, Operation >::RealType, - UnaryExpressionTemplate< T1, Operation >, - Division >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename L1, @@ -711,10 +561,7 @@ auto operator/( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< L1, LOperation >, - BinaryExpressionTemplate< R1, R2, ROperation >, - Division >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename L1, @@ -726,10 +573,7 @@ auto operator/( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const UnaryExpressionTemplate< R1,ROperation >& b ) { - return BinaryExpressionTemplate< - BinaryExpressionTemplate< L1, L2, LOperation >, - UnaryExpressionTemplate< R1, ROperation >, - Division >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename L1, @@ -740,10 +584,7 @@ auto operator/( const UnaryExpressionTemplate< L1,LOperation >& a, const UnaryExpressionTemplate< R1,ROperation >& b ) { - return BinaryExpressionTemplate< - UnaryExpressionTemplate< L1, LOperation >, - UnaryExpressionTemplate< R1, ROperation >, - Division >( a, b ); + return BinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } //// @@ -758,9 +599,7 @@ bool operator==( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::EQ( a, b ); + return Comparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, @@ -770,21 +609,16 @@ bool operator==( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = BinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - return Comparison< Left, Right >::EQ( a, b ); + return Comparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator==( const UnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator==( const UnaryExpressionTemplate< T1, Operation >& a, + const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = UnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return Comparison< Left, Right >::EQ( a, b ); + return Comparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, @@ -794,51 +628,40 @@ bool operator==( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = BinaryExpressionTemplate< T1, T2, Operation >; - return Comparison< Left, Right >::EQ( a, b ); + return Comparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator==( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const UnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator==( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, + const UnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = UnaryExpressionTemplate< T1, Operation, Parameter >; - return Comparison< Left, Right >::EQ( a, b ); + return Comparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > bool -operator==( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator==( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::EQ( a, b ); + return Comparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > bool operator==( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const UnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >; - return Comparison< Left, Right >::EQ( a, b ); + return Comparison< std::decay_t, std::decay_t >::EQ( a, b ); } //// @@ -853,9 +676,7 @@ bool operator!=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::NE( a, b ); + return Comparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, @@ -865,36 +686,27 @@ bool operator!=( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = BinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - return Comparison< Left, Right >::NE( a, b ); + return Comparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > bool -operator!=( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a, - const UnaryExpressionTemplate< R1, ROperation, RParameter >& b ) +operator!=( const UnaryExpressionTemplate< L1, LOperation >& a, + const UnaryExpressionTemplate< R1, ROperation >& b ) { - using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >; - return Comparison< Left, Right >::NE( a, b ); + return Comparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator!=( const UnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator!=( const UnaryExpressionTemplate< T1, Operation >& a, + const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = UnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return Comparison< Left, Right >::NE( a, b ); + return Comparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, @@ -904,51 +716,40 @@ bool operator!=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = BinaryExpressionTemplate< T1, T2, Operation >; - return Comparison< Left, Right >::NE( a, b ); + return Comparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator!=( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const UnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator!=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, + const UnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = UnaryExpressionTemplate< T1, Operation, Parameter >; - return Comparison< Left, Right >::NE( a, b ); + return Comparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > bool -operator!=( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator!=( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::NE( a, b ); + return Comparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > bool operator!=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const UnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >; - return Comparison< Left, Right >::NE( a, b ); + return Comparison< std::decay_t, std::decay_t >::NE( a, b ); } //// @@ -963,9 +764,7 @@ bool operator<( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::LT( a, b ); + return Comparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, @@ -975,36 +774,27 @@ bool operator<( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = BinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - return Comparison< Left, Right >::LT( a, b ); + return Comparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > bool -operator<( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a, - const UnaryExpressionTemplate< R1, ROperation, RParameter >& b ) +operator<( const UnaryExpressionTemplate< L1, LOperation >& a, + const UnaryExpressionTemplate< R1, ROperation >& b ) { - using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >; - return Comparison< Left, Right >::LT( a, b ); + return Comparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator<( const UnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator<( const UnaryExpressionTemplate< T1, Operation >& a, + const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = UnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return Comparison< Left, Right >::LT( a, b ); + return Comparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, @@ -1014,51 +804,40 @@ bool operator<( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = BinaryExpressionTemplate< T1, T2, Operation >; - return Comparison< Left, Right >::LT( a, b ); + return Comparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator<( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const UnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator<( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, + const UnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = UnaryExpressionTemplate< T1, Operation, Parameter >; - return Comparison< Left, Right >::LT( a, b ); + return Comparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > bool -operator<( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator<( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::LT( a, b ); + return Comparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > bool operator<( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const UnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >; - return Comparison< Left, Right >::LT( a, b ); + return Comparison< std::decay_t, std::decay_t >::LT( a, b ); } //// @@ -1073,9 +852,7 @@ bool operator<=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::LE( a, b ); + return Comparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, @@ -1085,36 +862,27 @@ bool operator<=( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = BinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - return Comparison< Left, Right >::LE( a, b ); + return Comparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > bool -operator<=( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a, - const UnaryExpressionTemplate< R1, ROperation, RParameter >& b ) +operator<=( const UnaryExpressionTemplate< L1, LOperation >& a, + const UnaryExpressionTemplate< R1, ROperation >& b ) { - using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >; - return Comparison< Left, Right >::LE( a, b ); + return Comparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator<=( const UnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator<=( const UnaryExpressionTemplate< T1, Operation >& a, + const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = UnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return Comparison< Left, Right >::LE( a, b ); + return Comparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, @@ -1124,51 +892,40 @@ bool operator<=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = BinaryExpressionTemplate< T1, T2, Operation >; - return Comparison< Left, Right >::LE( a, b ); + return Comparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator<=( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const UnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator<=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, + const UnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = UnaryExpressionTemplate< T1, Operation, Parameter >; - return Comparison< Left, Right >::LE( a, b ); + return Comparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > bool -operator<=( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator<=( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::LE( a, b ); + return Comparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > bool operator<=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const UnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >; - return Comparison< Left, Right >::LE( a, b ); + return Comparison< std::decay_t, std::decay_t >::LE( a, b ); } //// @@ -1183,9 +940,7 @@ bool operator>( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::GT( a, b ); + return Comparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, @@ -1195,21 +950,16 @@ bool operator>( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = BinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - return Comparison< Left, Right >::GT( a, b ); + return Comparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator>( const UnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator>( const UnaryExpressionTemplate< T1, Operation >& a, + const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = UnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return Comparison< Left, Right >::GT( a, b ); + return Comparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, @@ -1219,51 +969,40 @@ bool operator>( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = BinaryExpressionTemplate< T1, T2, Operation >; - return Comparison< Left, Right >::GT( a, b ); + return Comparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator>( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const UnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator>( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, + const UnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = UnaryExpressionTemplate< T1, Operation, Parameter >; - return Comparison< Left, Right >::GT( a, b ); + return Comparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > bool -operator>( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator>( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::GT( a, b ); + return Comparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > bool operator>( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const UnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >; - return Comparison< Left, Right >::GT( a, b ); + return Comparison< std::decay_t, std::decay_t >::GT( a, b ); } //// @@ -1278,9 +1017,7 @@ bool operator>=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::GE( a, b ); + return Comparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, @@ -1290,21 +1027,16 @@ bool operator>=( const BinaryExpressionTemplate< T1, T2, Operation >& a, const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = BinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - return Comparison< Left, Right >::GE( a, b ); + return Comparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator>=( const UnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator>=( const UnaryExpressionTemplate< T1, Operation >& a, + const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = UnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return Comparison< Left, Right >::GE( a, b ); + return Comparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, @@ -1314,51 +1046,40 @@ bool operator>=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const BinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename BinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = BinaryExpressionTemplate< T1, T2, Operation >; - return Comparison< Left, Right >::GE( a, b ); + return Comparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > bool -operator>=( const typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const UnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator>=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, + const UnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename UnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = UnaryExpressionTemplate< T1, Operation, Parameter >; - return Comparison< Left, Right >::GE( a, b ); + return Comparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > bool -operator>=( const UnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator>=( const UnaryExpressionTemplate< L1, LOperation >& a, const BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = UnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = BinaryExpressionTemplate< R1, R2, ROperation >; - return Comparison< Left, Right >::GE( a, b ); + return Comparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > bool operator>=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const UnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = BinaryExpressionTemplate< L1, L2, LOperation >; - using Right = UnaryExpressionTemplate< R1, ROperation, RParameter >; - return Comparison< Left, Right >::GE( a, b ); + return Comparison< std::decay_t, std::decay_t >::GE( a, b ); } //// @@ -1372,9 +1093,7 @@ template< typename L1, auto operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return UnaryExpressionTemplate< - BinaryExpressionTemplate< L1, L2, LOperation >, - Minus >( a ); + return UnaryExpressionTemplate< std::decay_t, Minus >( a ); } template< typename L1, @@ -1382,9 +1101,7 @@ template< typename L1, auto operator-( const UnaryExpressionTemplate< L1, LOperation >& a ) { - return UnaryExpressionTemplate< - UnaryExpressionTemplate< L1, LOperation >, - Minus >( a ); + return UnaryExpressionTemplate< std::decay_t, Minus >( a ); } //// @@ -1455,10 +1172,7 @@ auto min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, @@ -1468,10 +1182,7 @@ auto min( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a, const typename Containers::Expressions::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::Min >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, @@ -1481,10 +1192,7 @@ auto min( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const Containers::Expressions::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::Min >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, @@ -1493,10 +1201,7 @@ auto min( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a, const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< T1, Operation >, - typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, @@ -1505,10 +1210,7 @@ auto min( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a, const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType, - Containers::Expressions::UnaryExpressionTemplate< T1, Operation >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename L1, @@ -1520,10 +1222,7 @@ auto min( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename L1, @@ -1535,10 +1234,7 @@ auto min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename L1, @@ -1549,10 +1245,7 @@ auto min( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a, const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } //// @@ -1567,10 +1260,7 @@ auto max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, @@ -1580,10 +1270,7 @@ auto max( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a, const typename Containers::Expressions::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::Max >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, @@ -1593,10 +1280,7 @@ auto max( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const Containers::Expressions::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::Max >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, @@ -1605,10 +1289,7 @@ auto max( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a, const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< T1, Operation >, - typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, @@ -1617,10 +1298,7 @@ auto max( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a, const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType, - Containers::Expressions::UnaryExpressionTemplate< T1, Operation >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename L1, @@ -1632,10 +1310,7 @@ auto max( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename L1, @@ -1647,10 +1322,7 @@ auto max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename L1, @@ -1661,10 +1333,7 @@ auto max( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a, const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::BinaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } //// @@ -1675,9 +1344,7 @@ template< typename L1, auto abs( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Abs >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Abs >( a ); } template< typename L1, @@ -1685,199 +1352,199 @@ template< typename L1, auto abs( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Abs >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Abs >( a ); } //// -// Sin +// Pow +template< typename L1, + typename L2, + template< typename, typename > class LOperation, + typename Real > +auto +pow( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp ) +{ + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, Real, Containers::Expressions::Pow >( a, exp ); +} + +template< typename L1, + template< typename > class LOperation, + typename Real > +auto +pow( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Real& exp ) +{ + return Containers::Expressions::BinaryExpressionTemplate< std::decay_t, Real, Containers::Expressions::Pow >( a, exp ); +} + +//// +// Exp template< typename L1, typename L2, template< typename, typename > class LOperation > auto -sin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +exp( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Sin >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Exp >( a ); } template< typename L1, template< typename > class LOperation > auto -sin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +exp( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Sin >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Exp >( a ); } //// -// Cos +// Sqrt template< typename L1, typename L2, template< typename, typename > class LOperation > auto -cos( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +sqrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Cos >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sqrt >( a ); } template< typename L1, template< typename > class LOperation > auto -cos( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +sqrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Cos >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sqrt >( a ); } //// -// Tan +// Cbrt template< typename L1, typename L2, template< typename, typename > class LOperation > auto -tan( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +cbrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Tan >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cbrt >( a ); } template< typename L1, template< typename > class LOperation > auto -tan( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +cbrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Tan >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cbrt >( a ); } //// -// Sqrt +// Log template< typename L1, typename L2, template< typename, typename > class LOperation > auto -sqrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +log( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Sqrt >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log >( a ); } template< typename L1, template< typename > class LOperation > auto -sqrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +log( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Sqrt >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log >( a ); } //// -// Cbrt +// Log10 template< typename L1, typename L2, template< typename, typename > class LOperation > auto -cbrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +log10( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Cbrt >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log10 >( a ); } template< typename L1, template< typename > class LOperation > auto -cbrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +log10( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Cbrt >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log10 >( a ); } //// -// Pow +// Log2 template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Real > + template< typename, typename > class LOperation > auto -pow( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp ) +log2( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - auto e = Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Pow >( a ); - e.parameter.set( exp ); - return e; + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log2 >( a ); } template< typename L1, - template< typename > class LOperation, - typename Real > + template< typename > class LOperation > auto -pow( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Real& exp ) +log2( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - auto e = Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Pow >( a ); - e.parameter.set( exp ); - return e; + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log2 >( a ); } //// -// Floor +// Sin template< typename L1, typename L2, template< typename, typename > class LOperation > auto -floor( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +sin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Floor >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sin >( a ); } template< typename L1, template< typename > class LOperation > auto -floor( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +sin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Floor >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sin >( a ); } //// -// Ceil +// Cos template< typename L1, typename L2, template< typename, typename > class LOperation > auto -ceil( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +cos( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Ceil >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cos >( a ); } template< typename L1, template< typename > class LOperation > auto -ceil( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +cos( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Ceil >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cos >( a ); +} + +//// +// Tan +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +tan( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tan >( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +tan( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tan >( a ); } //// @@ -1888,9 +1555,7 @@ template< typename L1, auto asin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Asin >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asin >( a ); } template< typename L1, @@ -1898,9 +1563,7 @@ template< typename L1, auto asin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Asin >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asin >( a ); } //// @@ -1911,9 +1574,7 @@ template< typename L1, auto acos( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Acos >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acos >( a ); } template< typename L1, @@ -1921,9 +1582,7 @@ template< typename L1, auto acos( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Acos >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acos >( a ); } //// @@ -1934,9 +1593,7 @@ template< typename L1, auto atan( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Atan >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atan >( a ); } template< typename L1, @@ -1944,9 +1601,7 @@ template< typename L1, auto atan( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Atan >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atan >( a ); } //// @@ -1957,9 +1612,7 @@ template< typename L1, auto sinh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Sinh >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sinh >( a ); } template< typename L1, @@ -1967,9 +1620,7 @@ template< typename L1, auto sinh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Sinh >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sinh >( a ); } //// @@ -1980,9 +1631,7 @@ template< typename L1, auto cosh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Cosh >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cosh >( a ); } template< typename L1, @@ -1990,9 +1639,7 @@ template< typename L1, auto cosh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Cosh >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cosh >( a ); } //// @@ -2003,9 +1650,7 @@ template< typename L1, auto tanh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Tanh >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tanh >( a ); } template< typename L1, @@ -2013,101 +1658,146 @@ template< typename L1, auto tanh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Tanh >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tanh >( a ); } //// -// Log +// Asinh template< typename L1, typename L2, template< typename, typename > class LOperation > auto -log( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +asinh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Log >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asinh >( a ); } template< typename L1, template< typename > class LOperation > auto -log( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +asinh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Log >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asinh >( a ); } //// -// Log10 +// Acosh template< typename L1, typename L2, template< typename, typename > class LOperation > auto -log10( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +acosh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Log10 >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acosh >( a ); } template< typename L1, template< typename > class LOperation > auto -log10( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +acosh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Log10 >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acosh >( a ); } //// -// Log2 +// Atanh template< typename L1, typename L2, template< typename, typename > class LOperation > auto -log2( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +atanh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Log2 >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atanh >( a ); } template< typename L1, template< typename > class LOperation > auto -log2( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +atanh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Log2 >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atanh >( a ); } //// -// Exp +// Floor template< typename L1, typename L2, template< typename, typename > class LOperation > auto -exp( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +floor( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Exp >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Floor >( a ); } template< typename L1, template< typename > class LOperation > auto -exp( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +floor( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Floor >( a ); +} + +//// +// Ceil +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +ceil( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Ceil >( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +ceil( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Ceil >( a ); +} + +//// +// Sign +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +sign( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::UnaryExpressionTemplate< - Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >, - Containers::Expressions::Exp >( a ); + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sign >( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +sign( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sign >( a ); +} + +//// +// Cast +template< typename ResultType, + typename L1, + typename L2, + template< typename, typename > class LOperation, + // workaround: templated type alias cannot be declared at block level + template class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > +auto +cast( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, CastOperation >( a ); +} + +template< typename ResultType, + typename L1, + template< typename > class LOperation, + // workaround: templated type alias cannot be declared at block level + template class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > +auto +cast( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, CastOperation >( a ); } //// @@ -2122,32 +1812,28 @@ min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation } template< typename L1, - template< typename > class LOperation, - typename Parameter > + template< typename > class LOperation > auto -min( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a ) +min( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { return ExpressionMin( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Index > + template< typename, typename > class LOperation > auto -argMin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, Index& arg ) +argMin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return ExpressionArgMin( a, arg ); + return ExpressionArgMin( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, - typename Index > + template< typename > class LOperation > auto -argMin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a, Index& arg ) +argMin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return ExpressionArgMin( a, arg ); + return ExpressionArgMin( a ); } template< typename L1, @@ -2160,32 +1846,28 @@ max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation } template< typename L1, - template< typename > class LOperation, - typename Parameter > + template< typename > class LOperation > auto -max( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a ) +max( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { return ExpressionMax( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Index > + template< typename, typename > class LOperation > auto -argMax( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, Index& arg ) +argMax( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return ExpressionArgMax( a, arg ); + return ExpressionArgMax( a ); } template< typename L1, - template< typename > class LOperation, - typename Parameter, - typename Index > + template< typename > class LOperation > auto -argMax( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a, Index& arg ) +argMax( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { - return ExpressionArgMax( a, arg ); + return ExpressionArgMax( a ); } template< typename L1, @@ -2198,41 +1880,92 @@ sum( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation } template< typename L1, - template< typename > class LOperation, - typename Parameter > + template< typename > class LOperation > auto -sum( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a ) +sum( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { return ExpressionSum( a ); } +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +maxNorm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return max( abs( a ) ); +} + +template< typename L1, + template< typename > class LOperation > +auto +maxNorm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +{ + return max( abs( a ) ); +} + +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +l1Norm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return ExpressionL1Norm( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +l1Norm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +{ + return ExpressionL1Norm( a ); +} + +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +l2Norm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return TNL::sqrt( ExpressionL2Norm( a ) ); +} + +template< typename L1, + template< typename > class LOperation > +auto +l2Norm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) +{ + return TNL::sqrt( ExpressionL2Norm( a ) ); +} + template< typename L1, typename L2, template< typename, typename > class LOperation, typename Real > auto lpNorm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p ) --> decltype( ExpressionLpNorm( a, p ) ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { if( p == 1.0 ) - return ExpressionLpNorm( a, p ); + return l1Norm( a ); if( p == 2.0 ) - return TNL::sqrt( ExpressionLpNorm( a, p ) ); + return l2Norm( a ); return TNL::pow( ExpressionLpNorm( a, p ), 1.0 / p ); } template< typename L1, template< typename > class LOperation, - typename Parameter, typename Real > auto -lpNorm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a, const Real& p ) --> decltype( ExpressionLpNorm( a, p ) ) +lpNorm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Real& p ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { if( p == 1.0 ) - return ExpressionLpNorm( a, p ); + return l1Norm( a ); if( p == 2.0 ) - return TNL::sqrt( ExpressionLpNorm( a, p ) ); + return l2Norm( a ); return TNL::pow( ExpressionLpNorm( a, p ), 1.0 / p ); } @@ -2246,10 +1979,9 @@ product( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOpera } template< typename L1, - template< typename > class LOperation, - typename Parameter > + template< typename > class LOperation > auto -product( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a ) +product( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { return ExpressionProduct( a ); } @@ -2264,10 +1996,9 @@ logicalOr( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOpe } template< typename L1, - template< typename > class LOperation, - typename Parameter > + template< typename > class LOperation > auto -logicalOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a ) +logicalOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { return ExpressionLogicalOr( a ); } @@ -2282,10 +2013,9 @@ logicalAnd( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOp } template< typename L1, - template< typename > class LOperation, - typename Parameter > + template< typename > class LOperation > auto -logicalAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a ) +logicalAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { return ExpressionLogicalAnd( a ); } @@ -2300,10 +2030,9 @@ binaryOr( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOper } template< typename L1, - template< typename > class LOperation, - typename Parameter > + template< typename > class LOperation > auto -binaryOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a ) +binaryOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { return ExpressionBinaryOr( a ); } @@ -2318,10 +2047,9 @@ binaryAnd( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOpe } template< typename L1, - template< typename > class LOperation, - typename Parameter > + template< typename > class LOperation > auto -binaryAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation, Parameter >& a ) +binaryAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) { return ExpressionBinaryAnd( a ); } @@ -2336,7 +2064,7 @@ auto dot( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } template< typename L1, @@ -2347,7 +2075,7 @@ auto dot( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } template< typename L1, @@ -2359,7 +2087,7 @@ auto dot( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } template< typename L1, @@ -2371,7 +2099,7 @@ auto dot( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } diff --git a/src/TNL/Containers/Expressions/ExpressionVariableType.h b/src/TNL/Containers/Expressions/ExpressionVariableType.h index 15858ffed073f9ab69341df64cf9a7f2d35f2a39..ad9ab830ed30f1cbfc4f2701140ffb1efcb819e7 100644 --- a/src/TNL/Containers/Expressions/ExpressionVariableType.h +++ b/src/TNL/Containers/Expressions/ExpressionVariableType.h @@ -2,7 +2,7 @@ ExpressionVariableType.h - description ------------------- begin : Apr 18, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ diff --git a/src/TNL/Containers/Expressions/ExpressionTemplatesOperations.h b/src/TNL/Containers/Expressions/HorizontalOperations.h similarity index 91% rename from src/TNL/Containers/Expressions/ExpressionTemplatesOperations.h rename to src/TNL/Containers/Expressions/HorizontalOperations.h index 2b6ca2aca6c02b495d0f779b1a64c325cd2d5c62..4bfe6a0146fde1f3ac52a2e2175ea56f422ad56c 100644 --- a/src/TNL/Containers/Expressions/ExpressionTemplatesOperations.h +++ b/src/TNL/Containers/Expressions/HorizontalOperations.h @@ -1,8 +1,8 @@ /*************************************************************************** - ExpressionTemplatesOperations.h - description + HorizontalOperations.h - description ------------------- begin : Apr 18, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -96,12 +96,11 @@ struct Abs } }; -template< typename T1 > +template< typename T1, typename T2 > struct Pow { - template< typename Real > __cuda_callable__ - static auto evaluate( const T1& a, const Real& exp ) -> decltype( TNL::pow( a, exp ) ) + static auto evaluate( const T1& a, const T2& exp ) -> decltype( TNL::pow( a, exp ) ) { return TNL::pow( a, exp ); } @@ -317,6 +316,20 @@ struct Sign } }; +template< typename ResultType > +struct Cast +{ + template< typename T1 > + struct Operation + { + __cuda_callable__ + static auto evaluate( const T1& a ) -> ResultType + { + return static_cast( a ); + } + }; +}; + } // namespace Expressions } // namespace Containers } // namespace TNL diff --git a/src/TNL/Containers/Expressions/StaticComparison.h b/src/TNL/Containers/Expressions/StaticComparison.h index a39fabc9b021231f51561983c74cca9b13bc5cbd..d12f1c12bdd0a5a4f63f1e3f507141d675f34706 100644 --- a/src/TNL/Containers/Expressions/StaticComparison.h +++ b/src/TNL/Containers/Expressions/StaticComparison.h @@ -2,7 +2,7 @@ StaticComparison.h - description ------------------- begin : Jul 3, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -11,19 +11,17 @@ #pragma once #include -#include +#include namespace TNL { - namespace Containers { - namespace Expressions { +namespace Containers { +namespace Expressions { template< typename T1, typename T2, ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > -struct StaticComparison -{ -}; +struct StaticComparison; ///// // Static comparison of vector expressions @@ -31,13 +29,13 @@ template< typename T1, typename T2 > struct StaticComparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > { - __cuda_callable__ static bool EQ( const T1& a, const T2& b ) { - TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); + if( a.getSize() != b.getSize() ) + return false; for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] != b[ i ] ) + if( ! (a[ i ] == b[ i ]) ) return false; return true; } @@ -53,7 +51,7 @@ struct StaticComparison< T1, T2, VectorExpressionVariable, VectorExpressionVaria { TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] <= b[ i ] ) + if( ! (a[ i ] > b[ i ]) ) return false; return true; } @@ -63,7 +61,7 @@ struct StaticComparison< T1, T2, VectorExpressionVariable, VectorExpressionVaria { TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] < b[ i ] ) + if( ! (a[ i ] >= b[ i ]) ) return false; return true; } @@ -73,7 +71,7 @@ struct StaticComparison< T1, T2, VectorExpressionVariable, VectorExpressionVaria { TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] >= b[ i ] ) + if( ! (a[ i ] < b[ i ]) ) return false; return true; } @@ -83,7 +81,7 @@ struct StaticComparison< T1, T2, VectorExpressionVariable, VectorExpressionVaria { TNL_ASSERT_EQ( a.getSize(), b.getSize(), "Sizes of expressions to be compared do not fit." ); for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] > b[ i ] ) + if( ! (a[ i ] <= b[ i ]) ) return false; return true; } @@ -95,12 +93,11 @@ template< typename T1, typename T2 > struct StaticComparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > { - __cuda_callable__ static bool EQ( const T1& a, const T2& b ) { for( int i = 0; i < b.getSize(); i++ ) - if( a != b[ i ] ) + if( ! (a == b[ i ]) ) return false; return true; } @@ -115,7 +112,7 @@ struct StaticComparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > static bool GT( const T1& a, const T2& b ) { for( int i = 0; i < b.getSize(); i++ ) - if( a <= b[ i ] ) + if( ! (a > b[ i ]) ) return false; return true; } @@ -124,7 +121,7 @@ struct StaticComparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > static bool GE( const T1& a, const T2& b ) { for( int i = 0; i < b.getSize(); i++ ) - if( a < b[ i ] ) + if( ! (a >= b[ i ]) ) return false; return true; } @@ -133,7 +130,7 @@ struct StaticComparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > static bool LT( const T1& a, const T2& b ) { for( int i = 0; i < b.getSize(); i++ ) - if( a >= b[ i ] ) + if( ! (a < b[ i ]) ) return false; return true; } @@ -142,7 +139,7 @@ struct StaticComparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > static bool LE( const T1& a, const T2& b ) { for( int i = 0; i < b.getSize(); i++ ) - if( a > b[ i ] ) + if( ! (a <= b[ i ]) ) return false; return true; } @@ -154,12 +151,11 @@ template< typename T1, typename T2 > struct StaticComparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > { - __cuda_callable__ static bool EQ( const T1& a, const T2& b ) { for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] != b ) + if( ! (a[ i ] == b) ) return false; return true; } @@ -174,7 +170,7 @@ struct StaticComparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > static bool GT( const T1& a, const T2& b ) { for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] <= b ) + if( ! (a[ i ] > b) ) return false; return true; } @@ -183,7 +179,7 @@ struct StaticComparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > static bool GE( const T1& a, const T2& b ) { for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] < b ) + if( ! (a[ i ] >= b) ) return false; return true; } @@ -192,7 +188,7 @@ struct StaticComparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > static bool LT( const T1& a, const T2& b ) { for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] >= b ) + if( ! (a[ i ] < b) ) return false; return true; } @@ -201,12 +197,12 @@ struct StaticComparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > static bool LE( const T1& a, const T2& b ) { for( int i = 0; i < a.getSize(); i++ ) - if( a[ i ] > b ) + if( ! (a[ i ] <= b) ) return false; return true; } }; - } //namespace Expressions - } // namespace Containers +} // namespace Expressions +} // namespace Containers } // namespace TNL diff --git a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h index 7fe4379f6edcd7c9a23b00049bebb38bf4d6334c..cce42592306b71cb6ca513b1e6efacbf29d1f5f6 100644 --- a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h +++ b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h @@ -2,7 +2,7 @@ StaticExpressionTemplates.h - description ------------------- begin : Apr 18, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,14 +10,15 @@ #pragma once -#include +#include +#include #include #include -#include #include +#include #include -#include +#include namespace TNL { namespace Containers { @@ -25,16 +26,14 @@ namespace Expressions { template< typename T1, template< typename > class Operation, - typename Parameter = void, ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value > struct StaticUnaryExpressionTemplate {}; template< typename T1, template< typename > class Operation, - typename Parameter, ExpressionVariableType T1Type > -struct IsExpressionTemplate< StaticUnaryExpressionTemplate< T1, Operation, Parameter, T1Type > > +struct IsExpressionTemplate< StaticUnaryExpressionTemplate< T1, Operation, T1Type > > : std::true_type {}; @@ -63,34 +62,25 @@ template< typename T1, template< typename, typename > class Operation > struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, VectorExpressionVariable > { - static_assert( IsStaticArrayType< T1 >::value, "Left-hand side operand of static expression is not static, i.e. based on static vector." ); - static_assert( IsStaticArrayType< T2 >::value, "Right-hand side operand of static expression is not static, i.e. based on static vector." ); - using RealType = typename T1::RealType; + using RealType = decltype( Operation< typename T1::RealType, typename T2::RealType >:: + evaluate( std::declval()[0], std::declval()[0] ) ); - static_assert( IsStaticArrayType< T1 >::value == IsStaticArrayType< T2 >::value, "Attempt to mix static and non-static operands in binary expression templates" ); - static_assert( T1::getSize() == T2::getSize(), "Attempt to mix static operands with different sizes." ); + static_assert( IsStaticArrayType< T1 >::value, + "Left-hand side operand of static expression is not static, i.e. based on static vector." ); + static_assert( IsStaticArrayType< T2 >::value, + "Right-hand side operand of static expression is not static, i.e. based on static vector." ); + static_assert( T1::getSize() == T2::getSize(), + "Attempt to mix static operands with different sizes." ); static constexpr int getSize() { return T1::getSize(); }; __cuda_callable__ - StaticBinaryExpressionTemplate( const T1& a, const T2& b ): op1( a ), op2( b ){} - - __cuda_callable__ - static StaticBinaryExpressionTemplate evaluate( const T1& a, const T2& b ) - { - return StaticBinaryExpressionTemplate( a, b ); - } - - RealType getElement( const int i ) const - { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); - return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1[ i ], op2[ i ] ); - } + StaticBinaryExpressionTemplate( const T1& a, const T2& b ) + : op1( a ), op2( b ) {} __cuda_callable__ RealType operator[]( const int i ) const { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); return Operation< typename T1::RealType, typename T2::RealType >::evaluate( op1[ i ], op2[ i ] ); } @@ -112,9 +102,9 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariab return (*this)[ 2 ]; } - protected: - const T1 &op1; - const T2 &op2; +protected: + const T1& op1; + const T2& op2; }; template< typename T1, @@ -122,32 +112,21 @@ template< typename T1, template< typename, typename > class Operation > struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, ArithmeticVariable > { - static_assert( IsStaticArrayType< T1 >::value, "Left-hand side operand of static expression is not static, i.e. based on static vector." ); + static_assert( IsStaticArrayType< T1 >::value, + "Left-hand side operand of static expression is not static, i.e. based on static vector." ); - using RealType = typename T1::RealType; + using RealType = decltype( Operation< typename T1::RealType, T2 >:: + evaluate( std::declval()[0], std::declval() ) ); static constexpr int getSize() { return T1::getSize(); }; - __cuda_callable__ - StaticBinaryExpressionTemplate( const T1& a, const T2& b ): op1( a ), op2( b ){} - - __cuda_callable__ - StaticBinaryExpressionTemplate evaluate( const T1& a, const T2& b ) - { - return StaticBinaryExpressionTemplate( a, b ); - } - - RealType getElement( const int i ) const - { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); - return Operation< typename T1::RealType, T2 >::evaluate( op1[ i ], op2 ); - } + StaticBinaryExpressionTemplate( const T1& a, const T2& b ) + : op1( a ), op2( b ) {} __cuda_callable__ RealType operator[]( const int i ) const { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); return Operation< typename T1::RealType, T2 >::evaluate( op1[ i ], op2 ); } @@ -169,10 +148,9 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariab return (*this)[ 2 ]; } - protected: - const T1 &op1; - const T2 &op2; - +protected: + const T1& op1; + const T2& op2; }; template< typename T1, @@ -180,32 +158,21 @@ template< typename T1, template< typename, typename > class Operation > struct StaticBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorExpressionVariable > { - static_assert( IsStaticArrayType< T2 >::value, "Right-hand side operand of static expression is not static, i.e. based on static vector." ); + static_assert( IsStaticArrayType< T2 >::value, + "Right-hand side operand of static expression is not static, i.e. based on static vector." ); - using RealType = typename T2::RealType; + using RealType = decltype( Operation< T1, typename T2::RealType >:: + evaluate( std::declval(), std::declval()[0] ) ); static constexpr int getSize() { return T2::getSize(); }; - __cuda_callable__ - StaticBinaryExpressionTemplate( const T1& a, const T2& b ): op1( a ), op2( b ){} - - __cuda_callable__ - StaticBinaryExpressionTemplate evaluate( const T1& a, const T2& b ) - { - return StaticBinaryExpressionTemplate( a, b ); - } - - RealType getElement( const int i ) const - { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); - return Operation< T1, typename T2::RealType >::evaluate( op1, op2[ i ] ); - } + StaticBinaryExpressionTemplate( const T1& a, const T2& b ) + : op1( a ), op2( b ) {} __cuda_callable__ RealType operator[]( const int i ) const { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); return Operation< T1, typename T2::RealType >::evaluate( op1, op2[ i ] ); } @@ -227,106 +194,29 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, Ve return (*this)[ 2 ]; } - protected: - const T1& op1; - const T2& op2; +protected: + const T1& op1; + const T2& op2; }; //// // Static unary expression template -// -// Parameter type serves mainly for pow( base, exp ). Here exp is parameter we need -// to pass to pow. -template< typename T1, - template< typename > class Operation, - typename Parameter > -struct StaticUnaryExpressionTemplate< T1, Operation, Parameter, VectorExpressionVariable > -{ - static_assert( IsStaticArrayType< T1 >::value, "Operand of static expression is not static, i.e. based on static vector." ); - - using RealType = typename T1::RealType; - - static constexpr int getSize() { return T1::getSize(); }; - - __cuda_callable__ - StaticUnaryExpressionTemplate( const T1& a, const Parameter& p ) - : operand( a ), parameter( p ) {} - - __cuda_callable__ - static StaticUnaryExpressionTemplate evaluate( const T1& a ) - { - return StaticUnaryExpressionTemplate( a ); - } - - RealType getElement( const int i ) const - { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); - return Operation< typename T1::RealType >::evaluate( operand[ i ], parameter ); - } - - __cuda_callable__ - RealType operator[]( const int i ) const - { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); - return Operation< typename T1::RealType >::evaluate( operand[ i ], parameter ); - } - - __cuda_callable__ - RealType x() const - { - return (*this)[ 0 ]; - } - - __cuda_callable__ - RealType y() const - { - return (*this)[ 1 ]; - } - - __cuda_callable__ - RealType z() const - { - return (*this)[ 2 ]; - } - - void set( const Parameter& p ) { parameter = p; } - - const Parameter& get() { return parameter; } - - protected: - const T1& operand; - Parameter parameter; -}; - -//// -// Static unary expression template with no parameter template< typename T1, template< typename > class Operation > -struct StaticUnaryExpressionTemplate< T1, Operation, void, VectorExpressionVariable > +struct StaticUnaryExpressionTemplate< T1, Operation, VectorExpressionVariable > { - using RealType = typename T1::RealType; + using RealType = decltype( Operation< typename T1::RealType >:: + evaluate( std::declval()[0] ) ); static constexpr int getSize() { return T1::getSize(); }; __cuda_callable__ - StaticUnaryExpressionTemplate( const T1& a ): operand( a ){} - - __cuda_callable__ - static StaticUnaryExpressionTemplate evaluate( const T1& a ) - { - return StaticUnaryExpressionTemplate( a ); - } - - RealType getElement( const int i ) const - { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); - return Operation< typename T1::RealType >::evaluate( operand[ i ] ); - } + StaticUnaryExpressionTemplate( const T1& a ) + : operand( a ) {} __cuda_callable__ RealType operator[]( const int i ) const { - TNL_ASSERT_LT( i, this->getSize(), "Asking for element with index larger than expression size." ); return Operation< typename T1::RealType >::evaluate( operand[ i ] ); } @@ -348,8 +238,8 @@ struct StaticUnaryExpressionTemplate< T1, Operation, void, VectorExpressionVaria return (*this)[ 2 ]; } - protected: - const T1& operand; +protected: + const T1& operand; }; //// @@ -360,114 +250,92 @@ template< typename L1, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto operator+( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< L1, L2, LOperation >, - StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Addition >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto operator+( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< T1, T2, Operation >, - typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - Addition >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto operator+( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return StaticBinaryExpressionTemplate< - typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - StaticBinaryExpressionTemplate< T1, T2, Operation >, - Addition >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -operator+( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator+( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - Addition >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -operator+( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator+( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - return StaticBinaryExpressionTemplate< - typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - Addition >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto -operator+( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator+( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Addition >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto operator+( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) + const StaticUnaryExpressionTemplate< R1, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< L1, L2, LOperation >, - StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Addition >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto operator+( const StaticUnaryExpressionTemplate< L1,LOperation >& a, const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Addition >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Addition >( a, b ); } //// @@ -478,114 +346,92 @@ template< typename L1, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< L1, L2, LOperation >, - StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto operator-( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< T1, T2, Operation >, - typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto operator-( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return StaticBinaryExpressionTemplate< - typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - StaticBinaryExpressionTemplate< T1, T2, Operation >, - Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -operator-( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator-( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -operator-( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator-( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - return StaticBinaryExpressionTemplate< - typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto -operator-( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator-( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< L1, L2, LOperation >, - StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto operator-( const StaticUnaryExpressionTemplate< L1,LOperation >& a, const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Subtraction >( a, b ); } //// @@ -596,114 +442,92 @@ template< typename L1, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto operator*( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< L1, L2, LOperation >, - StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Multiplication >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto operator*( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< T1, T2, Operation >, - typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - Multiplication >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto operator*( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return StaticBinaryExpressionTemplate< - typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - StaticBinaryExpressionTemplate< T1, T2, Operation >, - Multiplication >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -operator*( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator*( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - Multiplication >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -operator*( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator*( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - return StaticBinaryExpressionTemplate< - typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - Multiplication >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto -operator*( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator*( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Multiplication >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto operator*( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1, ROperation, RParameter >& b ) + const StaticUnaryExpressionTemplate< R1, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< L1, L2, LOperation >, - StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Multiplication >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto operator*( const StaticUnaryExpressionTemplate< L1,LOperation >& a, const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Multiplication >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Multiplication >( a, b ); } //// @@ -714,114 +538,92 @@ template< typename L1, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto operator/( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< L1, L2, LOperation >, - StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Division >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto operator/( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< T1, T2, Operation >, - typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - Division >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto operator/( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return StaticBinaryExpressionTemplate< - typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - StaticBinaryExpressionTemplate< T1, T2, Operation >, - Division >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -operator/( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator/( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - Division >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -operator/( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator/( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - return StaticBinaryExpressionTemplate< - typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - Division >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto -operator/( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator/( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Division >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto operator/( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticBinaryExpressionTemplate< L1, L2, LOperation >, - StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Division >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto operator/( const StaticUnaryExpressionTemplate< L1,LOperation >& a, const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return StaticBinaryExpressionTemplate< - StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Division >( a, b ); + return StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Division >( a, b ); } //// @@ -837,9 +639,7 @@ bool operator==( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::EQ( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, @@ -850,22 +650,17 @@ bool operator==( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = StaticBinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - return StaticComparison< Left, Right >::EQ( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator==( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator==( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return StaticComparison< Left, Right >::EQ( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, @@ -876,54 +671,43 @@ bool operator==( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = StaticBinaryExpressionTemplate< T1, T2, Operation >; - return StaticComparison< Left, Right >::EQ( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator==( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator==( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - return StaticComparison< Left, Right >::EQ( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > __cuda_callable__ bool -operator==( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator==( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticUnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::EQ( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::EQ( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ bool operator==( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticUnaryExpressionTemplate< R1, ROperation, RParameter >; - return StaticComparison< Left, Right >::EQ( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::EQ( a, b ); } //// @@ -939,9 +723,7 @@ bool operator!=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::NE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, @@ -952,38 +734,29 @@ bool operator!=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = StaticBinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - return StaticComparison< Left, Right >::NE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ bool -operator!=( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, - const StaticUnaryExpressionTemplate< R1, ROperation, RParameter >& b ) +operator!=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, + const StaticUnaryExpressionTemplate< R1, ROperation >& b ) { - using Left = StaticUnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = StaticUnaryExpressionTemplate< R1, ROperation, RParameter >; - return StaticComparison< Left, Right >::NE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator!=( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator!=( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return StaticComparison< Left, Right >::NE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, @@ -994,54 +767,43 @@ bool operator!=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = StaticBinaryExpressionTemplate< T1, T2, Operation >; - return StaticComparison< Left, Right >::NE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator!=( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator!=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - return StaticComparison< Left, Right >::NE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > __cuda_callable__ bool -operator!=( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator!=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticUnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::NE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::NE( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ bool operator!=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticUnaryExpressionTemplate< R1, ROperation, RParameter >; - return StaticComparison< Left, Right >::NE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::NE( a, b ); } //// @@ -1057,9 +819,7 @@ bool operator<( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::LT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, @@ -1070,38 +830,29 @@ bool operator<( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = StaticBinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - return StaticComparison< Left, Right >::LT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ bool -operator<( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, - const StaticUnaryExpressionTemplate< R1, ROperation, RParameter >& b ) +operator<( const StaticUnaryExpressionTemplate< L1, LOperation >& a, + const StaticUnaryExpressionTemplate< R1, ROperation >& b ) { - using Left = StaticUnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = StaticUnaryExpressionTemplate< R1, ROperation, RParameter >; - return StaticComparison< Left, Right >::LT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator<( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator<( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return StaticComparison< Left, Right >::LT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, @@ -1112,54 +863,43 @@ bool operator<( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = StaticBinaryExpressionTemplate< T1, T2, Operation >; - return StaticComparison< Left, Right >::LT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator<( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator<( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - return StaticComparison< Left, Right >::LT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > __cuda_callable__ bool -operator<( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator<( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticUnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::LT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LT( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ bool operator<( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticUnaryExpressionTemplate< R1, ROperation, RParameter >; - return StaticComparison< Left, Right >::LT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LT( a, b ); } //// @@ -1175,9 +915,7 @@ bool operator<=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::LE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, @@ -1188,38 +926,29 @@ bool operator<=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = StaticBinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - return StaticComparison< Left, Right >::LE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ bool -operator<=( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, - const StaticUnaryExpressionTemplate< R1, ROperation, RParameter >& b ) +operator<=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, + const StaticUnaryExpressionTemplate< R1, ROperation >& b ) { - using Left = StaticUnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = StaticUnaryExpressionTemplate< R1, ROperation, RParameter >; - return StaticComparison< Left, Right >::LE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator<=( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator<=( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return StaticComparison< Left, Right >::LE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, @@ -1230,54 +959,43 @@ bool operator<=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = StaticBinaryExpressionTemplate< T1, T2, Operation >; - return StaticComparison< Left, Right >::LE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator<=( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator<=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - return StaticComparison< Left, Right >::LE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > __cuda_callable__ bool -operator<=( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator<=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticUnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::LE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LE( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ bool operator<=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticUnaryExpressionTemplate< R1, ROperation, RParameter >; - return StaticComparison< Left, Right >::LE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::LE( a, b ); } //// @@ -1293,9 +1011,7 @@ bool operator>( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::GT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, @@ -1306,22 +1022,17 @@ bool operator>( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = StaticBinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - return StaticComparison< Left, Right >::GT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator>( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator>( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return StaticComparison< Left, Right >::GT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, @@ -1332,54 +1043,43 @@ bool operator>( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = StaticBinaryExpressionTemplate< T1, T2, Operation >; - return StaticComparison< Left, Right >::GT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator>( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator>( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - return StaticComparison< Left, Right >::GT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > __cuda_callable__ bool -operator>( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator>( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticUnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::GT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GT( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ bool operator>( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticUnaryExpressionTemplate< R1, ROperation, RParameter >; - return StaticComparison< Left, Right >::GT( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GT( a, b ); } //// @@ -1395,9 +1095,7 @@ bool operator>=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::GE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, @@ -1408,22 +1106,17 @@ bool operator>=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - using Left = StaticBinaryExpressionTemplate< T1, T2, Operation >; - using Right = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - return StaticComparison< Left, Right >::GE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator>=( const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +operator>=( const StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - using Left = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - using Right = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - return StaticComparison< Left, Right >::GE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, @@ -1434,54 +1127,43 @@ bool operator>=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - using Left = typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType; - using Right = StaticBinaryExpressionTemplate< T1, T2, Operation >; - return StaticComparison< Left, Right >::GE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > __cuda_callable__ bool -operator>=( const typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +operator>=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const StaticUnaryExpressionTemplate< T1, Operation >& b ) { - using Left = typename StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType; - using Right = StaticUnaryExpressionTemplate< T1, Operation, Parameter >; - return StaticComparison< Left, Right >::GE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > __cuda_callable__ bool -operator>=( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator>=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - using Left = StaticUnaryExpressionTemplate< L1, LOperation, LParameter >; - using Right = StaticBinaryExpressionTemplate< R1, R2, ROperation >; - return StaticComparison< Left, Right >::GE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GE( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ bool operator>=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation, RParameter >& b ) + const StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - using Left = StaticBinaryExpressionTemplate< L1, L2, LOperation >; - using Right = StaticUnaryExpressionTemplate< R1, ROperation, RParameter >; - return StaticComparison< Left, Right >::GE( a, b ); + return StaticComparison< std::decay_t, std::decay_t >::GE( a, b ); } //// @@ -1496,21 +1178,16 @@ __cuda_callable__ auto operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return StaticUnaryExpressionTemplate< - StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Minus >( a ); + return StaticUnaryExpressionTemplate< std::decay_t, Minus >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -operator-( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +operator-( const StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return StaticUnaryExpressionTemplate< - StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Minus >( a ); + return StaticUnaryExpressionTemplate< std::decay_t, Minus >( a ); } //// @@ -1543,13 +1220,12 @@ operator,( const StaticUnaryExpressionTemplate< L1, LOperation >& a, template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > __cuda_callable__ auto -operator,( const StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +operator,( const StaticUnaryExpressionTemplate< L1, LOperation >& a, const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { return StaticExpressionSum( a * b ); @@ -1559,8 +1235,7 @@ template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ auto operator,( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, @@ -1584,9 +1259,8 @@ std::ostream& operator<<( std::ostream& str, const StaticBinaryExpressionTemplat } template< typename T, - template< typename > class Operation, - typename Parameter > -std::ostream& operator<<( std::ostream& str, const StaticUnaryExpressionTemplate< T, Operation, Parameter >& expression ) + template< typename > class Operation > +std::ostream& operator<<( std::ostream& str, const StaticUnaryExpressionTemplate< T, Operation >& expression ) { str << "[ "; for( int i = 0; i < expression.getSize() - 1; i++ ) @@ -1609,114 +1283,92 @@ template< typename L1, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto min( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >, - typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto min( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -min( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +min( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -min( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +min( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto -min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1,LOperation >& a, const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Containers::Expressions::Min >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Min >( a, b ); } //// @@ -1727,114 +1379,92 @@ template< typename L1, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto max( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a, const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >, - typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, typename T2, template< typename, typename > class Operation > +__cuda_callable__ auto max( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType, - Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -max( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >& a, - const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& b ) +max( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a, + const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename T1, - template< typename > class Operation, - typename Parameter > + template< typename > class Operation > +__cuda_callable__ auto -max( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >& b ) +max( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, + const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >::RealType, - Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > +__cuda_callable__ auto -max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > +__cuda_callable__ auto max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1,LOperation >& a, const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return Containers::Expressions::StaticBinaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation, RParameter >, - Containers::Expressions::Max >( a, b ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, std::decay_t, Containers::Expressions::Max >( a, b ); } //// @@ -1846,235 +1476,228 @@ __cuda_callable__ auto abs( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Abs >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Abs >( a ); +} + +template< typename L1, + template< typename > class LOperation > +__cuda_callable__ +auto +abs( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Abs >( a ); +} + +//// +// Pow +template< typename L1, + typename L2, + template< typename, typename > class LOperation, + typename Real > +__cuda_callable__ +auto +pow( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp ) +{ + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, Real, Containers::Expressions::Pow >( a, exp ); } template< typename L1, template< typename > class LOperation, - typename LParameter > + typename Real > __cuda_callable__ auto -abs( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +pow( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Real& exp ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Abs >( a ); + return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t, Real, Containers::Expressions::Pow >( a, exp ); } //// -// Sin +// Exp template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -sin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +exp( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Sin >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Exp >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -sin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +exp( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Sin >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Exp >( a ); } //// -// Cos +// Sqrt template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -cos( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +sqrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Cos >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sqrt >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -cos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +sqrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Cos >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sqrt >( a ); } //// -// Tan +// Cbrt template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -tan( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +cbrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Tan >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cbrt >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -tan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +cbrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Tan >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cbrt >( a ); } //// -// Sqrt +// Log template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -sqrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +log( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Sqrt >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -sqrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +log( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Sqrt >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log >( a ); } //// -// Cbrt +// Log10 template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -cbrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +log10( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Cbrt >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log10 >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -cbrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +log10( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Cbrt >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log10 >( a ); } //// -// Pow +// Log2 template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Real > + template< typename, typename > class LOperation > __cuda_callable__ auto -pow( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp ) +log2( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - auto e = Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Pow >( a ); - e.parameter.set( exp ); - return e; + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log2 >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter, - typename Real > + template< typename > class LOperation > __cuda_callable__ auto -pow( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, const Real& exp ) +log2( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - auto e = Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Pow >( a ); - e.parameter.set( exp ); - return e; + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Log2 >( a ); } //// -// Floor +// Sin template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -floor( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +sin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Floor >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sin >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -floor( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +sin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Floor >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sin >( a ); } //// -// Ceil +// Cos template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -ceil( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +cos( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Ceil >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cos >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > +__cuda_callable__ +auto +cos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cos >( a ); +} + +//// +// Tan +template< typename L1, + typename L2, + template< typename, typename > class LOperation > __cuda_callable__ auto -ceil( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +tan( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Ceil >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tan >( a ); +} + +template< typename L1, + template< typename > class LOperation > +__cuda_callable__ +auto +tan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tan >( a ); } //// @@ -2086,21 +1709,16 @@ __cuda_callable__ auto asin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Asin >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asin >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -asin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +asin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Asin >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asin >( a ); } //// @@ -2112,21 +1730,16 @@ __cuda_callable__ auto acos( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Acos >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acos >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -acos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +acos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Acos >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acos >( a ); } //// @@ -2138,21 +1751,16 @@ __cuda_callable__ auto atan( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Atan >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atan >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -atan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +atan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Atan >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atan >( a ); } //// @@ -2164,21 +1772,16 @@ __cuda_callable__ auto sinh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Sinh >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sinh >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -sinh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +sinh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Sinh >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sinh >( a ); } //// @@ -2190,21 +1793,16 @@ __cuda_callable__ auto cosh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Cosh >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cosh >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -cosh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +cosh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Cosh >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Cosh >( a ); } //// @@ -2216,125 +1814,169 @@ __cuda_callable__ auto tanh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Tanh >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tanh >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -tanh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +tanh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Tanh >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Tanh >( a ); } //// -// Log +// Asinh template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -log( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +asinh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Log >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asinh >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -log( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +asinh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Log >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Asinh >( a ); } //// -// Log10 +// Acosh template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -log10( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +acosh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Log10 >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acosh >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -log10( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +acosh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Log10 >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Acosh >( a ); } //// -// Log2 +// Atanh template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -log2( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +atanh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Log2 >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atanh >( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -log2( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +atanh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Log2 >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Atanh >( a ); } //// -// Exp +// Floor template< typename L1, typename L2, template< typename, typename > class LOperation > __cuda_callable__ auto -exp( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +floor( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Floor >( a ); +} + +template< typename L1, + template< typename > class LOperation > +__cuda_callable__ +auto +floor( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Floor >( a ); +} + +//// +// Ceil +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +__cuda_callable__ +auto +ceil( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Ceil >( a ); +} + +template< typename L1, + template< typename > class LOperation > +__cuda_callable__ +auto +ceil( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Ceil >( a ); +} + +//// +// Sign +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +__cuda_callable__ +auto +sign( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >, - Containers::Expressions::Exp >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sign >( a ); } template< typename L1, + template< typename > class LOperation > +__cuda_callable__ +auto +sign( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Containers::Expressions::Sign >( a ); +} + +//// +// Cast +template< typename ResultType, + typename L1, + typename L2, + template< typename, typename > class LOperation, + // workaround: templated type alias cannot be declared at block level + template class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > +__cuda_callable__ +auto +cast( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, CastOperation >( a ); +} + +template< typename ResultType, + typename L1, template< typename > class LOperation, - typename LParameter > + // workaround: templated type alias cannot be declared at block level + template class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > __cuda_callable__ auto -exp( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +cast( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< - Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >, - Containers::Expressions::Exp >( a ); + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, CastOperation >( a ); } //// @@ -2350,35 +1992,31 @@ min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOpe } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { return StaticExpressionMin( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Index > + template< typename, typename > class LOperation > __cuda_callable__ auto -argMin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, Index& arg ) +argMin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return StaticExpressionArgMin( a, arg ); + return StaticExpressionArgMin( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter, - typename Index > + template< typename > class LOperation > __cuda_callable__ auto -argMin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, Index& arg ) +argMin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return StaticExpressionArgMin( a, arg ); + return StaticExpressionArgMin( a ); } template< typename L1, @@ -2392,35 +2030,31 @@ max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOpe } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { return StaticExpressionMax( a ); } template< typename L1, typename L2, - template< typename, typename > class LOperation, - typename Index > + template< typename, typename > class LOperation > __cuda_callable__ auto -argMax( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, Index& arg ) +argMax( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) { - return StaticExpressionArgMax( a, arg ); + return StaticExpressionArgMax( a ); } template< typename L1, - template< typename > class LOperation, - typename LParameter, - typename Index > + template< typename > class LOperation > __cuda_callable__ auto -argMax( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, Index& arg ) +argMax( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { - return StaticExpressionArgMax( a, arg ); + return StaticExpressionArgMax( a ); } template< typename L1, @@ -2434,15 +2068,65 @@ sum( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOpe } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -sum( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +sum( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { return StaticExpressionSum( a ); } +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +maxNorm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return max( abs( a ) ); +} + +template< typename L1, + template< typename > class LOperation > +auto +maxNorm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return max( abs( a ) ); +} + +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +l1Norm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return StaticExpressionL1Norm( a ); +} + +template< typename L1, + template< typename > class LOperation > +auto +l1Norm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return StaticExpressionL1Norm( a ); +} + +template< typename L1, + typename L2, + template< typename, typename > class LOperation > +auto +l2Norm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) +{ + return TNL::sqrt( StaticExpressionL2Norm( a ) ); +} + +template< typename L1, + template< typename > class LOperation > +auto +l2Norm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) +{ + return TNL::sqrt( StaticExpressionL2Norm( a ) ); +} + template< typename L1, typename L2, template< typename, typename > class LOperation, @@ -2450,28 +2134,29 @@ template< typename L1, __cuda_callable__ auto lpNorm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p ) --> decltype(StaticExpressionLpNorm( a, p )) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { if( p == 1.0 ) - return StaticExpressionLpNorm( a, p ); + return l1Norm( a ); if( p == 2.0 ) - return TNL::sqrt( StaticExpressionLpNorm( a, p ) ); + return l2Norm( a ); return TNL::pow( StaticExpressionLpNorm( a, p ), 1.0 / p ); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename Real > __cuda_callable__ auto -lpNorm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, const Real& p ) --> decltype(StaticExpressionLpNorm( a, p )) +lpNorm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Real& p ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { if( p == 1.0 ) - return StaticExpressionLpNorm( a, p ); + return l1Norm( a ); if( p == 2.0 ) - return TNL::sqrt( StaticExpressionLpNorm( a, p ) ); + return l2Norm( a ); return TNL::pow( StaticExpressionLpNorm( a, p ), 1.0 / p ); } @@ -2486,11 +2171,10 @@ product( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -product( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +product( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { return StaticExpressionProduct( a ); } @@ -2506,11 +2190,10 @@ logicalOr( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2 } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -logicalOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +logicalOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { return StaticExpressionLogicalOr( a ); } @@ -2526,11 +2209,10 @@ binaryOr( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, } template< typename L1, - template< typename > class LOperation, - typename LParameter > + template< typename > class LOperation > __cuda_callable__ auto -binaryOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a ) +binaryOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) { return StaticExpressionBinaryOr( a ); } @@ -2546,7 +2228,7 @@ auto dot( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } template< typename L1, @@ -2555,38 +2237,36 @@ template< typename L1, template< typename > class ROperation > __cuda_callable__ auto -operator,( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b ) +dot( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, + const Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } template< typename L1, template< typename > class LOperation, - typename LParameter, typename R1, typename R2, template< typename, typename > class ROperation > __cuda_callable__ auto -dot( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation, LParameter >& a, +dot( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } template< typename L1, typename L2, template< typename, typename > class LOperation, typename R1, - template< typename > class ROperation, - typename RParameter > + template< typename > class ROperation > __cuda_callable__ auto dot( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) { - return TNL::sum( a * b ); + return (a, b); } //// @@ -2614,13 +2294,12 @@ Result evaluateAndReduce( Vector& lhs, template< typename Vector, typename T1, template< typename > class Operation, - typename Parameter, typename Reduction, typename VolatileReduction, typename Result > __cuda_callable__ Result evaluateAndReduce( Vector& lhs, - const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >& expression, + const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& expression, Reduction& reduction, VolatileReduction& volatileReduction, const Result& zero ) @@ -2659,13 +2338,12 @@ Result addAndReduce( Vector& lhs, template< typename Vector, typename T1, template< typename > class Operation, - typename Parameter, typename Reduction, typename VolatileReduction, typename Result > __cuda_callable__ Result addAndReduce( Vector& lhs, - const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >& expression, + const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& expression, Reduction& reduction, VolatileReduction& volatileReduction, const Result& zero ) @@ -2707,13 +2385,12 @@ Result addAndReduceAbs( Vector& lhs, template< typename Vector, typename T1, template< typename > class Operation, - typename Parameter, typename Reduction, typename VolatileReduction, typename Result > __cuda_callable__ Result addAndReduceAbs( Vector& lhs, - const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation, Parameter >& expression, + const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& expression, Reduction& reduction, VolatileReduction& volatileReduction, const Result& zero ) diff --git a/src/TNL/Containers/Expressions/StaticVerticalOperations.h b/src/TNL/Containers/Expressions/StaticVerticalOperations.h index 04705d923426ad2e67815f79d4cfb38b8aa8d910..7c8477f4d8068373ce99b0366192d15bc1ea6b03 100644 --- a/src/TNL/Containers/Expressions/StaticVerticalOperations.h +++ b/src/TNL/Containers/Expressions/StaticVerticalOperations.h @@ -2,7 +2,7 @@ StaticVerticalOperations.h - description ------------------- begin : Jul 3, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,8 +10,7 @@ #pragma once -#include -#include +#include //// // By vertical operations we mean those applied across vector elements or @@ -33,10 +32,10 @@ auto StaticExpressionMin( const Expression& expression ) template< typename Expression > __cuda_callable__ -auto StaticExpressionArgMin( const Expression& expression, int& arg ) +auto StaticExpressionArgMin( const Expression& expression ) { + int arg = 0; auto value = expression[ 0 ]; - arg = 0; for( int i = 1; i < expression.getSize(); i++ ) { if( expression[ i ] < value ) @@ -45,7 +44,7 @@ auto StaticExpressionArgMin( const Expression& expression, int& arg ) arg = i; } } - return value; + return std::make_pair( arg, value ); } template< typename Expression > @@ -60,10 +59,10 @@ auto StaticExpressionMax( const Expression& expression ) template< typename Expression > __cuda_callable__ -auto StaticExpressionArgMax( const Expression& expression, int& arg ) +auto StaticExpressionArgMax( const Expression& expression ) { + int arg = 0; auto value = expression[ 0 ]; - arg = 0; for( int i = 1; i < expression.getSize(); i++ ) { if( expression[ i ] > value ) @@ -72,7 +71,7 @@ auto StaticExpressionArgMax( const Expression& expression, int& arg ) arg = i; } } - return value; + return std::make_pair( arg, value ); } template< typename Expression > @@ -85,32 +84,36 @@ auto StaticExpressionSum( const Expression& expression ) return aux; } +template< typename Expression > +__cuda_callable__ +auto StaticExpressionL1Norm( const Expression& expression ) +{ + auto aux = TNL::abs( expression[ 0 ] ); + for( int i = 1; i < expression.getSize(); i++ ) + aux += TNL::abs( expression[ i ] ); + return aux; +} + +template< typename Expression > +__cuda_callable__ +auto StaticExpressionL2Norm( const Expression& expression ) +{ + auto aux = expression[ 0 ] * expression[ 0 ]; + for( int i = 1; i < expression.getSize(); i++ ) + aux += expression[ i ] * expression[ i ]; + return aux; +} + template< typename Expression, typename Real > __cuda_callable__ auto StaticExpressionLpNorm( const Expression& expression, const Real& p ) --> typename std::remove_reference< decltype( expression[ 0 ] ) >::type { - if( p == ( Real ) 1.0 ) - { - auto aux = TNL::abs( expression[ 0 ] ); - for( int i = 1; i < expression.getSize(); i++ ) - aux += TNL::abs( expression[ i ] ); - return aux; - } - if( p == ( Real ) 2.0 ) - { - auto aux = expression[ 0 ] * expression[ 0 ]; - for( int i = 1; i < expression.getSize(); i++ ) - aux += expression[ i ] * expression[ i ]; - return aux; - } auto aux = TNL::pow( TNL::abs( expression[ 0 ] ), p ); for( int i = 1; i < expression.getSize(); i++ ) aux += TNL::pow( TNL::abs( expression[ i ] ), p ); return aux; } - template< typename Expression > __cuda_callable__ auto StaticExpressionProduct( const Expression& expression ) diff --git a/src/TNL/Containers/Expressions/TypeTraits.h b/src/TNL/Containers/Expressions/TypeTraits.h index 951df0fdc62babfc1e3de77e9beadb525b28ce8b..606bb337aeb3438fdce861b54e949376652b8616 100644 --- a/src/TNL/Containers/Expressions/TypeTraits.h +++ b/src/TNL/Containers/Expressions/TypeTraits.h @@ -27,6 +27,6 @@ struct IsNumericExpression IsExpressionTemplate< T >::value > {}; -} //namespace Expressions -} //namespace Containers -} //namespace TNL +} // namespace Expressions +} // namespace Containers +} // namespace TNL diff --git a/src/TNL/Containers/Expressions/VerticalOperations.h b/src/TNL/Containers/Expressions/VerticalOperations.h index 032feacfa71672d51321555fcdb8646150d497e5..a1250578084b4f95d6c4de23884d9396fea397b0 100644 --- a/src/TNL/Containers/Expressions/VerticalOperations.h +++ b/src/TNL/Containers/Expressions/VerticalOperations.h @@ -2,7 +2,7 @@ VerticalOperations.h - description ------------------- begin : May 1, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,7 +10,9 @@ #pragma once -#include +#include +#include + #include //// @@ -24,24 +26,25 @@ namespace Expressions { //// // Vertical operations template< typename Expression > -auto ExpressionMin( const Expression& expression ) -> typename std::remove_reference< decltype( expression[ 0 ] ) >::type +auto ExpressionMin( const Expression& expression ) -> std::decay_t< decltype( expression[0] ) > { - using ResultType = typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type; + using ResultType = std::decay_t< decltype( expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a = a < b ? a : b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a = a < b ? a : b; }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, std::numeric_limits< ResultType >::max() ); } template< typename Expression > -auto ExpressionArgMin( const Expression& expression, typename Expression::IndexType& arg ) -> typename std::remove_reference< decltype( expression[ 0 ] ) >::type +auto ExpressionArgMin( const Expression& expression ) +-> std::pair< typename Expression::IndexType, std::decay_t< decltype( expression[0] ) > > { - using ResultType = typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type; + using ResultType = std::decay_t< decltype( expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; auto reduction = [=] __cuda_callable__ ( IndexType& aIdx, const IndexType& bIdx, ResultType& a, const ResultType& b ) { if( a > b ) { a = b; @@ -49,7 +52,6 @@ auto ExpressionArgMin( const Expression& expression, typename Expression::IndexT } else if( a == b && bIdx < aIdx ) aIdx = bIdx; - }; auto volatileReduction = [=] __cuda_callable__ ( volatile IndexType& aIdx, volatile IndexType& bIdx, volatile ResultType& a, volatile ResultType& b ) { if( a > b ) { @@ -58,30 +60,30 @@ auto ExpressionArgMin( const Expression& expression, typename Expression::IndexT } else if( a == b && bIdx < aIdx ) aIdx = bIdx; - }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduceWithArgument( expression.getSize(), arg, reduction, volatileReduction, fetch, std::numeric_limits< ResultType >::max() ); + return Algorithms::Reduction< typename Expression::DeviceType >::reduceWithArgument( expression.getSize(), reduction, volatileReduction, fetch, std::numeric_limits< ResultType >::max() ); } template< typename Expression > -auto ExpressionMax( const Expression& expression ) -> typename std::remove_reference< decltype( expression[ 0 ] ) >::type +auto ExpressionMax( const Expression& expression ) -> std::decay_t< decltype( expression[0] ) > { - using ResultType = typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type; + using ResultType = std::decay_t< decltype( expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a = a > b ? a : b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a = a > b ? a : b; }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, std::numeric_limits< ResultType >::lowest() ); } template< typename Expression > -auto ExpressionArgMax( const Expression& expression, typename Expression::IndexType& arg ) -> typename std::remove_reference< decltype( expression[ 0 ] ) >::type +auto ExpressionArgMax( const Expression& expression ) +-> std::pair< typename Expression::IndexType, std::decay_t< decltype( expression[0] ) > > { - using ResultType = typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type; + using ResultType = std::decay_t< decltype( expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; auto reduction = [=] __cuda_callable__ ( IndexType& aIdx, const IndexType& bIdx, ResultType& a, const ResultType& b ) { if( a < b ) { a = b; @@ -98,117 +100,115 @@ auto ExpressionArgMax( const Expression& expression, typename Expression::IndexT else if( a == b && bIdx < aIdx ) aIdx = bIdx; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduceWithArgument( expression.getSize(), arg, reduction, volatileReduction, fetch, std::numeric_limits< ResultType >::lowest() ); + return Algorithms::Reduction< typename Expression::DeviceType >::reduceWithArgument( expression.getSize(), reduction, volatileReduction, fetch, std::numeric_limits< ResultType >::lowest() ); +} + +template< typename Expression > +auto ExpressionSum( const Expression& expression ) -> std::decay_t< decltype( expression[0] + expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] + expression[0] ) >; + using IndexType = typename Expression::IndexType; + + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a += b; }; + auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a += b; }; + return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, (ResultType) 0 ); } template< typename Expression > -auto ExpressionSum( const Expression& expression ) -> - typename std::conditional< - std::is_same< typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type, bool >::value, - typename Expression::IndexType, - typename std::remove_reference< decltype( expression[ 0 ] ) >::type - >::type +auto ExpressionL1Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] + expression[0] ) > { - using ResultTypeBase = typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type; + using ResultType = std::decay_t< decltype( expression[0] + expression[0] ) >; using IndexType = typename Expression::IndexType; - using ResultType = typename std::conditional< std::is_same< ResultTypeBase, bool >::value, IndexType, ResultTypeBase >::type; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::abs( expression[ i ] ); }; auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a += b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a += b; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, ( ResultType ) 0.0 ); + return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, (ResultType) 0 ); +} + +template< typename Expression > +auto ExpressionL2Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) > +{ + using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >; + using IndexType = typename Expression::IndexType; + + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ] * expression[ i ]; }; + auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a += b; }; + auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a += b; }; + return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, (ResultType) 0 ); } template< typename Expression, typename Real > -auto ExpressionLpNorm( const Expression& expression, const Real& p ) -> - typename std::conditional< - std::is_same< typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type, bool >::value, - double, // TODO: Solve this some better way - typename std::remove_reference< decltype( expression[ 0 ] ) >::type - >::type +auto ExpressionLpNorm( const Expression& expression, const Real& p ) -> std::decay_t< decltype( TNL::pow( expression[0], p ) ) > { - using ResultTypeBase = typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type; + using ResultType = std::decay_t< decltype( TNL::pow( expression[0], p ) ) >; using IndexType = typename Expression::IndexType; - using ResultType = typename std::conditional< std::is_same< ResultTypeBase, bool >::value, double, ResultTypeBase >::type; - - if( p == ( Real ) 1.0 ) - { - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::abs( expression[ i ] ); }; - auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a += b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a += b; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, ( ResultType ) 0.0 ); - } - if( p == ( Real ) 2.0 ) - { - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ] * expression[ i ]; }; - auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a += b; }; - auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a += b; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, ( ResultType ) 0.0 ); - } - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::pow( TNL::abs( expression[ i ] ), p ); }; + + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::pow( TNL::abs( expression[ i ] ), p ); }; auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a += b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a += b; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, ( ResultType ) 0.0 ); + return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, (ResultType) 0 ); } template< typename Expression > -auto ExpressionProduct( const Expression& expression ) -> typename std::remove_reference< decltype( expression[ 0 ] ) >::type +auto ExpressionProduct( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) > { - using ResultType = typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type; + using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a *= b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a *= b; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, ( ResultType ) 1.0 ); + return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, (ResultType) 1 ); } template< typename Expression > -bool ExpressionLogicalAnd( const Expression& expression ) +auto ExpressionLogicalAnd( const Expression& expression ) -> std::decay_t< decltype( expression[0] && expression[0] ) > { - using ResultType = bool; + using ResultType = std::decay_t< decltype( expression[0] && expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a = a && b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a = a && b; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, true ); + return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, std::numeric_limits< ResultType >::max() ); } template< typename Expression > -bool ExpressionLogicalOr( const Expression& expression ) +auto ExpressionLogicalOr( const Expression& expression ) -> std::decay_t< decltype( expression[0] || expression[0] ) > { - using ResultType = bool; + using ResultType = std::decay_t< decltype( expression[0] || expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a = a || b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a = a || b; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, ( ResultType ) 0 ); + return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, (ResultType) 0 ); } template< typename Expression > -auto ExpressionBinaryAnd( const Expression& expression ) -> typename std::remove_reference< decltype( expression[ 0 ] ) >::type +auto ExpressionBinaryAnd( const Expression& expression ) -> std::decay_t< decltype( expression[0] & expression[0] ) > { - using ResultType = typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type; + using ResultType = std::decay_t< decltype( expression[0] & expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a = a & b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a = a & b; }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, std::numeric_limits< ResultType >::max() ); } template< typename Expression > -auto ExpressionBinaryOr( const Expression& expression ) -> typename std::remove_reference< decltype( expression[ 0 ] ) >::type +auto ExpressionBinaryOr( const Expression& expression ) -> std::decay_t< decltype( expression[0] | expression[0] ) > { - using ResultType = typename std::remove_cv< typename std::remove_reference< decltype( expression[ 0 ] ) >::type >::type; + using ResultType = std::decay_t< decltype( expression[0] | expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; auto reduction = [=] __cuda_callable__ ( ResultType& a, const ResultType& b ) { a = a | b; }; auto volatileReduction = [=] __cuda_callable__ ( volatile ResultType& a, volatile ResultType& b ) { a = a | b; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, ( ResultType ) 0 ); + return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, volatileReduction, fetch, (ResultType) 0 ); } } // namespace Expressions diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h index 822b7abb4d533ba10de88d3bb24111e3b8888086..76e61846afebe3e5dab4706556550e95db667db3 100644 --- a/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h +++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimap.h @@ -111,4 +111,4 @@ std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimap< Index } // namespace Containers } // namespace TNL -#include +#include diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimap.hpp similarity index 100% rename from src/TNL/Containers/Multimaps/EllpackIndexMultimap_impl.h rename to src/TNL/Containers/Multimaps/EllpackIndexMultimap.hpp diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h index be86f31fac38464ea6e1e0c60fc4f07646325917..fe7a0fb380230909be094042f69cf3ddabd24522 100644 --- a/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h +++ b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.h @@ -118,4 +118,4 @@ std::ostream& operator << ( std::ostream& str, const EllpackIndexMultimapValues< } // namespace Containers } // namespace TNL -#include +#include diff --git a/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h b/src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.hpp similarity index 100% rename from src/TNL/Containers/Multimaps/EllpackIndexMultimapValues_impl.h rename to src/TNL/Containers/Multimaps/EllpackIndexMultimapValues.hpp diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h index 1af67bd3b165b419065f06eb1673f0f9e69bf2a0..ba9994da9bb933fa7da825b550cca73bdc2e7498 100644 --- a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h +++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.h @@ -108,4 +108,4 @@ std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimap< } // namespace Containers } // namespace TNL -#include +#include diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.hpp similarity index 100% rename from src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap_impl.h rename to src/TNL/Containers/Multimaps/StaticEllpackIndexMultimap.hpp diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h index 1b88f0816b3af6ec31727f334b2926ff43e0ce0f..95ffade9fcad3674a7092bc69701e2a2500ab819 100644 --- a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h +++ b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.h @@ -105,4 +105,4 @@ std::ostream& operator << ( std::ostream& str, const StaticEllpackIndexMultimapV } // namespace Containers } // namespace TNL -#include +#include diff --git a/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h b/src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.hpp similarity index 100% rename from src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues_impl.h rename to src/TNL/Containers/Multimaps/StaticEllpackIndexMultimapValues.hpp diff --git a/src/TNL/Containers/StaticVectorExpressions.h b/src/TNL/Containers/StaticVectorExpressions.h index 77bba0c27a392157d1a6d3ca88369f420d79e04f..245a34f36a667fea184ee011583c554e4b15f79d 100644 --- a/src/TNL/Containers/StaticVectorExpressions.h +++ b/src/TNL/Containers/StaticVectorExpressions.h @@ -11,9 +11,6 @@ #pragma once #include -#include -#include -#include #include "StaticVector.h" @@ -427,7 +424,7 @@ __cuda_callable__ auto pow( const Containers::StaticVector< Size, Real >& a, const ExpType& exp ) { - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Pow, ExpType >( a, exp ); + return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ExpType, Containers::Expressions::Pow >( a, exp ); } //// @@ -640,6 +637,18 @@ sign( const Containers::StaticVector< Size, Real >& a ) return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sign >( a ); } +//// +// Cast +template< typename ResultType, int Size, typename Real, + // workaround: templated type alias cannot be declared at block level + template class Operation = Containers::Expressions::Cast< ResultType >::template Operation > +auto +__cuda_callable__ +cast( const Containers::StaticVector< Size, Real >& a ) +{ + return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t, Operation >( a ); +} + //// // Vertical operations - min template< int Size, typename Real > @@ -652,10 +661,10 @@ min( const Containers::StaticVector< Size, Real >& a ) template< int Size, typename Real > __cuda_callable__ -auto -argMin( const Containers::StaticVector< Size, Real >& a, int& arg ) +std::pair< int, Real > +argMin( const Containers::StaticVector< Size, Real >& a ) { - return Containers::Expressions::StaticExpressionArgMin( a, arg ); + return Containers::Expressions::StaticExpressionArgMin( a ); } template< int Size, typename Real > @@ -668,10 +677,10 @@ max( const Containers::StaticVector< Size, Real >& a ) template< int Size, typename Real > __cuda_callable__ -auto -argMax( const Containers::StaticVector< Size, Real >& a, int& arg ) +std::pair< int, Real > +argMax( const Containers::StaticVector< Size, Real >& a ) { - return Containers::Expressions::StaticExpressionArgMax( a, arg ); + return Containers::Expressions::StaticExpressionArgMax( a ); } template< int Size, typename Real > @@ -682,16 +691,41 @@ sum( const Containers::StaticVector< Size, Real >& a ) return Containers::Expressions::StaticExpressionSum( a ); } +template< int Size, typename Real > +__cuda_callable__ +auto +maxNorm( const Containers::StaticVector< Size, Real >& a ) +{ + return max( abs( a ) ); +} + +template< int Size, typename Real > +__cuda_callable__ +auto +l1Norm( const Containers::StaticVector< Size, Real >& a ) +{ + return Containers::Expressions::StaticExpressionL1Norm( a ); +} + +template< int Size, typename Real > +__cuda_callable__ +auto +l2Norm( const Containers::StaticVector< Size, Real >& a ) +{ + return TNL::sqrt( Containers::Expressions::StaticExpressionL2Norm( a ) ); +} + template< int Size, typename Real, typename Real2 > __cuda_callable__ auto lpNorm( const Containers::StaticVector< Size, Real >& a, const Real2& p ) --> decltype( Containers::Expressions::StaticExpressionLpNorm( a, p ) ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { if( p == 1.0 ) - return Containers::Expressions::StaticExpressionLpNorm( a, p ); + return l1Norm( a ); if( p == 2.0 ) - return TNL::sqrt( Containers::Expressions::StaticExpressionLpNorm( a, p ) ); + return l2Norm( a ); return TNL::pow( Containers::Expressions::StaticExpressionLpNorm( a, p ), 1.0 / p ); } diff --git a/src/TNL/Containers/UnorderedIndexedSet.h b/src/TNL/Containers/UnorderedIndexedSet.h index 38a1e53937fabb7ca3de9e7e4c9f31a41b5adbe3..042a555bc1b7f54b88961dd1da4dbade48694aa2 100644 --- a/src/TNL/Containers/UnorderedIndexedSet.h +++ b/src/TNL/Containers/UnorderedIndexedSet.h @@ -59,4 +59,4 @@ std::ostream& operator <<( std::ostream& str, UnorderedIndexedSet< Element, Inde } // namespace Containers } // namespace TNL -#include +#include diff --git a/src/TNL/Containers/UnorderedIndexedSet_impl.h b/src/TNL/Containers/UnorderedIndexedSet.hpp similarity index 100% rename from src/TNL/Containers/UnorderedIndexedSet_impl.h rename to src/TNL/Containers/UnorderedIndexedSet.hpp diff --git a/src/TNL/Containers/Vector.h b/src/TNL/Containers/Vector.h index 30f0afbc2518d0aebebb4e5a72bb7e2ef661ec46..1fb6a01aa135aee79969a87696a1be1a2e79e55f 100644 --- a/src/TNL/Containers/Vector.h +++ b/src/TNL/Containers/Vector.h @@ -22,7 +22,7 @@ namespace Containers { * 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 + * \tparam Real An arithmetic 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. @@ -51,27 +51,27 @@ public: using ViewType = VectorView< Real, Device, Index >; using ConstViewType = VectorView< std::add_const_t< Real >, Device, Index >; - //! \brief Default constructor. + // constructors and assignment operators inherited from the class Array + using Array< Real, Device, Index, Allocator >::Array; + using Array< Real, Device, Index, Allocator >::operator=; + + //! \brief Constructs an empty array with zero size. Vector() = default; - //! \brief Default copy constructor. + //! \brief Copy constructor (makes a deep copy). explicit Vector( const Vector& ) = default; - //! \brief Copy constructor with a specific allocator. + //! \brief Copy constructor with a specific allocator (makes a deep copy). explicit Vector( const Vector& vector, const AllocatorType& allocator ); //! \brief Default move constructor. Vector( Vector&& ) = default; - //! \brief Default copy-assignment operator. + //! \brief Copy-assignment operator for copying data from another vector. Vector& operator=( const Vector& ) = default; - //! \brief Default move-assignment operator. + //! \brief Move-assignment operator for acquiring data from \e rvalues. Vector& operator=( Vector&& ) = default; - //! Constructors and assignment operators are inherited from the class \ref Array. - 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. */ + //! \brief Returns a \ref String representation of the vector type in C++ style. static String getType(); - /** \brief Returns type of vector Real value, Device type and the type of Index. */ + //! \brief Returns a \ref String representation of the vector type in C++ style. virtual String getTypeVirtual() const; /** @@ -88,20 +88,6 @@ public: */ ViewType getView( IndexType begin = 0, IndexType end = 0 ); - /** - * \brief Returns a non-modifiable view of the vector. - * - * 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. - * \param end The end of the vector sub-interval. The default value is 0 - * which is, however, replaced with the array size. - */ - ConstViewType getView( IndexType begin = 0, IndexType end = 0 ) const; - /** * \brief Returns a non-modifiable view of the vector. * @@ -127,26 +113,16 @@ public: operator ConstViewType() const; /** - * \brief Adds another element to this vector. + * \brief Assigns a vector expression to this vector. * - * New element has index type \e i and reference to its real type \e value. - */ - void addElement( const IndexType i, - const RealType& value ); - - /** - * \brief Adds another element with multiplicator to this vector. + * The assignment is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector. If it evaluates to a vector + * with a different size than this vector, this vector is reallocated to + * match the size of the vector expression. * - * New element has index type \e i and reference to its real type \e value - * multiplied by \e thisElementMultiplicator. - */ - template< typename Scalar > - void addElement( const IndexType i, - const RealType& value, - const Scalar thisElementMultiplicator ); - - /** - * \brief Assigns a vector expression to this vector. + * \param expression The vector expression to be evaluated and assigned to + * this vector. + * \return Reference to this vector. */ template< typename VectorExpression, typename..., @@ -155,6 +131,8 @@ public: /** * \brief Assigns a value or an array - same as \ref Array::operator=. + * + * \return Reference to this vector. */ // operator= from the base class should be hidden according to the C++14 standard, // although GCC does not do that - see https://stackoverflow.com/q/57322624 @@ -168,85 +146,65 @@ public: } /** - * \brief This function subtracts \e vector from this vector and returns the resulting vector. + * \brief Adds elements of this vector and a vector expression and + * stores the result in this vector. * - * The subtraction is applied to all the vector elements separately. - * \param vector Reference to another vector. - */ - template< typename VectorExpression > - Vector& operator-=( const VectorExpression& expression ); - - /** - * \brief This function adds \e vector to this vector and returns the resulting vector. + * The addition is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector of the same size as this vector. * - * The addition is applied to all the vector elements separately. - * \param vector Reference to another vector. + * \param expression Reference to a vector expression. + * \return Reference to this vector. */ template< typename VectorExpression > Vector& operator+=( const VectorExpression& expression ); /** - * \brief This function multiplies this vector by \e c and returns the resulting vector. + * \brief Subtracts elements of this vector and a vector expression and + * stores the result in this vector. * - * The multiplication is applied to all the vector elements separately. - * \param c Multiplicator. + * The subtraction is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector of the same size as this vector. + * + * \param expression Reference to a vector expression. + * \return Reference to this vector. */ template< typename VectorExpression > - Vector& operator*=( const VectorExpression& expression ); + Vector& operator-=( const VectorExpression& expression ); /** - * \brief This function divides this vector by \e c and returns the resulting vector. + * \brief Multiplies elements of this vector and a vector expression and + * stores the result in this vector. * - * The division is applied to all the vector elements separately. - * \param c Divisor. + * The multiplication is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector of the same size as this vector. + * + * \param expression Reference to a vector expression. + * \return Reference to this vector. */ template< typename VectorExpression > - Vector& operator/=( const VectorExpression& expression ); - - /** - * \brief Returns sum of all vector elements. - */ - template< typename ResultType = RealType > - ResultType sum() const; + Vector& operator*=( const VectorExpression& expression ); /** - * \brief Computes scalar (dot) product. + * \brief Divides elements of this vector and a vector expression and + * stores the result in this vector. * - * An algebraic operation that takes two equal-length vectors and returns a single number. + * The division is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector of the same size as this vector. * - * \tparam vector Type of vector. - * \param v Reference to another vector of the same size as this vector. - */ - template< typename Vector > - Real scalarProduct( const Vector& v ) const; - - /** - * \brief Returns the result of following: thisMultiplicator * this + multiplicator * v. + * \param expression Reference to a vector expression. + * \return Reference to this vector. */ - template< typename Vector, typename Scalar1 = Real, typename Scalar2 = Real > - [[deprecated("addVector is deprecated - use expression templates instead.")]] - void addVector( const Vector& v, - const Scalar1 multiplicator = 1.0, - const Scalar2 thisMultiplicator = 1.0 ); - - /** - * \brief Returns the result of following: thisMultiplicator * this + multiplicator1 * v1 + multiplicator2 * v2. - */ - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2, typename Scalar3 = Real > - [[deprecated("addVectors is deprecated - use expression templates instead.")]] - void addVectors( const Vector1& v1, - const Scalar1 multiplicator1, - const Vector2& v2, - const Scalar2 multiplicator2, - const Scalar3 thisMultiplicator = 1.0 ); + template< typename VectorExpression > + Vector& operator/=( const VectorExpression& expression ); /** * \brief Returns specific sums of elements of this vector. * + * FIXME: computePrefixSum does not exist + * * Does the same as \ref computePrefixSum, but computes only sums for elements * with the index in range from \e begin to \e end. The other elements of this - * vector remain untouched - with the same value. Therefore this method returns - * a new vector with the length of this vector. + * vector remain untouched - with the same value. * * \param begin Index of the element in this vector which to begin with. * \param end Index of the element in this vector which to end with. diff --git a/src/TNL/Containers/Vector.hpp b/src/TNL/Containers/Vector.hpp index 487933ea4310be9e163c5be88f8056206d3fece1..7338c8317e4a5b29297240ff40d9de8ae73ff194 100644 --- a/src/TNL/Containers/Vector.hpp +++ b/src/TNL/Containers/Vector.hpp @@ -65,19 +65,6 @@ getView( IndexType begin, IndexType end ) return ViewType( this->getData() + begin, end - begin ); } -template< typename Real, - typename Device, - 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 ) - end = this->getSize(); - return ConstViewType( &this->getData()[ begin ], end - begin ); -} - template< typename Real, typename Device, typename Index, @@ -111,32 +98,6 @@ operator ConstViewType() const return getConstView(); } -template< typename Real, - typename Device, - typename Index, - typename Allocator > -void -Vector< Real, Device, Index, Allocator >:: -addElement( const IndexType i, - const RealType& value ) -{ - Algorithms::VectorOperations< Device >::addElement( *this, i, value ); -} - -template< typename Real, - typename Device, - typename Index, - typename Allocator > - template< typename Scalar > -void -Vector< Real, Device, Index, Allocator >:: -addElement( const IndexType i, - const RealType& value, - const Scalar thisElementMultiplicator ) -{ - Algorithms::VectorOperations< Device >::addElement( *this, i, value, thisElementMultiplicator ); -} - template< typename Real, typename Device, typename Index, @@ -158,9 +119,9 @@ template< typename Real, template< typename VectorExpression > Vector< Real, Device, Index, Allocator >& Vector< Real, Device, Index, Allocator >:: -operator-=( const VectorExpression& expression ) +operator+=( const VectorExpression& expression ) { - Algorithms::VectorAssignmentWithOperation< Vector, VectorExpression >::subtraction( *this, expression ); + Algorithms::VectorAssignmentWithOperation< Vector, VectorExpression >::addition( *this, expression ); return *this; } @@ -171,9 +132,9 @@ template< typename Real, template< typename VectorExpression > Vector< Real, Device, Index, Allocator >& Vector< Real, Device, Index, Allocator >:: -operator+=( const VectorExpression& expression ) +operator-=( const VectorExpression& expression ) { - Algorithms::VectorAssignmentWithOperation< Vector, VectorExpression >::addition( *this, expression ); + Algorithms::VectorAssignmentWithOperation< Vector, VectorExpression >::subtraction( *this, expression ); return *this; } @@ -203,56 +164,6 @@ operator/=( const VectorExpression& expression ) return *this; } -template< typename Real, - typename Device, - typename Index, - typename Allocator > - template< typename ResultType > -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 Allocator > - template< typename VectorT > -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 Allocator > - template< typename VectorT, typename Scalar1, typename Scalar2 > -void -Vector< Real, Device, Index, Allocator >:: -addVector( const VectorT& x, - const Scalar1 multiplicator, - const Scalar2 thisMultiplicator ) -{ - Algorithms::VectorOperations< Device >::addVector( *this, x, multiplicator, thisMultiplicator ); -} - -template< typename Real, - typename Device, - typename Index, - typename Allocator > - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2, typename Scalar3 > -void -Vector< Real, Device, Index, Allocator >:: -addVectors( const Vector1& v1, - const Scalar1 multiplicator1, - const Vector2& v2, - const Scalar2 multiplicator2, - const Scalar3 thisMultiplicator ) -{ - Algorithms::VectorOperations< Device >::addVectors( *this, v1, multiplicator1, v2, multiplicator2, thisMultiplicator ); -} - template< typename Real, typename Device, typename Index, diff --git a/src/TNL/Containers/VectorExpressions.h b/src/TNL/Containers/VectorExpressions.h index b4d1017062105bc9d364c75da89e9b19606e67f2..07961c42846e6423ed30b65641232d6538ceba33 100644 --- a/src/TNL/Containers/VectorExpressions.h +++ b/src/TNL/Containers/VectorExpressions.h @@ -2,7 +2,7 @@ VectorExpressions.h - description ------------------- begin : Jun 27, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,11 +10,7 @@ #pragma once -#include #include -#include -#include -#include #include "Vector.h" @@ -233,42 +229,27 @@ template< typename Real1, typename Real2, typename Device1, typename Device2, ty 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 >:: - compare( a.getData(), - b.getData(), - a.getSize() ); + using ConstView1 = typename Vector< Real1, Device1, Index, Allocator >::ConstViewType; + using ConstView2 = typename Vector< Real2, Device2, Index, Allocator >::ConstViewType; + return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a.getConstView(), b.getConstView() ); } template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator > bool operator==( const VectorView< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index, Allocator >& b ) { - if( a.getSize() != b.getSize() ) - return false; - if( a.getSize() == 0 ) - return true; - return Algorithms::ArrayOperations< Device1, Device2 >:: - compare( a.getData(), - b.getData(), - a.getSize() ); + using ConstView1 = VectorView< Real1, Device1, Index >; + using ConstView2 = typename Vector< Real2, Device2, Index, Allocator >::ConstViewType; + return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a, b.getConstView() ); } template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator > bool operator==( const Vector< Real1, Device1, Index, Allocator >& a, const VectorView< Real2, Device2, Index >& b ) { - if( a.getSize() != b.getSize() ) - return false; - if( a.getSize() == 0 ) - return true; - return Algorithms::ArrayOperations< Device1, Device2 >:: - compare( a.getData(), - b.getData(), - a.getSize() ); + using ConstView1 = typename Vector< Real1, Device1, Index, Allocator >::ConstViewType; + using ConstView2 = VectorView< Real2, Device2, Index >; + return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a.getConstView(), b ); } //// @@ -705,7 +686,7 @@ auto pow( const Containers::Vector< Real, Device, Index, Allocator >& a, const ExpType& exp ) { using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Pow, ExpType >( a.getConstView(), exp ); + return Containers::Expressions::BinaryExpressionTemplate< ConstView, ExpType, Containers::Expressions::Pow >( a.getConstView(), exp ); } //// @@ -918,6 +899,17 @@ sign( const Containers::Vector< Real, Device, Index, Allocator >& a ) return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sign >( a.getConstView() ); } +//// +// Cast +template< typename ResultType, typename Real, typename Device, typename Index, typename Allocator, + // workaround: templated type alias cannot be declared at block level + template class Operation = Containers::Expressions::Cast< ResultType >::template Operation > +auto +cast( const Containers::Vector< Real, Device, Index, Allocator >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< decltype(a.getConstView()), Operation >( a.getConstView() ); +} + //// // Vertical operations - min template< typename Real, @@ -932,10 +924,10 @@ min( const Containers::Vector< Real, Device, Index, Allocator >& a ) template< typename Real, typename Device, typename Index, typename Allocator > -Real -argMin( const Containers::Vector< Real, Device, Index, Allocator >& a, Index& arg ) +std::pair< Index, std::decay_t< Real > > +argMin( const Containers::Vector< Real, Device, Index, Allocator >& a ) { - return Containers::Expressions::ExpressionArgMin( a.getConstView(), arg ); + return Containers::Expressions::ExpressionArgMin( a.getConstView() ); } template< typename Real, @@ -950,10 +942,10 @@ max( const Containers::Vector< Real, Device, Index, Allocator >& a ) template< typename Real, typename Device, typename Index, typename Allocator > -Real -argMax( const Containers::Vector< Real, Device, Index, Allocator >& a, Index& arg ) +std::pair< Index, std::decay_t< Real > > +argMax( const Containers::Vector< Real, Device, Index, Allocator >& a ) { - return Containers::Expressions::ExpressionArgMax( a.getConstView(), arg ); + return Containers::Expressions::ExpressionArgMax( a.getConstView() ); } template< typename Real, @@ -965,19 +957,47 @@ sum( const Containers::Vector< Real, Device, Index, Allocator >& a ) return Containers::Expressions::ExpressionSum( a.getConstView() ); } +template< typename Real, + typename Device, + typename Index, typename Allocator > +auto +maxNorm( const Containers::Vector< Real, Device, Index, Allocator >& a ) +{ + return max( abs( a ) ); +} + +template< typename Real, + typename Device, + typename Index, typename Allocator > +auto +l1Norm( const Containers::Vector< Real, Device, Index, Allocator >& a ) +{ + return Containers::Expressions::ExpressionL1Norm( a.getConstView() ); +} + +template< typename Real, + typename Device, + typename Index, typename Allocator > +auto +l2Norm( const Containers::Vector< Real, Device, Index, Allocator >& a ) +{ + return TNL::sqrt( Containers::Expressions::ExpressionL2Norm( a.getConstView() ) ); +} + template< typename Real, typename Device, typename Index, typename Allocator, typename Real2 > auto lpNorm( const Containers::Vector< Real, Device, Index, Allocator >& a, const Real2& p ) --> decltype( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ) ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { if( p == 1.0 ) - return Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ); + return l1Norm( a ); if( p == 2.0 ) - return TNL::sqrt( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ) ); - return TNL::pow( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ), (Real2) (1.0 / p) ); + return l2Norm( a ); + return TNL::pow( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ), 1.0 / p ); } template< typename Real, diff --git a/src/TNL/Containers/VectorView.h b/src/TNL/Containers/VectorView.h index efb1ce509dec779cdd367b9a1f91d9131580f7cb..1662afb7c815892faf2b336d065a2fdf861dfb70 100644 --- a/src/TNL/Containers/VectorView.h +++ b/src/TNL/Containers/VectorView.h @@ -19,6 +19,17 @@ namespace TNL { namespace Containers { +/** + * \brief \e VectorView extends \ref ArrayView with algebraic operations. + * + * The template parameters have the same meaning as in \ref ArrayView, with + * \e Real corresponding to \e ArrayView's \e Value parameter. + * + * \tparam Real An arithmetic 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. + */ template< typename Real = double, typename Device = Devices::Host, typename Index = int > @@ -36,22 +47,27 @@ public: using ViewType = VectorView< Real, Device, Index >; using ConstViewType = VectorView< std::add_const_t< Real >, Device, Index >; - //! Constructors and assignment operators are inherited from the class \ref Array. + // constructors and assignment operators inherited from the class ArrayView using ArrayView< Real, Device, Index >::ArrayView; using ArrayView< Real, Device, Index >::operator=; // In C++14, default constructors cannot be inherited, although Clang // and GCC since version 7.0 inherit them. // https://stackoverflow.com/a/51854172 + //! \brief Constructs an empty array view with zero size. __cuda_callable__ VectorView() = default; + //! \brief Constructor for the initialization by a base class object. // initialization by base class is not a copy constructor so it has to be explicit template< typename Real_ > // template catches both const and non-const qualified Element __cuda_callable__ VectorView( const ArrayView< Real_, Device, Index >& view ) : BaseType( view ) {} + //! \brief Returns a \ref String representation of the vector view type. + static String getType(); + /** * \brief Returns a modifiable view of the vector view. * @@ -80,33 +96,19 @@ public: * which is, however, replaced with the array size. */ __cuda_callable__ - ConstViewType getView( IndexType begin = 0, IndexType end = 0 ) const; + ConstViewType getConstView( IndexType begin = 0, IndexType end = 0 ) const; /** - * \brief Returns a non-modifiable view of the vector view. + * \brief Assigns a vector expression to this vector view. * - * 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. + * The assignment is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector of the same size as this vector + * view. * - * \param begin The beginning of the vector view sub-interval. It is 0 by - * default. - * \param end The end of the vector view sub-interval. The default value is 0 - * which is, however, replaced with the array size. + * \param expression The vector expression to be evaluated and assigned to + * this vector view. + * \return Reference to this vector view. */ - __cuda_callable__ - ConstViewType getConstView( IndexType begin = 0, IndexType end = 0 ) const; - - static String getType(); - - // All other Vector methods follow... - void addElement( IndexType i, RealType value ); - - template< typename Scalar > - void addElement( IndexType i, - RealType value, - Scalar thisElementMultiplicator ); - template< typename VectorExpression, typename..., typename = std::enable_if_t< Expressions::IsExpressionTemplate< VectorExpression >::value > > @@ -114,6 +116,8 @@ public: /** * \brief Assigns a value or an array - same as \ref ArrayView::operator=. + * + * \return Reference to this vector view. */ // operator= from the base class should be hidden according to the C++14 standard, // although GCC does not do that - see https://stackoverflow.com/q/57322624 @@ -126,41 +130,74 @@ public: return ArrayView< Real, Device, Index >::operator=(data); } + /** + * \brief Adds elements of this vector view and a vector expression and + * stores the result in this vector view. + * + * The addition is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector of the same size as this vector + * view. + * + * \param expression Reference to a vector expression. + * \return Reference to this vector view. + */ template< typename VectorExpression > - VectorView& operator-=( const VectorExpression& expression ); + VectorView& operator+=( const VectorExpression& expression ); + /** + * \brief Subtracts elements of this vector view and a vector expression and + * stores the result in this vector view. + * + * The subtraction is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector of the same size as this vector + * view. + * + * \param expression Reference to a vector expression. + * \return Reference to this vector view. + */ template< typename VectorExpression > - VectorView& operator+=( const VectorExpression& expression ); + VectorView& operator-=( const VectorExpression& expression ); + /** + * \brief Multiplies elements of this vector view and a vector expression and + * stores the result in this vector view. + * + * The multiplication is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector of the same size as this vector + * view. + * + * \param expression Reference to a vector expression. + * \return Reference to this vector view. + */ template< typename VectorExpression > VectorView& operator*=( const VectorExpression& expression ); + /** + * \brief Divides elements of this vector view and a vector expression and + * stores the result in this vector view. + * + * The division is evaluated element-wise. The vector expression must + * either evaluate to a scalar or a vector of the same size as this vector + * view. + * + * \param expression Reference to a vector expression. + * \return Reference to this vector view. + */ template< typename VectorExpression > VectorView& operator/=( const VectorExpression& expression ); - template< typename ResultType = NonConstReal > - ResultType sum() const; - - //! Computes scalar dot product - template< typename Vector > - NonConstReal scalarProduct( const Vector& v ) const; - - //! Computes this = thisMultiplicator * this + alpha * x. - template< typename Vector, typename Scalar1 = Real, typename Scalar2 = Real > - [[deprecated("addVector is deprecated - use expression templates instead.")]] - void addVector( const Vector& x, - Scalar1 alpha = 1.0, - Scalar2 thisMultiplicator = 1.0 ); - - //! Computes this = thisMultiplicator * this + multiplicator1 * v1 + multiplicator2 * v2. - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2, typename Scalar3 = Real > - [[deprecated("addVectors is deprecated - use expression templates instead.")]] - void addVectors( const Vector1& v1, - Scalar1 multiplicator1, - const Vector2& v2, - Scalar2 multiplicator2, - Scalar3 thisMultiplicator = 1.0 ); - + /** + * \brief Returns specific sums of elements of this vector view. + * + * FIXME: computePrefixSum does not exist + * + * Does the same as \ref computePrefixSum, but computes only sums for elements + * with the index in range from \e begin to \e end. The other elements of this + * vector remain untouched - with the same value. + * + * \param begin Index of the element in this vector view which to begin with. + * \param end Index of the element in this vector view which to end with. + */ template< Algorithms::PrefixSumType Type = Algorithms::PrefixSumType::Inclusive > void prefixSum( IndexType begin = 0, IndexType end = 0 ); @@ -181,5 +218,5 @@ public: } // namespace Containers } // namespace TNL -#include #include +#include diff --git a/src/TNL/Containers/VectorView.hpp b/src/TNL/Containers/VectorView.hpp index b4dc6968ddd69f3725fa04c4bd949c04edda517e..986d2bc0fbde88de1d57670f64a6b6e08a176f10 100644 --- a/src/TNL/Containers/VectorView.hpp +++ b/src/TNL/Containers/VectorView.hpp @@ -22,32 +22,33 @@ namespace Containers { template< typename Real, typename Device, typename Index > -__cuda_callable__ -typename VectorView< Real, Device, Index >::ViewType +String VectorView< Real, Device, Index >:: -getView( IndexType begin, IndexType end ) +getType() { - if( end == 0 ) - end = this->getSize(); - return ViewType( this->getData() + begin, end - begin );; + return String( "Containers::VectorView< " ) + + TNL::getType< Real >() + ", " + + Device::getDeviceType() + ", " + + TNL::getType< Index >() + " >"; } template< typename Real, typename Device, typename Index > __cuda_callable__ -typename VectorView< Real, Device, Index >::ConstViewType +typename VectorView< Real, Device, Index >::ViewType VectorView< Real, Device, Index >:: -getView( IndexType begin, IndexType end ) const +getView( IndexType begin, IndexType end ) { if( end == 0 ) end = this->getSize(); - return ConstViewType( &this->getData()[ begin ], end - begin );; + return ViewType( this->getData() + begin, end - begin );; } template< typename Real, typename Device, typename Index > +__cuda_callable__ typename VectorView< Real, Device, Index >::ConstViewType VectorView< Real, Device, Index >:: getConstView( const IndexType begin, IndexType end ) const @@ -57,40 +58,6 @@ getConstView( const IndexType begin, IndexType end ) const return ConstViewType( this->getData() + begin, end - begin );; } -template< typename Real, - typename Device, - typename Index > -String -VectorView< Real, Device, Index >:: -getType() -{ - return String( "Containers::VectorView< " ) + - TNL::getType< Real >() + ", " + - Device::getDeviceType() + ", " + - TNL::getType< Index >() + " >"; -} - -template< typename Real, - typename Device, - typename Index > -void -VectorView< Real, Device, Index >:: -addElement( IndexType i, RealType value ) -{ - Algorithms::VectorOperations< Device >::addElement( *this, i, value ); -} - -template< typename Real, - typename Device, - typename Index > - template< typename Scalar > -void -VectorView< Real, Device, Index >:: -addElement( IndexType i, RealType value, Scalar thisElementMultiplicator ) -{ - Algorithms::VectorOperations< Device >::addElement( *this, i, value, thisElementMultiplicator ); -} - template< typename Real, typename Device, typename Index > @@ -108,9 +75,9 @@ template< typename Real, template< typename VectorExpression > VectorView< Real, Device, Index >& VectorView< Real, Device, Index >:: -operator-=( const VectorExpression& expression ) +operator+=( const VectorExpression& expression ) { - Algorithms::VectorAssignmentWithOperation< VectorView, VectorExpression >::subtraction( *this, expression ); + Algorithms::VectorAssignmentWithOperation< VectorView, VectorExpression >::addition( *this, expression ); return *this; } @@ -120,9 +87,9 @@ template< typename Real, template< typename VectorExpression > VectorView< Real, Device, Index >& VectorView< Real, Device, Index >:: -operator+=( const VectorExpression& expression ) +operator-=( const VectorExpression& expression ) { - Algorithms::VectorAssignmentWithOperation< VectorView, VectorExpression >::addition( *this, expression ); + Algorithms::VectorAssignmentWithOperation< VectorView, VectorExpression >::subtraction( *this, expression ); return *this; } @@ -150,54 +117,6 @@ operator/=( const VectorExpression& expression ) return *this; } -template< typename Real, - typename Device, - typename Index > - template< typename ResultType > -ResultType -VectorView< Real, Device, Index >:: -sum() const -{ - return Algorithms::VectorOperations< Device >::template getVectorSum< VectorView, ResultType >( *this ); -} - -template< typename Real, - typename Device, - typename Index > - template< typename Vector > -typename VectorView< Real, Device, Index >::NonConstReal -VectorView< Real, Device, Index >:: -scalarProduct( const Vector& v ) const -{ - return TNL::sum( *this * v ); -} - -template< typename Real, - typename Device, - typename Index > - template< typename Vector, typename Scalar1, typename Scalar2 > -void -VectorView< Real, Device, Index >:: -addVector( const Vector& x, Scalar1 alpha, Scalar2 thisMultiplicator ) -{ - Algorithms::VectorOperations< Device >::addVector( *this, x, alpha, thisMultiplicator ); -} - -template< typename Real, - typename Device, - typename Index > - template< typename Vector1, typename Vector2, typename Scalar1, typename Scalar2, typename Scalar3 > -void -VectorView< Real, Device, Index >:: -addVectors( const Vector1& v1, - Scalar1 multiplicator1, - const Vector2& v2, - Scalar2 multiplicator2, - Scalar3 thisMultiplicator ) -{ - Algorithms::VectorOperations< Device >::addVectors( *this, v1, multiplicator1, v2, multiplicator2, thisMultiplicator ); -} - template< typename Real, typename Device, typename Index > diff --git a/src/TNL/Containers/VectorViewExpressions.h b/src/TNL/Containers/VectorViewExpressions.h index 416bd23efeb0e6aac806c5fc56459e9e8ff96c04..efc8d860957d7d73e9384fab97aa62fd4a09c470 100644 --- a/src/TNL/Containers/VectorViewExpressions.h +++ b/src/TNL/Containers/VectorViewExpressions.h @@ -2,7 +2,7 @@ VectorViewExpressions.h - description ------------------- begin : Apr 27, 2019 - copyright : (C) 2019 by Tomas Oberhuber + copyright : (C) 2019 by Tomas Oberhuber et al. email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ @@ -10,11 +10,7 @@ #pragma once -#include #include -#include -#include -#include #include "VectorView.h" @@ -143,14 +139,7 @@ template< typename Real1, typename Real2, typename Device1, typename Device2, ty 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 Algorithms::ArrayOperations< Device1, Device2 >:: - compare( a.getData(), - b.getData(), - a.getSize() ); + return Expressions::Comparison< VectorView< Real1, Device1, Index >, VectorView< Real2, Device2, Index > >::EQ( a, b ); } //// @@ -367,6 +356,32 @@ max( const Containers::VectorView< Real1, Device, Index >& a, const Containers:: return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Max >( a, b ); } +//// +// Dot product - the same as scalar product, just for convenience +template< typename Real, typename Device, typename Index, typename ET, + typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression::value > > +auto +dot( const Containers::VectorView< Real, Device, Index >& a, const ET& b ) +{ + return (a, b); +} + +template< typename ET, typename Real, typename Device, typename Index, + typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression::value > > +auto +dot( const ET& a, const Containers::VectorView< Real, Device, Index >& b ) +{ + return (a, b); +} + +template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2 > +auto +dot( const Containers::VectorView< Real1, Device, Index1 >& a, const Containers::VectorView< Real2, Device, Index2 >& b ) +{ + return (a, b); +} + + //// // Abs template< typename Real, typename Device, typename Index > @@ -382,7 +397,7 @@ template< typename Real, typename Device, typename Index, typename 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 ); + return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ExpType, Containers::Expressions::Pow >( a, exp ); } //// @@ -574,6 +589,17 @@ sign( const Containers::VectorView< Real, Device, Index >& a ) return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sign >( a ); } +//// +// Cast +template< typename ResultType, typename Real, typename Device, typename Index, + // workaround: templated type alias cannot be declared at block level + template class Operation = Containers::Expressions::Cast< ResultType >::template Operation > +auto +cast( const Containers::VectorView< Real, Device, Index >& a ) +{ + return Containers::Expressions::UnaryExpressionTemplate< std::decay_t, Operation >( a ); +} + //// // Vertical operations - min template< typename Real, @@ -588,10 +614,10 @@ min( const Containers::VectorView< Real, Device, Index >& a ) template< typename Real, typename Device, typename Index > -Real -argMin( const Containers::VectorView< Real, Device, Index >& a, Index& arg ) +std::pair< Index, std::decay_t< Real > > +argMin( const Containers::VectorView< Real, Device, Index >& a ) { - return Containers::Expressions::ExpressionArgMin( a, arg ); + return Containers::Expressions::ExpressionArgMin( a ); } template< typename Real, @@ -606,10 +632,10 @@ max( const Containers::VectorView< Real, Device, Index >& a ) template< typename Real, typename Device, typename Index > -Real -argMax( const Containers::VectorView< Real, Device, Index >& a, Index& arg ) +std::pair< Index, std::decay_t< Real > > +argMax( const Containers::VectorView< Real, Device, Index >& a ) { - return Containers::Expressions::ExpressionArgMax( a, arg ); + return Containers::Expressions::ExpressionArgMax( a ); } template< typename Real, @@ -621,19 +647,47 @@ sum( const Containers::VectorView< Real, Device, Index >& a ) return Containers::Expressions::ExpressionSum( a ); } +template< typename Real, + typename Device, + typename Index > +auto +maxNorm( const Containers::VectorView< Real, Device, Index >& a ) +{ + return max( abs( a ) ); +} + +template< typename Real, + typename Device, + typename Index > +auto +l1Norm( const Containers::VectorView< Real, Device, Index >& a ) +{ + return Containers::Expressions::ExpressionL1Norm( a ); +} + +template< typename Real, + typename Device, + typename Index > +auto +l2Norm( const Containers::VectorView< Real, Device, Index >& a ) +{ + return TNL::sqrt( Containers::Expressions::ExpressionL2Norm( a ) ); +} + template< typename Real, typename Device, typename Index, typename Real2 > auto lpNorm( const Containers::VectorView< Real, Device, Index >& a, const Real2& p ) --> decltype( Containers::Expressions::ExpressionLpNorm( a, p ) ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { if( p == 1.0 ) - return Containers::Expressions::ExpressionLpNorm( a, p ); + return l1Norm( a ); if( p == 2.0 ) - return TNL::sqrt( Containers::Expressions::ExpressionLpNorm( a, p ) ); - return TNL::pow( Containers::Expressions::ExpressionLpNorm( a, p ), (Real2) (1.0 / p) ); + return l2Norm( a ); + return TNL::pow( Containers::Expressions::ExpressionLpNorm( a, p ), 1.0 / p ); } template< typename Real, @@ -681,29 +735,4 @@ binaryAnd( const Containers::VectorView< Real, Device, Index >& 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, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression::value > > -auto -dot( const Containers::VectorView< Real, Device, Index >& a, const ET& b ) -{ - return TNL::sum( a * b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression::value > > -auto -dot( const ET& a, const Containers::VectorView< Real, Device, Index >& b ) -{ - return TNL::sum( a * b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2 > -auto -dot( const Containers::VectorView< Real1, Device, Index1 >& a, const Containers::VectorView< Real2, Device, Index2 >& b ) -{ - return TNL::sum( a * b ); -} - } // namespace TNL diff --git a/src/TNL/Math.h b/src/TNL/Math.h index 53e6100ad08eefdbb7bdd488758e2cee8849120c..cd73b020e4c35fbe08c969864c9c26e400bd76ef 100644 --- a/src/TNL/Math.h +++ b/src/TNL/Math.h @@ -171,7 +171,7 @@ ResultType pow( const T1& base, const T2& exp ) */ template< typename T > __cuda_callable__ inline -T exp( const T& value ) +auto exp( const T& value ) -> decltype( std::exp(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::exp( value ); @@ -185,7 +185,7 @@ T exp( const T& value ) */ template< typename T > __cuda_callable__ inline -T sqrt( const T& value ) +auto sqrt( const T& value ) -> decltype( std::sqrt(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::sqrt( value ); @@ -199,7 +199,7 @@ T sqrt( const T& value ) */ template< typename T > __cuda_callable__ inline -T cbrt( const T& value ) +auto cbrt( const T& value ) -> decltype( std::cbrt(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::cbrt( value ); @@ -213,7 +213,7 @@ T cbrt( const T& value ) */ template< typename T > __cuda_callable__ inline -T log( const T& value ) +auto log( const T& value ) -> decltype( std::log(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::log( value ); @@ -227,7 +227,7 @@ T log( const T& value ) */ template< typename T > __cuda_callable__ inline -T log10( const T& value ) +auto log10( const T& value ) -> decltype( std::log10(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::log10( value ); @@ -241,7 +241,7 @@ T log10( const T& value ) */ template< typename T > __cuda_callable__ inline -T log2( const T& value ) +auto log2( const T& value ) -> decltype( std::log2(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::log2( value ); @@ -255,7 +255,7 @@ T log2( const T& value ) */ template< typename T > __cuda_callable__ inline -T sin( const T& value ) +auto sin( const T& value ) -> decltype( std::sin(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::sin( value ); @@ -269,7 +269,7 @@ T sin( const T& value ) */ template< typename T > __cuda_callable__ inline -T cos( const T& value ) +auto cos( const T& value ) -> decltype( std::cos(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::cos( value ); @@ -283,7 +283,7 @@ T cos( const T& value ) */ template< typename T > __cuda_callable__ inline -T tan( const T& value ) +auto tan( const T& value ) -> decltype( std::tan(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::tan( value ); @@ -297,7 +297,7 @@ T tan( const T& value ) */ template< typename T > __cuda_callable__ inline -T asin( const T& value ) +auto asin( const T& value ) -> decltype( std::asin(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::asin( value ); @@ -311,7 +311,7 @@ T asin( const T& value ) */ template< typename T > __cuda_callable__ inline -T acos( const T& value ) +auto acos( const T& value ) -> decltype( std::acos(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::acos( value ); @@ -325,7 +325,7 @@ T acos( const T& value ) */ template< typename T > __cuda_callable__ inline -T atan( const T& value ) +auto atan( const T& value ) -> decltype( std::atan(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::atan( value ); @@ -339,7 +339,7 @@ T atan( const T& value ) */ template< typename T > __cuda_callable__ inline -T sinh( const T& value ) +auto sinh( const T& value ) -> decltype( std::sinh(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::sinh( value ); @@ -353,7 +353,7 @@ T sinh( const T& value ) */ template< typename T > __cuda_callable__ inline -T cosh( const T& value ) +auto cosh( const T& value ) -> decltype( std::cosh(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::cosh( value ); @@ -367,7 +367,7 @@ T cosh( const T& value ) */ template< typename T > __cuda_callable__ inline -T tanh( const T& value ) +auto tanh( const T& value ) -> decltype( std::tanh(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::tanh( value ); @@ -381,7 +381,7 @@ T tanh( const T& value ) */ template< typename T > __cuda_callable__ inline -T asinh( const T& value ) +auto asinh( const T& value ) -> decltype( std::asinh(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::asinh( value ); @@ -395,7 +395,7 @@ T asinh( const T& value ) */ template< typename T > __cuda_callable__ inline -T acosh( const T& value ) +auto acosh( const T& value ) -> decltype( std::acosh(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::acosh( value ); @@ -409,7 +409,7 @@ T acosh( const T& value ) */ template< typename T > __cuda_callable__ inline -T atanh( const T& value ) +auto atanh( const T& value ) -> decltype( std::atanh(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::atanh( value ); @@ -423,7 +423,7 @@ T atanh( const T& value ) */ template< typename T > __cuda_callable__ inline -T floor( const T& value ) +auto floor( const T& value ) -> decltype( std::floor(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::floor( value ); @@ -437,7 +437,7 @@ T floor( const T& value ) */ template< typename T > __cuda_callable__ inline -T ceil( const T& value ) +auto ceil( const T& value ) -> decltype( std::ceil(value) ) { #if defined(__CUDA_ARCH__) || defined(__MIC__) return ::ceil( value ); @@ -465,7 +465,6 @@ void swap( Type& a, Type& b ) * * It extracts the sign of the number \e a. In other words, the signum function projects * negative numbers to value -1, positive numbers to value 1 and zero to value 0. - * Non-zero complex numbers are projected to the unit circle. */ template< class T > __cuda_callable__ diff --git a/src/TNL/Matrices/Dense_impl.h b/src/TNL/Matrices/Dense_impl.h index a1702f0af55683ee3b718eac567c8f0bd70c944b..5b55dbc292b76e63d28c6039ff6f552f89a05183 100644 --- a/src/TNL/Matrices/Dense_impl.h +++ b/src/TNL/Matrices/Dense_impl.h @@ -437,8 +437,8 @@ template< typename Real, typename Index > template< typename Matrix > void Dense< Real, Device, Index >::addMatrix( const Matrix& matrix, - const RealType& matrixMultiplicator, - const RealType& thisMatrixMultiplicator ) + const RealType& matrixMultiplicator, + const RealType& thisMatrixMultiplicator ) { TNL_ASSERT( this->getColumns() == matrix.getColumns() && this->getRows() == matrix.getRows(), @@ -448,9 +448,9 @@ void Dense< Real, Device, Index >::addMatrix( const Matrix& matrix, << "That matrix rows: " << matrix.getRows() << std::endl ); if( thisMatrixMultiplicator == 1.0 ) - this->values.addVector( matrix.values, matrixMultiplicator ); + this->values += matrixMultiplicator * matrix.values; else - this->values.addVector( matrix.values, matrixMultiplicator, thisMatrixMultiplicator ); + this->values = thisMatrixMultiplicator * this->values + matrixMultiplicator * matrix.values; } #ifdef HAVE_CUDA diff --git a/src/TNL/Matrices/DistributedMatrix_impl.h b/src/TNL/Matrices/DistributedMatrix_impl.h index f99319afc448c8819ee0741f474f6c6a5b5965ac..33eeef26458cf1c69a744578400f83dc23782466 100644 --- a/src/TNL/Matrices/DistributedMatrix_impl.h +++ b/src/TNL/Matrices/DistributedMatrix_impl.h @@ -180,7 +180,7 @@ setCompressedRowLengths( const CompressedRowLengthsVector& rowLengths ) TNL_ASSERT_EQ( rowLengths.getCommunicationGroup(), getCommunicationGroup(), "row lengths vector has wrong communication group" ); if( getCommunicationGroup() != CommunicatorType::NullGroup ) { - localMatrix.setCompressedRowLengths( rowLengths.getLocalVectorView() ); + localMatrix.setCompressedRowLengths( rowLengths.getConstLocalView() ); spmv.reset(); } @@ -194,7 +194,7 @@ getCompressedRowLengths( CompressedRowLengthsVector& rowLengths ) const { if( getCommunicationGroup() != CommunicatorType::NullGroup ) { rowLengths.setDistribution( getLocalRowRange(), getRows(), getCommunicationGroup() ); - localMatrix.getCompressedRowLengths( rowLengths.getLocalVectorView() ); + localMatrix.getCompressedRowLengths( rowLengths.getLocalView() ); } } @@ -319,7 +319,7 @@ vectorProduct( const InVector& inVector, TNL_ASSERT_EQ( outVector.getLocalRange(), getLocalRowRange(), "output vector has wrong distribution" ); TNL_ASSERT_EQ( outVector.getCommunicationGroup(), getCommunicationGroup(), "output vector has wrong communication group" ); - auto outView = outVector.getLocalVectorView(); + auto outView = outVector.getLocalView(); localMatrix.vectorProduct( inVector, outView ); } diff --git a/src/TNL/Matrices/DistributedSpMV.h b/src/TNL/Matrices/DistributedSpMV.h index f70773c1fc6afd998e833223a97cbef3c87c1476..0886d686c3947c5d57d022e46beb21cb9ca01f3d 100644 --- a/src/TNL/Matrices/DistributedSpMV.h +++ b/src/TNL/Matrices/DistributedSpMV.h @@ -154,8 +154,8 @@ public: // prepare buffers commRequests.clear(); globalBuffer.init( Partitioner::getOffset( localMatrix.getColumns(), rank, nproc ), - inVector.getLocalVectorView(), - localMatrix.getColumns() - Partitioner::getOffset( localMatrix.getColumns(), rank, nproc ) - inVector.getLocalVectorView().getSize() ); + inVector.getConstLocalView(), + localMatrix.getColumns() - Partitioner::getOffset( localMatrix.getColumns(), rank, nproc ) - inVector.getConstLocalView().getSize() ); const auto globalBufferView = globalBuffer.getConstView(); // send our data to all processes that need it @@ -164,7 +164,7 @@ public: continue; if( commPatternStarts( i, rank ) < commPatternEnds( i, rank ) ) commRequests.push_back( CommunicatorType::ISend( - inVector.getLocalVectorView().getData() + commPatternStarts( i, rank ) - Partitioner::getOffset( localMatrix.getColumns(), rank, nproc ), + inVector.getConstLocalView().getData() + commPatternStarts( i, rank ) - Partitioner::getOffset( localMatrix.getColumns(), rank, nproc ), commPatternEnds( i, rank ) - commPatternStarts( i, rank ), i, 0, group ) ); } @@ -186,7 +186,7 @@ public: CommunicatorType::WaitAll( &commRequests[0], commRequests.size() ); // perform matrix-vector multiplication - auto outVectorView = outVector.getLocalVectorView(); + auto outVectorView = outVector.getLocalView(); const Pointers::DevicePointer< const MatrixType > localMatrixPointer( localMatrix ); auto kernel = [=] __cuda_callable__ ( IndexType i, const MatrixType* localMatrix ) mutable { @@ -197,7 +197,7 @@ public: } // optimization for banded matrices else { - auto outVectorView = outVector.getLocalVectorView(); + auto outVectorView = outVector.getLocalView(); const Pointers::DevicePointer< const MatrixType > localMatrixPointer( localMatrix ); const auto inView = inVector.getConstView(); diff --git a/src/TNL/Matrices/Tridiagonal_impl.h b/src/TNL/Matrices/Tridiagonal_impl.h index 8aabbf0fef9082abc18632c20728e98462d5c103..9a2d5e4a87c4b505f186bb59a95280eecd5f1bf2 100644 --- a/src/TNL/Matrices/Tridiagonal_impl.h +++ b/src/TNL/Matrices/Tridiagonal_impl.h @@ -445,17 +445,17 @@ template< typename Real, typename Index > template< typename Real2, typename Index2 > void Tridiagonal< Real, Device, Index >::addMatrix( const Tridiagonal< Real2, Device, Index2 >& matrix, - const RealType& matrixMultiplicator, - const RealType& thisMatrixMultiplicator ) + const RealType& matrixMultiplicator, + const RealType& thisMatrixMultiplicator ) { TNL_ASSERT( this->getRows() == matrix.getRows(), std::cerr << "This matrix columns: " << this->getColumns() << std::endl << "This matrix rows: " << this->getRows() << std::endl ); if( thisMatrixMultiplicator == 1.0 ) - this->values.addVector( matrix.values, matrixMultiplicator ); + this->values += matrixMultiplicator * matrix.values; else - this->values.addVector( matrix.values, matrixMultiplicator, thisMatrixMultiplicator ); + this->values = thisMatrixMultiplicator * this->values + matrixMultiplicator * matrix.values; } #ifdef HAVE_CUDA diff --git a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h index f3d3a378cae2e57c7a4faf10731bc1a1488c81d8..873475bcab18a4bc1003843a527b2337d69328e3 100644 --- a/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h +++ b/src/TNL/Meshes/MeshDetails/MeshLayers/BoundaryTags/Layer.h @@ -99,7 +99,7 @@ public: // Array does not have sum(), Vector of bools does not fit due to arithmetics Containers::VectorView< typename BoundaryTagsArray::ValueType, typename BoundaryTagsArray::DeviceType, typename BoundaryTagsArray::IndexType > _boundaryTagsVector; _boundaryTagsVector.bind( boundaryTags.getData(), boundaryTags.getSize() ); - const GlobalIndexType boundaryEntities = _boundaryTagsVector.template sum< GlobalIndexType >(); + const GlobalIndexType boundaryEntities = sum(cast< GlobalIndexType >( _boundaryTagsVector )); boundaryIndices.setSize( boundaryEntities ); interiorIndices.setSize( boundaryTags.getSize() - boundaryEntities ); diff --git a/src/TNL/Solvers/Linear/BICGStabL_impl.h b/src/TNL/Solvers/Linear/BICGStabL_impl.h index 9e90cbdfa6843400cf9f09be0f1855a21b213384..1f20d4a30e582d4565bcf15ccb4fdaa07c91947e 100644 --- a/src/TNL/Solvers/Linear/BICGStabL_impl.h +++ b/src/TNL/Solvers/Linear/BICGStabL_impl.h @@ -103,7 +103,7 @@ solve( ConstVectorViewType b, VectorViewType x ) this->nextIteration(); r_j.bind( &R.getData()[ j * ldSize ], size ); - rho_1 = r_ast.scalarProduct( r_j ); + rho_1 = (r_ast, r_j); beta = alpha * rho_1 / rho_0; rho_0 = rho_1; @@ -123,7 +123,7 @@ solve( ConstVectorViewType b, VectorViewType x ) Au.bind( &U.getData()[ (j + 1) * ldSize ], size ); preconditioned_matvec( u, Au ); - gamma = r_ast.scalarProduct( Au ); + gamma = (r_ast, Au); alpha = rho_0 / gamma; /**** @@ -145,7 +145,7 @@ solve( ConstVectorViewType b, VectorViewType x ) /**** * x_0 := x_0 + alpha * u_0 */ - x.addVector( u_0, alpha ); + x += alpha * u_0; } /**** @@ -162,8 +162,8 @@ solve( ConstVectorViewType b, VectorViewType x ) * r_j := r_j - T_{i,j} * r_i */ const int ij = (i-1) + (j-1) * ell; - T[ ij ] = r_i.scalarProduct( r_j ) / sigma[ i ]; - r_j.addVector( r_i, -T[ ij ] ); + T[ ij ] = (r_i, r_j) / sigma[ i ]; + r_j -= T[ ij ] * r_i; } // MGS with reorthogonalization @@ -179,13 +179,13 @@ solve( ConstVectorViewType b, VectorViewType x ) // * r_j := r_j - T_{i,j} * r_i // */ // const int ij = (i-1) + (j-1) * ell; -// const RealType T_ij = r_i.scalarProduct( r_j ) / sigma[ i ]; +// const RealType T_ij = (r_i, r_j) / sigma[ i ]; // T[ ij ] += T_ij; -// r_j.addVector( r_i, -T_ij ); +// r_j -= T_ij * r_i ); // } - sigma[ j ] = r_j.scalarProduct( r_j ); - g_1[ j ] = r_0.scalarProduct( r_j ) / sigma[ j ]; + sigma[ j ] = (r_j, r_j); + g_1[ j ] = (r_0, r_j) / sigma[ j ]; } omega = g_1[ ell ]; @@ -217,17 +217,17 @@ solve( ConstVectorViewType b, VectorViewType x ) Matrices::MatrixOperations< DeviceType >:: gemv( size, ell, 1.0, R.getData(), ldSize, g_2.getData(), - 1.0, Traits::getLocalVectorView( x ).getData() ); + 1.0, Traits::getLocalView( x ).getData() ); // r_0 := r_0 - R_[1:ell] * g_1_[1:ell] Matrices::MatrixOperations< DeviceType >:: gemv( size, ell, -1.0, R.getData() + ldSize, ldSize, &g_1[ 1 ], - 1.0, Traits::getLocalVectorView( r_0 ).getData() ); + 1.0, Traits::getLocalView( r_0 ).getData() ); // u_0 := u_0 - U_[1:ell] * g_0_[1:ell] Matrices::MatrixOperations< DeviceType >:: gemv( size, ell, -1.0, U.getData() + ldSize, ldSize, &g_0[ 1 ], - 1.0, Traits::getLocalVectorView( u_0 ).getData() ); + 1.0, Traits::getLocalView( u_0 ).getData() ); if( exact_residue ) { /**** @@ -260,12 +260,12 @@ compute_residue( VectorViewType r, ConstVectorViewType x, ConstVectorViewType b */ if( this->preconditioner ) { this->matrix->vectorProduct( x, M_tmp ); - M_tmp.addVector( b, 1.0, -1.0 ); + M_tmp = b - M_tmp; this->preconditioner->solve( M_tmp, r ); } else { this->matrix->vectorProduct( x, r ); - r.addVector( b, 1.0, -1.0 ); + r = b - r; } } @@ -288,7 +288,7 @@ void BICGStabL< Matrix >:: setSize( const VectorViewType& x ) { - this->size = ldSize = Traits::getLocalVectorView( x ).getSize(); + this->size = ldSize = Traits::getConstLocalView( x ).getSize(); R.setSize( (ell + 1) * ldSize ); U.setSize( (ell + 1) * ldSize ); r_ast.setLike( x ); diff --git a/src/TNL/Solvers/Linear/BICGStab_impl.h b/src/TNL/Solvers/Linear/BICGStab_impl.h index b1255e33c581be1c9b4cb55062b93a18fa8e9fbf..735358622bd9875e825019793e0237f488f20bb4 100644 --- a/src/TNL/Solvers/Linear/BICGStab_impl.h +++ b/src/TNL/Solvers/Linear/BICGStab_impl.h @@ -57,18 +57,18 @@ bool BICGStab< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) b_norm = lpNorm( M_tmp, 2.0 ); this->matrix->vectorProduct( x, M_tmp ); - M_tmp.addVector( b, 1.0, -1.0 ); + M_tmp = b - M_tmp; this->preconditioner->solve( M_tmp, r ); } else { b_norm = lpNorm( b, 2.0 ); this->matrix->vectorProduct( x, r ); - r.addVector( b, 1.0, -1.0 ); + r = b - r; } p = r_ast = r; s.setValue( 0.0 ); - rho = r.scalarProduct( r_ast ); + rho = (r, r_ast); if( b_norm == 0.0 ) b_norm = 1.0; @@ -88,13 +88,13 @@ bool BICGStab< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) else { this->matrix->vectorProduct( p, Ap ); } - aux = Ap.scalarProduct( r_ast ); + aux = (Ap, r_ast); alpha = rho / aux; /**** * s_j = r_j - alpha_j * A p_j */ - s.addVectors( r, 1.0, Ap, -alpha, 0.0 ); + s = r - alpha * Ap; /**** * omega_j = ( A s_j, s_j ) / ( A s_j, A s_j ) @@ -107,29 +107,29 @@ bool BICGStab< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) this->matrix->vectorProduct( s, As ); } aux = lpNorm( As, 2.0 ); - omega = As.scalarProduct( s ) / ( aux * aux ); + omega = (As, s) / (aux * aux); /**** * x_{j+1} = x_j + alpha_j * p_j + omega_j * s_j */ - x.addVectors( p, alpha, s, omega ); + x += alpha * p + omega * s; /**** * r_{j+1} = s_j - omega_j * A s_j */ - r.addVectors( s, 1.0, As, -omega, 0.0 ); + r = s - omega * As; /**** * beta = alpha_j / omega_j * ( r_{j+1}, r^ast_0 ) / ( r_j, r^ast_0 ) */ rho_old = rho; - rho = r.scalarProduct( r_ast ); - beta = ( rho / rho_old ) * ( alpha / omega ); + rho = (r, r_ast); + beta = (rho / rho_old) * (alpha / omega); /**** * p_{j+1} = r_{j+1} + beta_j * ( p_j - omega_j * A p_j ) */ - p.addVectors( r, 1.0, Ap, -beta * omega, beta ); + p = r + beta * p - (beta * omega) * Ap; if( exact_residue ) { /**** @@ -137,12 +137,12 @@ bool BICGStab< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) */ if( this->preconditioner ) { this->matrix->vectorProduct( x, M_tmp ); - M_tmp.addVector( b, 1.0, -1.0 ); + M_tmp = b - M_tmp; this->preconditioner->solve( M_tmp, s ); } else { this->matrix->vectorProduct( x, s ); - s.addVector( b, 1.0, -1.0 ); + s = b - s; } const RealType residue = lpNorm( s, 2.0 ); this->setResidue( residue / b_norm ); diff --git a/src/TNL/Solvers/Linear/CG_impl.h b/src/TNL/Solvers/Linear/CG_impl.h index 0c5bcd72bd1d0108fdbcce3692329726e4a6cb4c..07f8ea1979a691029a34fecfe1e4cf052d1a0f73 100644 --- a/src/TNL/Solvers/Linear/CG_impl.h +++ b/src/TNL/Solvers/Linear/CG_impl.h @@ -49,7 +49,7 @@ solve( ConstVectorViewType b, VectorViewType x ) * r_0 = b - A x_0, p_0 = r_0 */ this->matrix->vectorProduct( x, r ); - r.addVector( b, 1.0, -1.0 ); + r = b - r; if( this->preconditioner ) { // z_0 = M^{-1} r_0 @@ -57,13 +57,13 @@ solve( ConstVectorViewType b, VectorViewType x ) // p_0 = z_0 p = z; // s1 = (r_0, z_0) - s1 = r.scalarProduct( z ); + s1 = (r, z); } else { // p_0 = r_0 p = r; // s1 = (r_0, r_0) - s1 = r.scalarProduct( r ); + s1 = (r, r); } this->setResidue( std::sqrt(s1) / normb ); @@ -72,7 +72,7 @@ solve( ConstVectorViewType b, VectorViewType x ) { // s2 = (A * p_j, p_j) this->matrix->vectorProduct( p, Ap ); - s2 = Ap.scalarProduct( p ); + s2 = (Ap, p); // if s2 = 0 => p = 0 => r = 0 => we have the solution (provided A != 0) if( s2 == 0.0 ) { @@ -84,22 +84,22 @@ solve( ConstVectorViewType b, VectorViewType x ) alpha = s1 / s2; // x_{j+1} = x_j + alpha_j p_j - x.addVector( p, alpha ); + x += alpha * p; // r_{j+1} = r_j - alpha_j A * p_j - r.addVector( Ap, -alpha ); + r -= alpha * Ap; if( this->preconditioner ) { // z_{j+1} = M^{-1} * r_{j+1} this->preconditioner->solve( r, z ); // beta_j = (r_{j+1}, z_{j+1}) / (r_j, z_j) s2 = s1; - s1 = r.scalarProduct( z ); + s1 = (r, z); } else { // beta_j = (r_{j+1}, r_{j+1}) / (r_j, r_j) s2 = s1; - s1 = r.scalarProduct( r ); + s1 = (r, r); } // if s2 = 0 => r = 0 => we have the solution @@ -108,10 +108,10 @@ solve( ConstVectorViewType b, VectorViewType x ) if( this->preconditioner ) // p_{j+1} = z_{j+1} + beta_j * p_j - p.addVector( z, 1.0, beta ); + p = z + beta * p; else // p_{j+1} = r_{j+1} + beta_j * p_j - p.addVector( r, 1.0, beta ); + p = r + beta * p; this->setResidue( std::sqrt(s1) / normb ); } diff --git a/src/TNL/Solvers/Linear/GMRES.h b/src/TNL/Solvers/Linear/GMRES.h index 80738a686b7028acc2bd2b579c06c4f7d2e6e794..1cc6901dc5fd142e53b4f4a1e3f458716bba0602 100644 --- a/src/TNL/Solvers/Linear/GMRES.h +++ b/src/TNL/Solvers/Linear/GMRES.h @@ -49,8 +49,8 @@ public: protected: // local vectors/views - using ConstDeviceView = typename Traits::ConstLocalVectorViewType; - using DeviceView = typename Traits::LocalVectorViewType; + using ConstDeviceView = typename Traits::ConstLocalViewType; + using DeviceView = typename Traits::LocalViewType; using HostView = typename DeviceView::HostType; using DeviceVector = typename Traits::LocalVectorType; using HostVector = typename DeviceVector::HostType; diff --git a/src/TNL/Solvers/Linear/GMRES_impl.h b/src/TNL/Solvers/Linear/GMRES_impl.h index 06b1295014839a353f1e1d69e285b4628d650984..f45741151b03c8fadcd695c09d94abd168c12c7f 100644 --- a/src/TNL/Solvers/Linear/GMRES_impl.h +++ b/src/TNL/Solvers/Linear/GMRES_impl.h @@ -192,7 +192,7 @@ orthogonalize_MGS( const int m, const RealType normb, const RealType beta ) * v_0 = r / | r | = 1.0 / beta * r */ v_i.bind( V.getData(), size ); - v_i.addVector( r, 1.0 / beta, 0.0 ); + v_i = (1.0 / beta) * r; H.setValue( 0.0 ); s.setValue( 0.0 ); @@ -217,25 +217,25 @@ orthogonalize_MGS( const int m, const RealType normb, const RealType beta ) /*** * H_{k,i} = ( w, v_k ) */ - RealType H_k_i = w.scalarProduct( v_k ); - H[ k + i * ( m + 1 ) ] += H_k_i; + RealType H_k_i = (w, v_k); + H[ k + i * (m + 1) ] += H_k_i; /**** * w = w - H_{k,i} v_k */ - w.addVector( v_k, -H_k_i ); + w = w - H_k_i * v_k; } /*** * H_{i+1,i} = |w| */ RealType normw = lpNorm( w, 2.0 ); - H[ i + 1 + i * ( m + 1 ) ] = normw; + H[ i + 1 + i * (m + 1) ] = normw; /*** * v_{i+1} = w / |w| */ v_i.bind( &V.getData()[ ( i + 1 ) * ldSize ], size ); - v_i.addVector( w, 1.0 / normw, 0.0 ); + v_i = (1.0 / normw) * w; /**** * Applying the Givens rotations G_0, ..., G_i @@ -266,8 +266,8 @@ orthogonalize_CWY( const int m, const RealType normb, const RealType beta ) * z = r / | r | = 1.0 / beta * r */ // TODO: investigate normalization by beta and normb -// z.addVector( r, 1.0 / beta, 0.0 ); -// z.addVector( r, 1.0 / normb, 0.0 ); +// z = (1.0 / beta) * r; +// z = (1.0 / normb) * r; z = r; H.setValue( 0.0 ); @@ -349,12 +349,12 @@ compute_residue( VectorViewType r, ConstVectorViewType x, ConstVectorViewType b */ if( this->preconditioner ) { this->matrix->vectorProduct( x, _M_tmp ); - _M_tmp.addVector( b, 1.0, -1.0 ); + _M_tmp = b - _M_tmp; this->preconditioner->solve( _M_tmp, r ); } else { this->matrix->vectorProduct( x, r ); - r.addVector( b, 1.0, -1.0 ); + r = b - r; } } @@ -394,8 +394,8 @@ hauseholder_generate( const int i, ParallelFor< DeviceType >::exec( (IndexType) 0, size, kernel_truncation ); } else { - ConstDeviceView z_local = Traits::getLocalVectorView( z ); - DeviceView y_i_local = Traits::getLocalVectorView( y_i ); + ConstDeviceView z_local = Traits::getConstLocalView( z ); + DeviceView y_i_local = Traits::getLocalView( y_i ); y_i_local = z_local; } @@ -434,7 +434,7 @@ hauseholder_generate( const int i, size, Y.getData(), ldSize, - Traits::getLocalVectorView( y_i ).getData(), + Traits::getLocalView( y_i ).getData(), aux ); // no-op if the problem is not distributed CommunicatorType::Allreduce( aux, i, MPI_SUM, Traits::getCommunicationGroup( *this->matrix ) ); @@ -460,13 +460,13 @@ 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 >::copy( YL_i.getData(), Traits::getLocalVectorView( y_i ).getData(), YL_i.getSize() ); + Containers::Algorithms::ArrayOperations< Devices::Host, DeviceType >::copy( YL_i.getData(), Traits::getLocalView( 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 ) ); // NOTE: aux = t_i * (y_i, z) = 1 since t_i = 2 / ||y_i||^2 and // (y_i, z) = ||z_trunc||^2 + |z_i| ||z_trunc|| = ||y_i||^2 / 2 -// const RealType aux = T[ i + i * (restarting_max + 1) ] * y_i.scalarProduct( z ); +// const RealType aux = T[ i + i * (restarting_max + 1) ] * (y_i, z); constexpr RealType aux = 1.0; if( localOffset == 0 ) { if( std::is_same< DeviceType, Devices::Host >::value ) { @@ -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 >::copy( host_z, Traits::getLocalVectorView( z ).getData(), i + 1 ); + Containers::Algorithms::ArrayOperations< Devices::Host, Devices::Cuda >::copy( host_z, Traits::getConstLocalView( z ).getData(), i + 1 ); for( int k = 0; k <= i; k++ ) out[ k ] = host_z[ k ] - YL_i[ k ] * aux; } @@ -511,7 +511,7 @@ hauseholder_cwy( VectorViewType v, Matrices::MatrixOperations< DeviceType >:: gemv( size, i + 1, -1.0, Y.getData(), ldSize, aux, - 0.0, Traits::getLocalVectorView( v ).getData() ); + 0.0, Traits::getLocalView( v ).getData() ); if( localOffset == 0 ) v.setElement( i, 1.0 + v.getElement( i ) ); } @@ -532,7 +532,7 @@ hauseholder_cwy_transposed( VectorViewType z, size, Y.getData(), ldSize, - Traits::getLocalVectorView( w ).getData(), + Traits::getConstLocalView( w ).getData(), aux ); // no-op if the problem is not distributed Traits::CommunicatorType::Allreduce( aux, i + 1, MPI_SUM, Traits::getCommunicationGroup( *this->matrix ) ); @@ -551,7 +551,7 @@ hauseholder_cwy_transposed( VectorViewType z, Matrices::MatrixOperations< DeviceType >:: gemv( size, i + 1, -1.0, Y.getData(), ldSize, aux, - 1.0, Traits::getLocalVectorView( z ).getData() ); + 1.0, Traits::getLocalView( z ).getData() ); } template< typename Matrix > @@ -593,7 +593,7 @@ update( const int k, Matrices::MatrixOperations< DeviceType >:: gemv( size, k + 1, 1.0, V.getData(), ldSize, y, - 1.0, Traits::getLocalVectorView( x ).getData() ); + 1.0, Traits::getLocalView( x ).getData() ); } else { // The vectors v_i are not stored, they can be reconstructed as P_0...P_j * e_j. @@ -625,7 +625,7 @@ update( const int k, Matrices::MatrixOperations< DeviceType >:: gemv( size, k + 1, -1.0, Y.getData(), ldSize, aux, - 1.0, Traits::getLocalVectorView( x ).getData() ); + 1.0, Traits::getLocalView( x ).getData() ); // x += y if( localOffset == 0 ) @@ -703,7 +703,7 @@ void GMRES< Matrix >:: setSize( const VectorViewType& x ) { - this->size = Traits::getLocalVectorView( x ).getSize(); + this->size = Traits::getLocalView( x ).getSize(); if( std::is_same< DeviceType, Devices::Cuda >::value ) // align each column to 256 bytes - optimal for CUDA ldSize = roundToMultiple( size, 256 / sizeof( RealType ) ); diff --git a/src/TNL/Solvers/Linear/Preconditioners/Diagonal.h b/src/TNL/Solvers/Linear/Preconditioners/Diagonal.h index 308423728af9069fc768a1ee374f28483f70a77b..25aa1cd7c7aff9d65c863a0f3a8e1e2f578ef1cb 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/Diagonal.h +++ b/src/TNL/Solvers/Linear/Preconditioners/Diagonal.h @@ -60,8 +60,8 @@ public: using typename Preconditioner< MatrixType >::ConstVectorViewType; using typename Preconditioner< MatrixType >::MatrixPointer; using VectorType = Containers::Vector< RealType, DeviceType, IndexType >; - using LocalVectorViewType = Containers::VectorView< RealType, DeviceType, IndexType >; - using ConstLocalVectorViewType = Containers::VectorView< std::add_const_t< RealType >, DeviceType, IndexType >; + using LocalViewType = Containers::VectorView< RealType, DeviceType, IndexType >; + using ConstLocalViewType = Containers::VectorView< std::add_const_t< RealType >, DeviceType, IndexType >; virtual void update( const MatrixPointer& matrixPointer ) override; diff --git a/src/TNL/Solvers/Linear/Preconditioners/Diagonal_impl.h b/src/TNL/Solvers/Linear/Preconditioners/Diagonal_impl.h index 5f40800d69be94ca5c06ce4120c4308b27b96e4a..de4b9f3f1ee84b668d4daf2a6515ddf102973d95 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/Diagonal_impl.h +++ b/src/TNL/Solvers/Linear/Preconditioners/Diagonal_impl.h @@ -68,7 +68,7 @@ update( const MatrixPointer& matrixPointer ) diagonal.setSize( matrixPointer->getLocalMatrix().getRows() ); - LocalVectorViewType diag_view( diagonal ); + LocalViewType diag_view( diagonal ); const MatrixType* kernel_matrix = &matrixPointer.template getData< DeviceType >(); auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable @@ -85,9 +85,9 @@ void Diagonal< Matrices::DistributedMatrix< Matrix, Communicator > >:: solve( ConstVectorViewType b, VectorViewType x ) const { - ConstLocalVectorViewType diag_view( diagonal ); - const auto b_view = b.getLocalVectorView(); - auto x_view = x.getLocalVectorView(); + ConstLocalViewType diag_view( diagonal ); + const auto b_view = b.getConstLocalView(); + auto x_view = x.getLocalView(); auto kernel = [=] __cuda_callable__ ( IndexType i ) mutable { diff --git a/src/TNL/Solvers/Linear/Preconditioners/ILU0_impl.h b/src/TNL/Solvers/Linear/Preconditioners/ILU0_impl.h index 33f44e60c186352890a3308e82a803ef77baa4dd..626469920ff9e08d7f935e13017086b7cd583081 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/ILU0_impl.h +++ b/src/TNL/Solvers/Linear/Preconditioners/ILU0_impl.h @@ -124,8 +124,8 @@ void ILU0_impl< Matrix, Real, Devices::Host, Index >:: solve( ConstVectorViewType _b, VectorViewType _x ) const { - const auto b = Traits< Matrix >::getLocalVectorView( _b ); - auto x = Traits< Matrix >::getLocalVectorView( _x ); + const auto b = Traits< Matrix >::getConstLocalView( _b ); + auto x = Traits< Matrix >::getLocalView( _x ); // Step 1: solve y from Ly = b triangularSolveLower< true >( L, x, b ); diff --git a/src/TNL/Solvers/Linear/Preconditioners/ILUT_impl.h b/src/TNL/Solvers/Linear/Preconditioners/ILUT_impl.h index a1735e9e6de16e1d2804e9524462e5094cc628d1..858f037febbd7f26ccfbc39d3c4de8e2fdbeecdb 100644 --- a/src/TNL/Solvers/Linear/Preconditioners/ILUT_impl.h +++ b/src/TNL/Solvers/Linear/Preconditioners/ILUT_impl.h @@ -266,8 +266,8 @@ void ILUT_impl< Matrix, Real, Devices::Host, Index >:: solve( ConstVectorViewType _b, VectorViewType _x ) const { - const auto b = Traits< Matrix >::getLocalVectorView( _b ); - auto x = Traits< Matrix >::getLocalVectorView( _x ); + const auto b = Traits< Matrix >::getConstLocalView( _b ); + auto x = Traits< Matrix >::getLocalView( _x ); // Step 1: solve y from Ly = b triangularSolveLower< false >( L, x, b ); diff --git a/src/TNL/Solvers/Linear/TFQMR_impl.h b/src/TNL/Solvers/Linear/TFQMR_impl.h index 33fde7561bbab25875d8034e5ba575d8d418c547..590aa35af0b9c9cf8cf73a0c66e02a265a1bacdf 100644 --- a/src/TNL/Solvers/Linear/TFQMR_impl.h +++ b/src/TNL/Solvers/Linear/TFQMR_impl.h @@ -38,13 +38,13 @@ bool TFQMR< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) b_norm = lpNorm( M_tmp, 2.0 ); this->matrix->vectorProduct( x, M_tmp ); - M_tmp.addVector( b, 1.0, -1.0 ); + M_tmp = b - M_tmp; this->preconditioner->solve( M_tmp, r ); } else { b_norm = lpNorm( b, 2.0 ); this->matrix->vectorProduct( x, r ); - r.addVector( b, 1.0, -1.0 ); + r = b - r; } w = u = r; if( this->preconditioner ) { @@ -59,7 +59,7 @@ bool TFQMR< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) tau = lpNorm( r, 2.0 ); theta = eta = 0.0; r_ast = r; - rho = r_ast.scalarProduct( r ); + rho = (r_ast, r); // only to avoid compiler warning; alpha is initialized inside the loop alpha = 0.0; @@ -74,7 +74,7 @@ bool TFQMR< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) const IndexType iter = this->getIterations(); if( iter % 2 == 1 ) { - alpha = rho / v. scalarProduct( this->r_ast ); + alpha = rho / (v, r_ast); } else { // not necessary in odd iter since the previous iteration @@ -87,14 +87,14 @@ bool TFQMR< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) this->matrix->vectorProduct( u, Au ); } } - w.addVector( Au, -alpha ); - d.addVector( u, 1.0, theta * theta * eta / alpha ); + w -= alpha * Au; + d = u + (theta * theta * eta / alpha) * d; w_norm = lpNorm( w, 2.0 ); theta = w_norm / tau; const RealType c = 1.0 / std::sqrt( 1.0 + theta * theta ); tau = tau * theta * c; eta = c * c * alpha; - x.addVector( d, eta ); + x += eta * d; this->setResidue( tau * std::sqrt(iter+1) / b_norm ); if( iter > this->getMinIterations() && this->getResidue() < this->getConvergenceResidue() ) { @@ -102,12 +102,12 @@ bool TFQMR< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) } if( iter % 2 == 0 ) { - const RealType rho_new = w.scalarProduct( this->r_ast ); + const RealType rho_new = (w, r_ast); const RealType beta = rho_new / rho; rho = rho_new; - u.addVector( w, 1.0, beta ); - v.addVector( Au, beta, beta * beta ); + u = w + beta * u; + v = beta * Au + (beta * beta) * v; if( this->preconditioner ) { this->matrix->vectorProduct( u, M_tmp ); this->preconditioner->solve( M_tmp, Au ); @@ -115,10 +115,10 @@ bool TFQMR< Matrix >::solve( ConstVectorViewType b, VectorViewType x ) else { this->matrix->vectorProduct( u, Au ); } - v.addVector( Au, 1.0 ); + v += Au; } else { - u.addVector( v, -alpha ); + u -= alpha * v; } this->refreshSolverMonitor(); diff --git a/src/TNL/Solvers/Linear/Traits.h b/src/TNL/Solvers/Linear/Traits.h index 4130ec430053b8fd28867c4d247c7d8760dc2a05..9a5db2c40297aeba9713482603fc8fcb15d6793e 100644 --- a/src/TNL/Solvers/Linear/Traits.h +++ b/src/TNL/Solvers/Linear/Traits.h @@ -43,13 +43,13 @@ struct Traits // compatibility aliases using LocalVectorType = VectorType; - using LocalVectorViewType = VectorViewType; - using ConstLocalVectorViewType = ConstVectorViewType; + using LocalViewType = VectorViewType; + using ConstLocalViewType = ConstVectorViewType; // compatibility wrappers for some DistributedMatrix methods static const Matrix& getLocalMatrix( const Matrix& m ) { return m; } - static ConstLocalVectorViewType getLocalVectorView( ConstVectorViewType v ) { return v; } - static LocalVectorViewType getLocalVectorView( VectorViewType v ) { return v; } + static ConstLocalViewType getConstLocalView( ConstVectorViewType v ) { return v; } + static LocalViewType getLocalView( VectorViewType v ) { return v; } static typename CommunicatorType::CommunicationGroup getCommunicationGroup( const Matrix& m ) { return CommunicatorType::AllGroup; } }; @@ -79,11 +79,11 @@ struct Traits< Matrices::DistributedMatrix< Matrix, Communicator > > < typename Matrix::RealType, typename Matrix::DeviceType, typename Matrix::IndexType >; - using LocalVectorViewType = Containers::VectorView + using LocalViewType = Containers::VectorView < typename Matrix::RealType, typename Matrix::DeviceType, typename Matrix::IndexType >; - using ConstLocalVectorViewType = Containers::VectorView + using ConstLocalViewType = Containers::VectorView < std::add_const_t< typename Matrix::RealType >, typename Matrix::DeviceType, typename Matrix::IndexType >; @@ -91,8 +91,8 @@ struct Traits< Matrices::DistributedMatrix< Matrix, Communicator > > // compatibility wrappers for some DistributedMatrix methods static const Matrix& getLocalMatrix( const Matrices::DistributedMatrix< Matrix, Communicator >& m ) { return m.getLocalMatrix(); } - static ConstLocalVectorViewType getLocalVectorView( ConstVectorViewType v ) { return v.getLocalVectorView(); } - static LocalVectorViewType getLocalVectorView( VectorViewType v ) { return v.getLocalVectorView(); } + static ConstLocalViewType getConstLocalView( ConstVectorViewType v ) { return v.getConstLocalView(); } + static LocalViewType getLocalView( VectorViewType v ) { return v.getLocalView(); } static typename CommunicatorType::CommunicationGroup getCommunicationGroup( const Matrices::DistributedMatrix< Matrix, Communicator >& m ) { return m.getCommunicationGroup(); } }; diff --git a/src/TNL/TypeTraits.h b/src/TNL/TypeTraits.h index 1de521cfcc8b2490e3bbc60673478ff540f4779b..a496aee5d01c4a7c25e3ef6a402e9426701275d5 100644 --- a/src/TNL/TypeTraits.h +++ b/src/TNL/TypeTraits.h @@ -163,4 +163,13 @@ struct IsStaticArrayType HasSubscriptOperator< T >::value > {}; +/** + * \brief Type trait for checking if T is a view type. + */ +template< typename T > +struct IsViewType +: public std::integral_constant< bool, + std::is_same< typename T::ViewType, T >::value > +{}; + } //namespace TNL diff --git a/src/UnitTests/Communicators/MpiCommunicatorTest.cpp b/src/UnitTests/Communicators/MpiCommunicatorTest.cpp index 0056e41a8714cc2f1cce10381e68701422acf8fe..b78011953e638a84796d5b30daa848f168274303 100644 --- a/src/UnitTests/Communicators/MpiCommunicatorTest.cpp +++ b/src/UnitTests/Communicators/MpiCommunicatorTest.cpp @@ -34,7 +34,7 @@ using MpiCommunicatorTypes = ::testing::Types< double >; -TYPED_TEST_CASE( MpiCommunicatorTest, MpiCommunicatorTypes ); +TYPED_TEST_SUITE( MpiCommunicatorTest, MpiCommunicatorTypes ); TYPED_TEST( MpiCommunicatorTest, allReduce ) { diff --git a/src/UnitTests/Containers/ArrayTest.h b/src/UnitTests/Containers/ArrayTest.h index 31d58bed65e2cec07bf3648b76b34bee9397f8cb..7436f0db77ff7dc4a618623b6734a05023cdfef9 100644 --- a/src/UnitTests/Containers/ArrayTest.h +++ b/src/UnitTests/Containers/ArrayTest.h @@ -78,8 +78,6 @@ using ArrayTypes = ::testing::Types< Array< float, Devices::Host, long >, Array< double, Devices::Host, long >, Array< MyData, Devices::Host, long > - // FIXME: this segfaults in String::~String() -// Array< String, Devices::Host, long > #endif #ifdef HAVE_CUDA Array< int, Devices::Cuda, short >, @@ -207,6 +205,7 @@ TYPED_TEST( ArrayTest, constructorsWithAllocators ) EXPECT_EQ( v.getAllocator(), allocator ); // deep copy + u = 0; // floating-point values have to be initialized before comparison, because nan != nan ArrayType w( u, allocator ); EXPECT_NE( w.getData(), u.getData() ); EXPECT_EQ( w.getSize(), u.getSize() ); @@ -463,12 +462,6 @@ TYPED_TEST( ArrayTest, assignmentOperator ) u_host.setElement( i, i ); } - v = 42; - for( int i = 0; i < 10; i++ ) - EXPECT_EQ( v.getElement( i ), 42 ); - v = u; - EXPECT_EQ( u, v ); - // assignment from host to device v.setValue( 0 ); v = u_host; @@ -479,9 +472,10 @@ TYPED_TEST( ArrayTest, assignmentOperator ) u_host = u; EXPECT_EQ( u_host, u ); - u = 5; + // assignment of a scalar + u = 42; for( int i = 0; i < 10; i++ ) - EXPECT_EQ( u.getElement( i ), 5 ); + EXPECT_EQ( u.getElement( i ), 42 ); } // test works only for arithmetic types diff --git a/src/UnitTests/Containers/ArrayViewTest.h b/src/UnitTests/Containers/ArrayViewTest.h index 1d77b768bfd8fe4945f170dec468a7a8f1a973dc..8b4972742c8fd7027cd39dc32e1fb6c0510161b6 100644 --- a/src/UnitTests/Containers/ArrayViewTest.h +++ b/src/UnitTests/Containers/ArrayViewTest.h @@ -81,8 +81,6 @@ using ViewTypes = ::testing::Types< ArrayView< float, Devices::Host, long >, ArrayView< double, Devices::Host, long >, ArrayView< MyData, Devices::Host, long > - // FIXME: this segfaults in String::~String() -// , ArrayView< String, Devices::Host, long > #endif #ifdef HAVE_CUDA ArrayView< int, Devices::Cuda, short >, @@ -411,9 +409,7 @@ TYPED_TEST( ArrayViewTest, comparisonOperator ) // comparison with different device EXPECT_TRUE( u == a_host ); EXPECT_TRUE( a_host == u ); - // FIXME: what operator is called without explicit retyping? -// EXPECT_TRUE( w != a_host ); - EXPECT_TRUE( w != (ArrayView< typename ArrayType::ValueType, Devices::Host, typename ArrayType::IndexType >) a_host ); + EXPECT_TRUE( w != a_host ); EXPECT_TRUE( a_host != w ); v.reset(); @@ -472,25 +468,27 @@ TYPED_TEST( ArrayViewTest, assignmentOperator ) EXPECT_EQ( v.getData(), b.getData() ); // assignment from host to device - //v.setValue( 0 ); - v = 0; + v.setValue( 0 ); v = u_host; - // TODO: Replace with EXPECT_EQ when nvcc accepts it - EXPECT_TRUE( u == v ); + EXPECT_EQ( u, v ); EXPECT_EQ( v.getData(), b.getData() ); // assignment from device to host - /*u_host.setValue( 0 ); + u_host.setValue( 0 ); u_host = u; - - EXPECT_TRUE( u_host == u ); - //EXPECT_EQ( u_host, u ); TODO: this is not accepted by nvcc 10, because nvcc is cockot + EXPECT_EQ( u_host, u ); EXPECT_EQ( u_host.getData(), a_host.getData() ); // assignment of const view to non-const view v.setValue( 0 ); ConstViewType c( u ); - v = c;*/ + v = c; + + // assignment of a scalar + u = 42; + for( int i = 0; i < 10; i++ ) + EXPECT_EQ( u.getElement( i ), 42 ); + EXPECT_EQ( u.getData(), a.getData() ); } // test works only for arithmetic types diff --git a/src/UnitTests/Containers/CMakeLists.txt b/src/UnitTests/Containers/CMakeLists.txt index eb94f9406f1201c0b074ea2dfdfa367293e12f15..d33f5d2631bea262c9732d2489e02554738a72fb 100644 --- a/src/UnitTests/Containers/CMakeLists.txt +++ b/src/UnitTests/Containers/CMakeLists.txt @@ -22,23 +22,27 @@ TARGET_LINK_LIBRARIES( ArrayViewTest ${GTEST_BOTH_LIBRARIES} ) # NOTE: Vector = Array + VectorOperations, VectorView = ArrayView + VectorOperations, # so we test Vector, VectorView and VectorOperations at the same time -ADD_EXECUTABLE( VectorTest-1 VectorTest-1.cpp ) -ADD_EXECUTABLE( VectorTest-2 VectorTest-2.cpp ) -ADD_EXECUTABLE( VectorTest-3 VectorTest-3.cpp ) -TARGET_COMPILE_OPTIONS( VectorTest-1 PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_COMPILE_OPTIONS( VectorTest-2 PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_COMPILE_OPTIONS( VectorTest-3 PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_LINK_LIBRARIES( VectorTest-1 ${GTEST_BOTH_LIBRARIES} ) -TARGET_LINK_LIBRARIES( VectorTest-2 ${GTEST_BOTH_LIBRARIES} ) -TARGET_LINK_LIBRARIES( VectorTest-3 ${GTEST_BOTH_LIBRARIES} ) - -ADD_EXECUTABLE( BinaryVectorOperationsTest VectorBinaryOperationsTest.cpp ) -TARGET_COMPILE_OPTIONS( BinaryVectorOperationsTest PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_LINK_LIBRARIES( BinaryVectorOperationsTest ${GTEST_BOTH_LIBRARIES} ) - -ADD_EXECUTABLE( UnaryVectorOperationsTest VectorUnaryOperationsTest.cpp ) -TARGET_COMPILE_OPTIONS( UnaryVectorOperationsTest PRIVATE ${CXX_TESTS_FLAGS} ) -TARGET_LINK_LIBRARIES( UnaryVectorOperationsTest ${GTEST_BOTH_LIBRARIES} ) +ADD_EXECUTABLE( VectorTest VectorTest.cpp ) +ADD_EXECUTABLE( VectorPrefixSumTest VectorPrefixSumTest.cpp ) +ADD_EXECUTABLE( VectorEvaluateAndReduceTest VectorEvaluateAndReduceTest.cpp ) +TARGET_COMPILE_OPTIONS( VectorTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_COMPILE_OPTIONS( VectorPrefixSumTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_COMPILE_OPTIONS( VectorEvaluateAndReduceTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( VectorTest ${GTEST_BOTH_LIBRARIES} ) +TARGET_LINK_LIBRARIES( VectorPrefixSumTest ${GTEST_BOTH_LIBRARIES} ) +TARGET_LINK_LIBRARIES( VectorEvaluateAndReduceTest ${GTEST_BOTH_LIBRARIES} ) + +ADD_EXECUTABLE( VectorBinaryOperationsTest VectorBinaryOperationsTest.cpp ) +TARGET_COMPILE_OPTIONS( VectorBinaryOperationsTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( VectorBinaryOperationsTest ${GTEST_BOTH_LIBRARIES} ) + +ADD_EXECUTABLE( VectorUnaryOperationsTest VectorUnaryOperationsTest.cpp ) +TARGET_COMPILE_OPTIONS( VectorUnaryOperationsTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( VectorUnaryOperationsTest ${GTEST_BOTH_LIBRARIES} ) + +ADD_EXECUTABLE( VectorVerticalOperationsTest VectorVerticalOperationsTest.cpp ) +TARGET_COMPILE_OPTIONS( VectorVerticalOperationsTest PRIVATE ${CXX_TESTS_FLAGS} ) +TARGET_LINK_LIBRARIES( VectorVerticalOperationsTest ${GTEST_BOTH_LIBRARIES} ) IF( BUILD_CUDA ) CUDA_ADD_EXECUTABLE( ArrayTestCuda ArrayTest.cu @@ -49,18 +53,21 @@ IF( BUILD_CUDA ) OPTIONS ${CXX_TESTS_FLAGS} ) TARGET_LINK_LIBRARIES( ArrayViewTestCuda ${GTEST_BOTH_LIBRARIES} ) - CUDA_ADD_EXECUTABLE( VectorTestCuda-1 VectorTest-1.cu OPTIONS ${CXX_TESTS_FLAGS} ) - CUDA_ADD_EXECUTABLE( VectorTestCuda-2 VectorTest-2.cu OPTIONS ${CXX_TESTS_FLAGS} ) - CUDA_ADD_EXECUTABLE( VectorTestCuda-3 VectorTest-3.cu OPTIONS ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( VectorTestCuda-1 ${GTEST_BOTH_LIBRARIES} ) - TARGET_LINK_LIBRARIES( VectorTestCuda-2 ${GTEST_BOTH_LIBRARIES} ) - TARGET_LINK_LIBRARIES( VectorTestCuda-3 ${GTEST_BOTH_LIBRARIES} ) + CUDA_ADD_EXECUTABLE( VectorTestCuda VectorTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) + CUDA_ADD_EXECUTABLE( VectorPrefixSumTestCuda VectorPrefixSumTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) + CUDA_ADD_EXECUTABLE( VectorEvaluateAndReduceTestCuda VectorEvaluateAndReduceTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( VectorTestCuda ${GTEST_BOTH_LIBRARIES} ) + TARGET_LINK_LIBRARIES( VectorPrefixSumTestCuda ${GTEST_BOTH_LIBRARIES} ) + TARGET_LINK_LIBRARIES( VectorEvaluateAndReduceTestCuda ${GTEST_BOTH_LIBRARIES} ) - CUDA_ADD_EXECUTABLE( BinaryVectorOperationsTestCuda VectorBinaryOperationsTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( BinaryVectorOperationsTestCuda ${GTEST_BOTH_LIBRARIES} ) + CUDA_ADD_EXECUTABLE( VectorBinaryOperationsTestCuda VectorBinaryOperationsTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( VectorBinaryOperationsTestCuda ${GTEST_BOTH_LIBRARIES} ) - CUDA_ADD_EXECUTABLE( UnaryVectorOperationsTestCuda VectorUnaryOperationsTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( UnaryVectorOperationsTestCuda ${GTEST_BOTH_LIBRARIES} ) + CUDA_ADD_EXECUTABLE( VectorUnaryOperationsTestCuda VectorUnaryOperationsTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( VectorUnaryOperationsTestCuda ${GTEST_BOTH_LIBRARIES} ) + + CUDA_ADD_EXECUTABLE( VectorVerticalOperationsTestCuda VectorVerticalOperationsTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( VectorVerticalOperationsTestCuda ${GTEST_BOTH_LIBRARIES} ) ENDIF( BUILD_CUDA ) IF( BUILD_CUDA ) @@ -90,19 +97,21 @@ ADD_TEST( ListTest ${EXECUTABLE_OUTPUT_PATH}/ListTest${CMAKE_EXECUTABLE_SUFFIX} ADD_TEST( ArrayOperationsTest ${EXECUTABLE_OUTPUT_PATH}/ArrayOperationsTest${CMAKE_EXECUTABLE_SUFFIX} ) ADD_TEST( ArrayTest ${EXECUTABLE_OUTPUT_PATH}/ArrayTest${CMAKE_EXECUTABLE_SUFFIX} ) ADD_TEST( ArrayViewTest ${EXECUTABLE_OUTPUT_PATH}/ArrayViewTest${CMAKE_EXECUTABLE_SUFFIX} ) -ADD_TEST( VectorTest-1 ${EXECUTABLE_OUTPUT_PATH}/VectorTest-1${CMAKE_EXECUTABLE_SUFFIX} ) -ADD_TEST( VectorTest-2 ${EXECUTABLE_OUTPUT_PATH}/VectorTest-2${CMAKE_EXECUTABLE_SUFFIX} ) -ADD_TEST( VectorTest-3 ${EXECUTABLE_OUTPUT_PATH}/VectorTest-3${CMAKE_EXECUTABLE_SUFFIX} ) -ADD_TEST( BinaryVectorOperationsTest ${EXECUTABLE_OUTPUT_PATH}/BinaryVectorOperationsTest${CMAKE_EXECUTABLE_SUFFIX} ) -ADD_TEST( UnaryVectorOperationsTest ${EXECUTABLE_OUTPUT_PATH}/UnaryVectorOperationsTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( VectorTest ${EXECUTABLE_OUTPUT_PATH}/VectorTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( VectorPrefixSumTest ${EXECUTABLE_OUTPUT_PATH}/VectorPrefixSumTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( VectorEvaluateAndReduceTest ${EXECUTABLE_OUTPUT_PATH}/VectorEvaluateAndReduceTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( VectorBinaryOperationsTest ${EXECUTABLE_OUTPUT_PATH}/VectorBinaryOperationsTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( VectorUnaryOperationsTest ${EXECUTABLE_OUTPUT_PATH}/VectorUnaryOperationsTest${CMAKE_EXECUTABLE_SUFFIX} ) +ADD_TEST( VectorVerticalOperationsTest ${EXECUTABLE_OUTPUT_PATH}/VectorVerticalOperationsTest${CMAKE_EXECUTABLE_SUFFIX} ) IF( BUILD_CUDA ) ADD_TEST( ArrayTestCuda ${EXECUTABLE_OUTPUT_PATH}/ArrayTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) ADD_TEST( ArrayViewTestCuda ${EXECUTABLE_OUTPUT_PATH}/ArrayViewTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) - ADD_TEST( VectorTestCuda-1 ${EXECUTABLE_OUTPUT_PATH}/VectorTestCuda-1${CMAKE_EXECUTABLE_SUFFIX} ) - ADD_TEST( VectorTestCuda-2 ${EXECUTABLE_OUTPUT_PATH}/VectorTestCuda-2${CMAKE_EXECUTABLE_SUFFIX} ) - ADD_TEST( VectorTestCuda-3 ${EXECUTABLE_OUTPUT_PATH}/VectorTestCuda-3${CMAKE_EXECUTABLE_SUFFIX} ) - ADD_TEST( BinaryVectorOperationsTestCuda ${EXECUTABLE_OUTPUT_PATH}/BinaryVectorOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) - ADD_TEST( UnaryVectorOperationsTestCuda ${EXECUTABLE_OUTPUT_PATH}/UnaryVectorOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) + ADD_TEST( VectorTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) + ADD_TEST( VectorPrefixSumTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorPrefixSumTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) + ADD_TEST( VectorEvaluateAndReduceTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorEvaluateAndReduceTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) + ADD_TEST( VectorBinaryOperationsTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorBinaryOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) + ADD_TEST( VectorUnaryOperationsTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorUnaryOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) + ADD_TEST( VectorVerticalOperationsTestCuda ${EXECUTABLE_OUTPUT_PATH}/VectorVerticalOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX} ) ENDIF() ADD_TEST( MultireductionTest ${EXECUTABLE_OUTPUT_PATH}/MultireductionTest${CMAKE_EXECUTABLE_SUFFIX} ) ADD_TEST( StaticArrayTest ${EXECUTABLE_OUTPUT_PATH}/StaticArrayTest${CMAKE_EXECUTABLE_SUFFIX} ) @@ -118,23 +127,71 @@ if( ${BUILD_MPI} ) CUDA_ADD_EXECUTABLE( DistributedArrayTest DistributedArrayTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) TARGET_LINK_LIBRARIES( DistributedArrayTest ${GTEST_BOTH_LIBRARIES} ) - - CUDA_ADD_EXECUTABLE( DistributedVectorTest DistributedVectorTest.cu - OPTIONS ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( DistributedVectorTest ${GTEST_BOTH_LIBRARIES} ) else() ADD_EXECUTABLE( DistributedArrayTest DistributedArrayTest.cpp ) TARGET_COMPILE_OPTIONS( DistributedArrayTest PRIVATE ${CXX_TESTS_FLAGS} ) TARGET_LINK_LIBRARIES( DistributedArrayTest ${GTEST_BOTH_LIBRARIES} ) + endif() + + ADD_EXECUTABLE( DistributedVectorTest DistributedVectorTest.cpp ) + TARGET_COMPILE_OPTIONS( DistributedVectorTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorTest ${GTEST_BOTH_LIBRARIES} ) - ADD_EXECUTABLE( DistributedVectorTest DistributedVectorTest.cpp ) - TARGET_COMPILE_OPTIONS( DistributedVectorTest PRIVATE ${CXX_TESTS_FLAGS} ) - TARGET_LINK_LIBRARIES( DistributedVectorTest ${GTEST_BOTH_LIBRARIES} ) + if( BUILD_CUDA ) + CUDA_ADD_EXECUTABLE( DistributedVectorTestCuda DistributedVectorTest.cu + OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorTestCuda ${GTEST_BOTH_LIBRARIES} ) endif() + ADD_EXECUTABLE( DistributedVectorBinaryOperationsTest DistributedVectorBinaryOperationsTest.cpp ) + TARGET_COMPILE_OPTIONS( DistributedVectorBinaryOperationsTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorBinaryOperationsTest ${GTEST_BOTH_LIBRARIES} ) + + ADD_EXECUTABLE( DistributedVectorUnaryOperationsTest DistributedVectorUnaryOperationsTest.cpp ) + TARGET_COMPILE_OPTIONS( DistributedVectorUnaryOperationsTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorUnaryOperationsTest ${GTEST_BOTH_LIBRARIES} ) + + ADD_EXECUTABLE( DistributedVectorVerticalOperationsTest DistributedVectorVerticalOperationsTest.cpp ) + TARGET_COMPILE_OPTIONS( DistributedVectorVerticalOperationsTest PRIVATE ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorVerticalOperationsTest ${GTEST_BOTH_LIBRARIES} ) + + if( BUILD_CUDA ) + CUDA_ADD_EXECUTABLE( DistributedVectorBinaryOperationsTestCuda DistributedVectorBinaryOperationsTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorBinaryOperationsTestCuda ${GTEST_BOTH_LIBRARIES} ) + + CUDA_ADD_EXECUTABLE( DistributedVectorUnaryOperationsTestCuda DistributedVectorUnaryOperationsTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorUnaryOperationsTestCuda ${GTEST_BOTH_LIBRARIES} ) + + CUDA_ADD_EXECUTABLE( DistributedVectorVerticalOperationsTestCuda DistributedVectorVerticalOperationsTest.cu OPTIONS ${CXX_TESTS_FLAGS} ) + TARGET_LINK_LIBRARIES( DistributedVectorVerticalOperationsTestCuda ${GTEST_BOTH_LIBRARIES} ) + endif( BUILD_CUDA ) + SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedArrayTest${CMAKE_EXECUTABLE_SUFFIX}" ) ADD_TEST( NAME DistributedArrayTest COMMAND "mpirun" ${mpi_test_parameters}) SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedVectorTest${CMAKE_EXECUTABLE_SUFFIX}" ) ADD_TEST( NAME DistributedVectorTest COMMAND "mpirun" ${mpi_test_parameters}) + + SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedVectorBinaryOperationsTest${CMAKE_EXECUTABLE_SUFFIX}" ) + ADD_TEST( NAME DistributedVectorBinaryOperationsTest COMMAND "mpirun" ${mpi_test_parameters}) + + SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedVectorUnaryOperationsTest${CMAKE_EXECUTABLE_SUFFIX}" ) + ADD_TEST( NAME DistributedVectorUnaryOperationsTest COMMAND "mpirun" ${mpi_test_parameters}) + + SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedVectorVerticalOperationsTest${CMAKE_EXECUTABLE_SUFFIX}" ) + ADD_TEST( NAME DistributedVectorVerticalOperationsTest COMMAND "mpirun" ${mpi_test_parameters}) + + if( BUILD_CUDA ) + SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedVectorTestCuda${CMAKE_EXECUTABLE_SUFFIX}" ) + ADD_TEST( NAME DistributedVectorTestCuda COMMAND "mpirun" ${mpi_test_parameters}) + + SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedVectorBinaryOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX}" ) + ADD_TEST( NAME DistributedVectorBinaryOperationsTestCuda COMMAND "mpirun" ${mpi_test_parameters}) + + SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedVectorUnaryOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX}" ) + ADD_TEST( NAME DistributedVectorUnaryOperationsTestCuda COMMAND "mpirun" ${mpi_test_parameters}) + + SET( mpi_test_parameters -np 4 -H localhost:4 "${EXECUTABLE_OUTPUT_PATH}/DistributedVectorVerticalOperationsTestCuda${CMAKE_EXECUTABLE_SUFFIX}" ) + ADD_TEST( NAME DistributedVectorVerticalOperationsTestCuda COMMAND "mpirun" ${mpi_test_parameters}) + endif() endif() diff --git a/src/UnitTests/Containers/DistributedArrayTest.h b/src/UnitTests/Containers/DistributedArrayTest.h index 24fd79c618d3652dbab4f73f5d75534d825abfec..851bd95811b74dbd8ad809d4e06d922dff672d58 100644 --- a/src/UnitTests/Containers/DistributedArrayTest.h +++ b/src/UnitTests/Containers/DistributedArrayTest.h @@ -34,8 +34,8 @@ protected: using CommunicatorType = typename DistributedArray::CommunicatorType; using IndexType = typename DistributedArray::IndexType; using DistributedArrayType = DistributedArray; - using ArrayViewType = typename DistributedArrayType::LocalArrayViewType; - using ArrayType = typename DistributedArrayType::LocalArrayType; + using ArrayViewType = typename DistributedArrayType::LocalViewType; + using ArrayType = Array< typename ArrayViewType::ValueType, typename ArrayViewType::DeviceType, typename ArrayViewType::IndexType >; const int globalSize = 97; // prime number to force non-uniform distribution @@ -74,7 +74,7 @@ TYPED_TEST( DistributedArrayTest, checkSumOfLocalSizes ) { using CommunicatorType = typename TestFixture::CommunicatorType; - const int localSize = this->distributedArray.getLocalArrayView().getSize(); + const int localSize = this->distributedArray.getLocalView().getSize(); int sumOfLocalSizes = 0; CommunicatorType::Allreduce( &localSize, &sumOfLocalSizes, 1, MPI_SUM, this->group ); EXPECT_EQ( sumOfLocalSizes, this->globalSize ); @@ -91,7 +91,7 @@ TYPED_TEST( DistributedArrayTest, copyFromGlobal ) globalArray.setValue( 1.0 ); this->distributedArray.copyFromGlobal( globalArray ); - ArrayViewType localArrayView = this->distributedArray.getLocalArrayView(); + ArrayViewType localArrayView = this->distributedArray.getLocalView(); auto globalView = globalArray.getConstView(); const auto localRange = this->distributedArray.getLocalRange(); globalView.bind( &globalArray[ localRange.getBegin() ], localRange.getEnd() - localRange.getBegin() ); @@ -112,10 +112,10 @@ TYPED_TEST( DistributedArrayTest, setLike ) TYPED_TEST( DistributedArrayTest, reset ) { EXPECT_EQ( this->distributedArray.getSize(), this->globalSize ); - EXPECT_GT( this->distributedArray.getLocalArrayView().getSize(), 0 ); + EXPECT_GT( this->distributedArray.getLocalView().getSize(), 0 ); this->distributedArray.reset(); EXPECT_EQ( this->distributedArray.getSize(), 0 ); - EXPECT_EQ( this->distributedArray.getLocalArrayView().getSize(), 0 ); + EXPECT_EQ( this->distributedArray.getLocalView().getSize(), 0 ); } // TODO: swap @@ -126,7 +126,7 @@ TYPED_TEST( DistributedArrayTest, setValue ) using ArrayType = typename TestFixture::ArrayType; this->distributedArray.setValue( 1.0 ); - ArrayViewType localArrayView = this->distributedArray.getLocalArrayView(); + ArrayViewType localArrayView = this->distributedArray.getLocalView(); ArrayType expected( localArrayView.getSize() ); expected.setValue( 1.0 ); EXPECT_EQ( localArrayView, expected ); @@ -138,7 +138,7 @@ TYPED_TEST( DistributedArrayTest, elementwiseAccess ) using IndexType = typename TestFixture::IndexType; this->distributedArray.setValue( 0 ); - ArrayViewType localArrayView = this->distributedArray.getLocalArrayView(); + ArrayViewType localArrayView = this->distributedArray.getLocalView(); const auto localRange = this->distributedArray.getLocalRange(); // check initial value @@ -191,7 +191,7 @@ TYPED_TEST( DistributedArrayTest, copyConstructor ) this->distributedArray.setValue( 1 ); DistributedArrayType copy( this->distributedArray ); // Array has "binding" copy-constructor - //EXPECT_EQ( copy.getLocalArrayView().getData(), this->distributedArray.getLocalArrayView().getData() ); + //EXPECT_EQ( copy.getLocalView().getData(), this->distributedArray.getLocalView().getData() ); } TYPED_TEST( DistributedArrayTest, copyAssignment ) @@ -202,8 +202,8 @@ TYPED_TEST( DistributedArrayTest, copyAssignment ) DistributedArrayType copy; copy = this->distributedArray; // no binding, but deep copy - EXPECT_NE( copy.getLocalArrayView().getData(), this->distributedArray.getLocalArrayView().getData() ); - EXPECT_EQ( copy.getLocalArrayView(), this->distributedArray.getLocalArrayView() ); + EXPECT_NE( copy.getLocalView().getData(), this->distributedArray.getLocalView().getData() ); + EXPECT_EQ( copy.getLocalView(), this->distributedArray.getLocalView() ); } TYPED_TEST( DistributedArrayTest, comparisonOperators ) @@ -217,7 +217,7 @@ TYPED_TEST( DistributedArrayTest, comparisonOperators ) v.setLike( u ); w.setLike( u ); - for( int i = 0; i < u.getLocalArrayView().getSize(); i ++ ) { + for( int i = 0; i < u.getLocalView().getSize(); i ++ ) { const IndexType gi = localRange.getGlobalIndex( i ); u.setElement( gi, i ); v.setElement( gi, i ); @@ -246,7 +246,7 @@ TYPED_TEST( DistributedArrayTest, containsValue ) const auto localRange = this->distributedArray.getLocalRange(); - for( int i = 0; i < this->distributedArray.getLocalArrayView().getSize(); i++ ) { + for( int i = 0; i < this->distributedArray.getLocalView().getSize(); i++ ) { const IndexType gi = localRange.getGlobalIndex( i ); this->distributedArray.setElement( gi, i % 10 ); } @@ -264,7 +264,7 @@ TYPED_TEST( DistributedArrayTest, containsOnlyValue ) const auto localRange = this->distributedArray.getLocalRange(); - for( int i = 0; i < this->distributedArray.getLocalArrayView().getSize(); i++ ) { + for( int i = 0; i < this->distributedArray.getLocalView().getSize(); i++ ) { const IndexType gi = localRange.getGlobalIndex( i ); this->distributedArray.setElement( gi, i % 10 ); } diff --git a/src/UnitTests/Containers/DistributedVectorBinaryOperationsTest.cpp b/src/UnitTests/Containers/DistributedVectorBinaryOperationsTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1798a42f0795ad23b136884919e31e05d876ebf --- /dev/null +++ b/src/UnitTests/Containers/DistributedVectorBinaryOperationsTest.cpp @@ -0,0 +1 @@ +#include "DistributedVectorBinaryOperationsTest.h" diff --git a/src/UnitTests/Containers/DistributedVectorBinaryOperationsTest.cu b/src/UnitTests/Containers/DistributedVectorBinaryOperationsTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..a1798a42f0795ad23b136884919e31e05d876ebf --- /dev/null +++ b/src/UnitTests/Containers/DistributedVectorBinaryOperationsTest.cu @@ -0,0 +1 @@ +#include "DistributedVectorBinaryOperationsTest.h" diff --git a/src/UnitTests/Containers/DistributedVectorBinaryOperationsTest.h b/src/UnitTests/Containers/DistributedVectorBinaryOperationsTest.h new file mode 100644 index 0000000000000000000000000000000000000000..1a89432e0a0911c48adde21e44f5a912f16b1802 --- /dev/null +++ b/src/UnitTests/Containers/DistributedVectorBinaryOperationsTest.h @@ -0,0 +1,3 @@ +#define DISTRIBUTED_VECTOR +#include "VectorBinaryOperationsTest.h" +#include "../main_mpi.h" diff --git a/src/UnitTests/Containers/DistributedVectorTest.h b/src/UnitTests/Containers/DistributedVectorTest.h index b9bced064f530e7123cc0bb0a2ec2011f598965e..e2d07a02aaf2958cc4c2b410c8670a2ac8294650 100644 --- a/src/UnitTests/Containers/DistributedVectorTest.h +++ b/src/UnitTests/Containers/DistributedVectorTest.h @@ -6,37 +6,6 @@ email : tomas.oberhuber@fjfi.cvut.cz ***************************************************************************/ -template< typename Vector > -void setLinearSequence( Vector& deviceVector ) -{ - typename Vector::HostType a; - a.setLike( deviceVector ); - for( int i = 0; i < a.getLocalVectorView().getSize(); i++ ) { - const auto gi = a.getLocalRange().getGlobalIndex( i ); - a[ gi ] = gi; - } - deviceVector = a; -} - -template< typename Vector > -void setConstantSequence( Vector& deviceVector, - typename Vector::RealType v ) -{ - deviceVector.setValue( v ); -} - -template< typename Vector > -void setNegativeLinearSequence( Vector& deviceVector ) -{ - typename Vector::HostType a; - a.setLike( deviceVector ); - for( int i = 0; i < a.getLocalVectorView().getSize(); i++ ) { - const auto gi = a.getLocalRange().getGlobalIndex( i ); - a[ gi ] = -gi; - } - deviceVector = a; -} - #ifdef HAVE_GTEST #include @@ -48,6 +17,9 @@ void setNegativeLinearSequence( Vector& deviceVector ) #include #include +#define DISTRIBUTED_VECTOR +#include "VectorHelperFunctions.h" + using namespace TNL; using namespace TNL::Containers; @@ -68,7 +40,7 @@ protected: using CommunicatorType = typename DistributedVector::CommunicatorType; using IndexType = typename DistributedVector::IndexType; using DistributedVectorType = DistributedVector; - using VectorViewType = typename DistributedVectorType::LocalVectorViewType; + using VectorViewType = typename DistributedVectorType::LocalViewType; using DistributedVectorView = Containers::DistributedVectorView< RealType, DeviceType, IndexType, CommunicatorType >; const int globalSize = 97; // prime number to force non-uniform distribution @@ -113,238 +85,6 @@ using DistributedVectorTypes = ::testing::Types< TYPED_TEST_SUITE( DistributedVectorTest, DistributedVectorTypes ); -TYPED_TEST( DistributedVectorTest, max ) -{ - EXPECT_EQ( max( this->x ), 1 ); - EXPECT_EQ( max( this->y ), this->globalSize - 1 ); - EXPECT_EQ( max( this->z ), 0 ); - - EXPECT_EQ( max( this->x_view ), 1 ); - EXPECT_EQ( max( this->y_view ), this->globalSize - 1 ); - EXPECT_EQ( max( this->z_view ), 0 ); -} - -TYPED_TEST( DistributedVectorTest, min ) -{ - EXPECT_EQ( min( this->x ), 1 ); - EXPECT_EQ( min( this->y ), 0 ); - EXPECT_EQ( min( this->z ), 1 - this->globalSize ); - - EXPECT_EQ( min( this->x_view ), 1 ); - EXPECT_EQ( min( this->y_view ), 0 ); - EXPECT_EQ( min( this->z_view ), 1 - this->globalSize ); -} - -TYPED_TEST( DistributedVectorTest, absMax ) -{ - - EXPECT_EQ( max( abs( this->x ) ), 1 ); - EXPECT_EQ( max( abs( this->y ) ), this->globalSize - 1 ); - EXPECT_EQ( max( abs( this->z ) ), this->globalSize - 1 ); - - EXPECT_EQ( max( abs( this->x_view ) ), 1 ); - EXPECT_EQ( max( abs( this->y_view ) ), this->globalSize - 1 ); - EXPECT_EQ( max( abs( this->z_view ) ), this->globalSize - 1 ); -} - -TYPED_TEST( DistributedVectorTest, absMin ) -{ - EXPECT_EQ( min( abs( this->x ) ), 1 ); - EXPECT_EQ( min( abs( this->y ) ), 0 ); - EXPECT_EQ( min( abs( this->z ) ), 0 ); - - EXPECT_EQ( min( abs( this->x_view ) ), 1 ); - EXPECT_EQ( min( abs( this->y_view ) ), 0 ); - EXPECT_EQ( min( abs( this->z_view ) ), 0 ); -} - -TYPED_TEST( DistributedVectorTest, lpNorm ) -{ - using RealType = typename TestFixture::RealType; - - const RealType epsilon = 64 * std::numeric_limits< RealType >::epsilon(); - const RealType expectedL1norm = this->globalSize; - const RealType expectedL2norm = std::sqrt( this->globalSize ); - const RealType expectedL3norm = std::cbrt( this->globalSize ); - - EXPECT_EQ( lpNorm( this->x , 1.0 ), expectedL1norm ); - EXPECT_EQ( lpNorm( this->x, 2.0 ), expectedL2norm ); - EXPECT_NEAR( lpNorm( this->x, 3.0 ), expectedL3norm, epsilon ); - - EXPECT_EQ( lpNorm( this->x_view, 1.0 ), expectedL1norm ); - EXPECT_EQ( lpNorm( this->x_view, 2.0 ), expectedL2norm ); - EXPECT_NEAR( lpNorm( this->x_view, 3.0 ), expectedL3norm, epsilon ); -} - -TYPED_TEST( DistributedVectorTest, sum ) -{ - EXPECT_EQ( sum( this->x ), this->globalSize ); - EXPECT_EQ( sum( this->y ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - EXPECT_EQ( sum( this->z ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - - EXPECT_EQ( sum( this->x_view ), this->globalSize ); - EXPECT_EQ( sum( this->y_view ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - EXPECT_EQ( sum( this->z_view ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); -} - -TYPED_TEST( DistributedVectorTest, differenceMax ) -{ - EXPECT_TRUE( max( this->x - this->y ) == 1 ); - EXPECT_TRUE( max( this->y - this->x ) == this->globalSize - 2 ); - - EXPECT_EQ( max( this->x_view - this->y_view ), 1 ); - EXPECT_EQ( max( this->y_view - this->x_view ), this->globalSize - 2 ); -} - -TYPED_TEST( DistributedVectorTest, differenceMin ) -{ - EXPECT_EQ( min( this->x - this->y ), 2 - this->globalSize ); - EXPECT_EQ( min( this->y - this->x ), -1 ); - - EXPECT_EQ( min( this->x_view - this->y_view ), 2 - this->globalSize ); - EXPECT_EQ( min( this->y_view - this->x_view ), -1 ); -} - -TYPED_TEST( DistributedVectorTest, differenceAbsMax ) -{ - EXPECT_EQ( max( abs( this->x - this->y ) ), this->globalSize - 2 ); - EXPECT_EQ( max( abs( this->y - this->x ) ), this->globalSize - 2 ); - - EXPECT_EQ( max( abs( this->x_view - this->y_view ) ), this->globalSize - 2 ); - EXPECT_EQ( max( abs( this->y_view - this->x_view ) ), this->globalSize - 2 ); -} - -TYPED_TEST( DistributedVectorTest, differenceAbsMin ) -{ - EXPECT_EQ( min( abs( this->x - this->y ) ), 0 ); - EXPECT_EQ( min( abs( this->y - this->x ) ), 0 ); - - EXPECT_EQ( min( abs( this->x_view - this->y_view ) ), 0 ); - EXPECT_EQ( min( abs( this->y_view - this->x_view ) ), 0 ); -} - -TYPED_TEST( DistributedVectorTest, differenceLpNorm ) -{ - using RealType = typename TestFixture::RealType; - - this->x.setValue( 2 ); - this->y.setValue( 1 ); - const RealType epsilon = 64 * std::numeric_limits< RealType >::epsilon(); - const RealType expectedL1norm = this->globalSize; - const RealType expectedL2norm = std::sqrt( this->globalSize ); - const RealType expectedL3norm = std::cbrt( this->globalSize ); - - EXPECT_EQ( lpNorm( this->x - this->y, 1.0 ), expectedL1norm ); - EXPECT_EQ( lpNorm( this->x - this->y, 2.0 ), expectedL2norm ); - EXPECT_NEAR( lpNorm( this->x - this->y, 3.0 ), expectedL3norm, epsilon ); - - EXPECT_EQ( lpNorm( this->x_view - this->y_view, 1.0 ), expectedL1norm ); - EXPECT_EQ( lpNorm( this->x_view - this->y_view, 2.0 ), expectedL2norm ); - EXPECT_NEAR( lpNorm( this->x_view - this->y_view, 3.0 ), expectedL3norm, epsilon ); -} - -TYPED_TEST( DistributedVectorTest, differenceSum ) -{ - EXPECT_EQ( TNL::sum( this->x - this->x ), 0 ); - EXPECT_EQ( TNL::sum( this->y - this->x ), 0.5 * this->globalSize * ( this->globalSize - 1 ) - this->globalSize ); - EXPECT_EQ( TNL::sum( this->y - this->y ), 0 ); - - EXPECT_EQ( TNL::sum( this->x_view - this->x_view ), 0 ); - EXPECT_EQ( TNL::sum( this->y_view - this->x_view ), 0.5 * this->globalSize * ( this->globalSize - 1 ) - this->globalSize ); - EXPECT_EQ( TNL::sum( this->y_view - this->y_view ), 0 ); -} - -/*TYPED_TEST( DistributedVectorTest, scalarMultiplication ) -{ - this->y *= 2; - for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->y.getElement( gi ), 2 * gi ); - } - - this->y.scalarMultiplication( 2 ); - for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->y.getElement( gi ), 4 * gi ); - } - - setLinearSequence( this->y ); - - this->y_view *= 2; - for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->y_view.getElement( gi ), 2 * gi ); - } - - this->y_view.scalarMultiplication( 2 ); - for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->y_view.getElement( gi ), 4 * gi ); - } -}*/ - -TYPED_TEST( DistributedVectorTest, scalarProduct ) -{ - EXPECT_EQ( this->x.scalarProduct( this->x ), this->globalSize ); - EXPECT_EQ( this->x.scalarProduct( this->y ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - EXPECT_EQ( this->y.scalarProduct( this->x ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - EXPECT_EQ( this->x.scalarProduct( this->z ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - EXPECT_EQ( this->z.scalarProduct( this->x ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - - EXPECT_EQ( this->x_view.scalarProduct( this->x_view ), this->globalSize ); - EXPECT_EQ( this->x_view.scalarProduct( this->y_view ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - EXPECT_EQ( this->y_view.scalarProduct( this->x_view ), 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - EXPECT_EQ( this->x_view.scalarProduct( this->z_view ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); - EXPECT_EQ( this->z_view.scalarProduct( this->x_view ), - 0.5 * this->globalSize * ( this->globalSize - 1 ) ); -} - -TYPED_TEST( DistributedVectorTest, addVector ) -{ - this->x.addVector( this->y, 3.0, 1.0 ); - for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->x.getElement( gi ), 1 + 3 * gi ); - } - - this->y += this->z; - for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->y.getElement( gi ), 0 ); - } - - setConstantSequence( this->x, 1 ); - setLinearSequence( this->y ); - - this->x_view.addVector( this->y_view, 3.0, 1.0 ); - for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->x_view.getElement( gi ), 1 + 3 * gi ); - } - - this->y_view += this->z_view; - for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->y_view.getElement( gi ), 0 ); - } -} - -TYPED_TEST( DistributedVectorTest, addVectors ) -{ - this->x.addVectors( this->y, 3.0, this->z, 1.0, 2.0 ); - for( int i = 0; i < this->y.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->x.getElement( gi ), 2 + 3 * gi - gi ); - } - - setConstantSequence( this->x, 1 ); - - this->x_view.addVectors( this->y_view, 3.0, this->z_view, 1.0, 2.0 ); - for( int i = 0; i < this->y_view.getLocalVectorView().getSize(); i++ ) { - const auto gi = this->y_view.getLocalRange().getGlobalIndex( i ); - EXPECT_EQ( this->x_view.getElement( gi ), 2 + 3 * gi - gi ); - } -} - // TODO: distributed prefix sum #endif // HAVE_GTEST diff --git a/src/UnitTests/Containers/DistributedVectorUnaryOperationsTest.cpp b/src/UnitTests/Containers/DistributedVectorUnaryOperationsTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..304f99c47d4243596a3ed0166528d2b0a2c74a44 --- /dev/null +++ b/src/UnitTests/Containers/DistributedVectorUnaryOperationsTest.cpp @@ -0,0 +1 @@ +#include "DistributedVectorUnaryOperationsTest.h" diff --git a/src/UnitTests/Containers/DistributedVectorUnaryOperationsTest.cu b/src/UnitTests/Containers/DistributedVectorUnaryOperationsTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..304f99c47d4243596a3ed0166528d2b0a2c74a44 --- /dev/null +++ b/src/UnitTests/Containers/DistributedVectorUnaryOperationsTest.cu @@ -0,0 +1 @@ +#include "DistributedVectorUnaryOperationsTest.h" diff --git a/src/UnitTests/Containers/DistributedVectorUnaryOperationsTest.h b/src/UnitTests/Containers/DistributedVectorUnaryOperationsTest.h new file mode 100644 index 0000000000000000000000000000000000000000..60f781d1541420f579643489b947cc62904b88fa --- /dev/null +++ b/src/UnitTests/Containers/DistributedVectorUnaryOperationsTest.h @@ -0,0 +1,3 @@ +#define DISTRIBUTED_VECTOR +#include "VectorUnaryOperationsTest.h" +#include "../main_mpi.h" diff --git a/src/UnitTests/Containers/DistributedVectorVerticalOperationsTest.cpp b/src/UnitTests/Containers/DistributedVectorVerticalOperationsTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..868d3fe3b708bdc8fd26e510c6cf6e020608f1d5 --- /dev/null +++ b/src/UnitTests/Containers/DistributedVectorVerticalOperationsTest.cpp @@ -0,0 +1 @@ +#include "DistributedVectorVerticalOperationsTest.h" diff --git a/src/UnitTests/Containers/DistributedVectorVerticalOperationsTest.cu b/src/UnitTests/Containers/DistributedVectorVerticalOperationsTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..868d3fe3b708bdc8fd26e510c6cf6e020608f1d5 --- /dev/null +++ b/src/UnitTests/Containers/DistributedVectorVerticalOperationsTest.cu @@ -0,0 +1 @@ +#include "DistributedVectorVerticalOperationsTest.h" diff --git a/src/UnitTests/Containers/DistributedVectorVerticalOperationsTest.h b/src/UnitTests/Containers/DistributedVectorVerticalOperationsTest.h new file mode 100644 index 0000000000000000000000000000000000000000..2ac1596bbd8905618825fd256e4d975478a3ccd0 --- /dev/null +++ b/src/UnitTests/Containers/DistributedVectorVerticalOperationsTest.h @@ -0,0 +1,3 @@ +#define DISTRIBUTED_VECTOR +#include "VectorVerticalOperationsTest.h" +#include "../main_mpi.h" diff --git a/src/UnitTests/Containers/ListTest.cpp b/src/UnitTests/Containers/ListTest.cpp index 8330e5268a3ddc6adfa6a20db1137595c542fd83..f24e650b43b681dc82b9571800e0c3201b202504 100644 --- a/src/UnitTests/Containers/ListTest.cpp +++ b/src/UnitTests/Containers/ListTest.cpp @@ -64,7 +64,7 @@ using ListTypes = ::testing::Types< List< MyData > >; -TYPED_TEST_CASE( ListTest, ListTypes ); +TYPED_TEST_SUITE( ListTest, ListTypes ); TYPED_TEST( ListTest, constructor ) diff --git a/src/UnitTests/Containers/StaticArrayTest.cpp b/src/UnitTests/Containers/StaticArrayTest.cpp index 26a50bdfe4484beea328d3dc9643e9f45236a117..a3369f02d0773d17ccdec74c783ad035b6f014c3 100644 --- a/src/UnitTests/Containers/StaticArrayTest.cpp +++ b/src/UnitTests/Containers/StaticArrayTest.cpp @@ -56,7 +56,7 @@ using StaticArrayTypes = ::testing::Types< StaticArray< 5, double > >; -TYPED_TEST_CASE( StaticArrayTest, StaticArrayTypes ); +TYPED_TEST_SUITE( StaticArrayTest, StaticArrayTypes ); TYPED_TEST( StaticArrayTest, constructors ) { diff --git a/src/UnitTests/Containers/StaticVectorOperationsTest.cpp b/src/UnitTests/Containers/StaticVectorOperationsTest.cpp index 2e4d8e4cbb9a53cc4ac38137f56c6f709fbb099e..23df06f42d6e95532b051a5a79d4d8a531ef6f07 100644 --- a/src/UnitTests/Containers/StaticVectorOperationsTest.cpp +++ b/src/UnitTests/Containers/StaticVectorOperationsTest.cpp @@ -1,4 +1,5 @@ #define STATIC_VECTOR #include "VectorBinaryOperationsTest.h" #include "VectorUnaryOperationsTest.h" +#include "VectorVerticalOperationsTest.h" #include "../main.h" diff --git a/src/UnitTests/Containers/StaticVectorTest.cpp b/src/UnitTests/Containers/StaticVectorTest.cpp index ef3aa8ddd58f50a4a0f3b8cd529f4b5ebc827f62..a2b651a8b28ab0b0b5aa10fce86e51e6fcfd14fa 100644 --- a/src/UnitTests/Containers/StaticVectorTest.cpp +++ b/src/UnitTests/Containers/StaticVectorTest.cpp @@ -54,7 +54,7 @@ using StaticVectorTypes = ::testing::Types< StaticVector< 5, double > >; -TYPED_TEST_CASE( StaticVectorTest, StaticVectorTypes ); +TYPED_TEST_SUITE( StaticVectorTest, StaticVectorTypes ); TYPED_TEST( StaticVectorTest, constructors ) diff --git a/src/UnitTests/Containers/VectorBinaryOperationsTest.h b/src/UnitTests/Containers/VectorBinaryOperationsTest.h index e276775ffc1ac5c5653ca4e3b20535417f4cbd68..8fae768849c26406ecabc08c9fcf261e686d9453 100644 --- a/src/UnitTests/Containers/VectorBinaryOperationsTest.h +++ b/src/UnitTests/Containers/VectorBinaryOperationsTest.h @@ -11,10 +11,21 @@ #pragma once #ifdef HAVE_GTEST -#include -#include -#include -#include "VectorSequenceSetupFunctions.h" + +#if defined(DISTRIBUTED_VECTOR) + #include + #include + #include + #include + #include +#elif defined(STATIC_VECTOR) + #include +#else + #include + #include +#endif + +#include "VectorHelperFunctions.h" #include "gtest/gtest.h" @@ -24,11 +35,12 @@ using namespace TNL::Containers::Algorithms; namespace binary_tests { -constexpr int VECTOR_TEST_SIZE = 100; +// prime number to force non-uniform distribution in block-wise algorithms +constexpr int VECTOR_TEST_SIZE = 97; // should be small enough to have fast tests, but larger than minGPUReductionDataSize // and large enough to require multiple CUDA blocks for reduction -constexpr int VECTOR_TEST_REDUCTION_SIZE = 5000; +constexpr int VECTOR_TEST_REDUCTION_SIZE = 4999; template< typename T1, typename T2 > struct Pair @@ -47,13 +59,124 @@ protected: #ifndef STATIC_VECTOR using LeftNonConstReal = std::remove_const_t< typename Left::RealType >; using RightNonConstReal = std::remove_const_t< typename Right::RealType >; - using LeftVector = Vector< LeftNonConstReal, typename Left::DeviceType, typename Left::IndexType >; - using RightVector = Vector< RightNonConstReal, typename Right::DeviceType, typename Right::IndexType >; + #ifdef DISTRIBUTED_VECTOR + using CommunicatorType = typename Left::CommunicatorType; + static_assert( std::is_same< typename Right::CommunicatorType, CommunicatorType >::value, + "CommunicatorType must be the same for both Left and Right vectors." ); + using LeftVector = DistributedVector< LeftNonConstReal, typename Left::DeviceType, typename Left::IndexType, CommunicatorType >; + using RightVector = DistributedVector< RightNonConstReal, typename Right::DeviceType, typename Right::IndexType, CommunicatorType >; + #else + using LeftVector = Vector< LeftNonConstReal, typename Left::DeviceType, typename Left::IndexType >; + using RightVector = Vector< RightNonConstReal, typename Right::DeviceType, typename Right::IndexType >; + #endif +#endif + + Left L1, L2; + Right R1, R2; + +#ifndef STATIC_VECTOR + LeftVector _L1, _L2; + RightVector _R1, _R2; #endif + + void reset( int size ) + { +#ifdef STATIC_VECTOR + L1 = 1; + L2 = 2; + R1 = 1; + R2 = 2; +#else + #ifdef DISTRIBUTED_VECTOR + const typename CommunicatorType::CommunicationGroup group = CommunicatorType::AllGroup; + using LocalRangeType = typename LeftVector::LocalRangeType; + const LocalRangeType localRange = Partitioner< typename Left::IndexType, CommunicatorType >::splitRange( size, group ); + + const int rank = CommunicatorType::GetRank(group); + const int nproc = CommunicatorType::GetSize(group); + + _L1.setDistribution( localRange, size, group ); + _L2.setDistribution( localRange, size, group ); + _R1.setDistribution( localRange, size, group ); + _R2.setDistribution( localRange, size, group ); + #else + _L1.setSize( size ); + _L2.setSize( size ); + _R1.setSize( size ); + _R2.setSize( size ); + #endif + _L1 = 1; + _L2 = 2; + _R1 = 1; + _R2 = 2; + bindOrAssign( L1, _L1 ); + bindOrAssign( L2, _L2 ); + bindOrAssign( R1, _R1 ); + bindOrAssign( R2, _R2 ); +#endif + } + + VectorBinaryOperationsTest() + { + reset( VECTOR_TEST_SIZE ); + } }; +#ifdef HAVE_CUDA + // ignore useless nvcc warning: https://stackoverflow.com/a/49997636 + #pragma push + #pragma diag_suppress = declared_but_not_referenced +#endif + +#define SETUP_BINARY_TEST_ALIASES \ + using Left = typename TestFixture::Left; \ + using Right = typename TestFixture::Right; \ + Left& L1 = this->L1; \ + Left& L2 = this->L2; \ + Right& R1 = this->R1; \ + Right& R2 = this->R2; \ + // types for which VectorBinaryOperationsTest is instantiated -#ifdef STATIC_VECTOR +#if defined(DISTRIBUTED_VECTOR) + using VectorPairs = ::testing::Types< + #ifndef HAVE_CUDA + Pair< DistributedVector< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Host, int, Communicators::MpiCommunicator > >, + Pair< DistributedVector< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVectorView< double, Devices::Host, int, Communicators::MpiCommunicator > >, + Pair< DistributedVectorView< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Host, int, Communicators::MpiCommunicator > >, + Pair< DistributedVectorView< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVectorView< double, Devices::Host, int, Communicators::MpiCommunicator > >, + + Pair< DistributedVector< double, Devices::Host, int, Communicators::NoDistrCommunicator >, + DistributedVector< double, Devices::Host, int, Communicators::NoDistrCommunicator > >, + Pair< DistributedVector< double, Devices::Host, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< double, Devices::Host, int, Communicators::NoDistrCommunicator > >, + Pair< DistributedVectorView< double, Devices::Host, int, Communicators::NoDistrCommunicator >, + DistributedVector< double, Devices::Host, int, Communicators::NoDistrCommunicator > >, + Pair< DistributedVectorView< double, Devices::Host, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< double, Devices::Host, int, Communicators::NoDistrCommunicator > > + #else + Pair< DistributedVector< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Cuda, int, Communicators::MpiCommunicator > >, + Pair< DistributedVector< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVectorView< double, Devices::Cuda, int, Communicators::MpiCommunicator > >, + Pair< DistributedVectorView< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Cuda, int, Communicators::MpiCommunicator > >, + Pair< DistributedVectorView< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVectorView< double, Devices::Cuda, int, Communicators::MpiCommunicator > >, + Pair< DistributedVector< double, Devices::Cuda, int, Communicators::NoDistrCommunicator >, + DistributedVector< double, Devices::Cuda, int, Communicators::NoDistrCommunicator > >, + Pair< DistributedVector< double, Devices::Cuda, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< double, Devices::Cuda, int, Communicators::NoDistrCommunicator > >, + Pair< DistributedVectorView< double, Devices::Cuda, int, Communicators::NoDistrCommunicator >, + DistributedVector< double, Devices::Cuda, int, Communicators::NoDistrCommunicator > >, + Pair< DistributedVectorView< double, Devices::Cuda, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< double, Devices::Cuda, int, Communicators::NoDistrCommunicator > > + #endif + >; +#elif defined(STATIC_VECTOR) using VectorPairs = ::testing::Types< Pair< StaticVector< 1, int >, StaticVector< 1, int > >, Pair< StaticVector< 1, double >, StaticVector< 1, double > >, @@ -82,8 +205,7 @@ protected: Pair< VectorView< double, Devices::Host >, Vector< double, Devices::Host > >, Pair< Vector< double, Devices::Host >, VectorView< double, Devices::Host > >, Pair< VectorView< double, Devices::Host >, VectorView< double, Devices::Host > > - #endif - #ifdef HAVE_CUDA + #else Pair< Vector< int, Devices::Cuda >, Vector< int, Devices::Cuda > >, Pair< VectorView< int, Devices::Cuda >, Vector< int, Devices::Cuda > >, Pair< VectorView< const int, Devices::Cuda >, Vector< int, Devices::Cuda > >, @@ -103,42 +225,9 @@ protected: TYPED_TEST_SUITE( VectorBinaryOperationsTest, VectorPairs ); -#ifdef STATIC_VECTOR - #define SETUP_BINARY_VECTOR_TEST( size ) \ - using Left = typename TestFixture::Left; \ - using Right = typename TestFixture::Right; \ - \ - Left L1, L2; \ - Right R1, R2; \ - \ - L1 = 1; \ - L2 = 2; \ - R1 = 1; \ - R2 = 2; \ - -#else - #define SETUP_BINARY_VECTOR_TEST( size ) \ - using LeftVector = typename TestFixture::LeftVector; \ - using RightVector = typename TestFixture::RightVector; \ - using Left = typename TestFixture::Left; \ - using Right = typename TestFixture::Right; \ - \ - LeftVector _L1( size ), _L2( size ); \ - RightVector _R1( size ), _R2( size ); \ - \ - _L1 = 1; \ - _L2 = 2; \ - _R1 = 1; \ - _R2 = 2; \ - \ - Left L1( _L1 ), L2( _L2 ); \ - Right R1( _R1 ), R2( _R2 ); \ - -#endif - TYPED_TEST( VectorBinaryOperationsTest, EQ ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; EXPECT_EQ( L1, R1 ); // vector or vector view EXPECT_EQ( L1, 1 ); // right scalar @@ -157,7 +246,7 @@ TYPED_TEST( VectorBinaryOperationsTest, EQ ) TYPED_TEST( VectorBinaryOperationsTest, NE ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; EXPECT_NE( L1, R2 ); // vector or vector view EXPECT_NE( L1, 2 ); // right scalar @@ -176,7 +265,7 @@ TYPED_TEST( VectorBinaryOperationsTest, NE ) TYPED_TEST( VectorBinaryOperationsTest, LT ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; EXPECT_LT( L1, R2 ); // vector or vector view EXPECT_LT( L1, 2 ); // right scalar @@ -188,7 +277,7 @@ TYPED_TEST( VectorBinaryOperationsTest, LT ) TYPED_TEST( VectorBinaryOperationsTest, GT ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; EXPECT_GT( L2, R1 ); // vector or vector view EXPECT_GT( L2, 1 ); // right scalar @@ -200,7 +289,7 @@ TYPED_TEST( VectorBinaryOperationsTest, GT ) TYPED_TEST( VectorBinaryOperationsTest, LE ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; // same as LT EXPECT_LE( L1, R2 ); // vector or vector view @@ -221,7 +310,7 @@ TYPED_TEST( VectorBinaryOperationsTest, LE ) TYPED_TEST( VectorBinaryOperationsTest, GE ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; // same as GT EXPECT_GE( L2, R1 ); // vector or vector view @@ -242,7 +331,7 @@ TYPED_TEST( VectorBinaryOperationsTest, GE ) TYPED_TEST( VectorBinaryOperationsTest, addition ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; // with vector or vector view EXPECT_EQ( L1 + R1, 2 ); @@ -260,7 +349,7 @@ TYPED_TEST( VectorBinaryOperationsTest, addition ) TYPED_TEST( VectorBinaryOperationsTest, subtraction ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; // with vector or vector view EXPECT_EQ( L1 - R1, 0 ); @@ -278,7 +367,7 @@ TYPED_TEST( VectorBinaryOperationsTest, subtraction ) TYPED_TEST( VectorBinaryOperationsTest, multiplication ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; // with vector or vector view EXPECT_EQ( L1 * R2, L2 ); @@ -296,7 +385,7 @@ TYPED_TEST( VectorBinaryOperationsTest, multiplication ) TYPED_TEST( VectorBinaryOperationsTest, division ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; // with vector or vector view EXPECT_EQ( L2 / R2, L1 ); @@ -330,7 +419,7 @@ void test_assignment( Left& L1, Left& L2, Right& R1, Right& R2 ) } TYPED_TEST( VectorBinaryOperationsTest, assignment ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; test_assignment( L1, L2, R1, R2 ); } @@ -354,7 +443,7 @@ void test_add_assignment( Left& L1, Left& L2, Right& R1, Right& R2 ) } TYPED_TEST( VectorBinaryOperationsTest, add_assignment ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; test_add_assignment( L1, L2, R1, R2 ); } @@ -378,7 +467,7 @@ void test_subtract_assignment( Left& L1, Left& L2, Right& R1, Right& R2 ) } TYPED_TEST( VectorBinaryOperationsTest, subtract_assignment ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; test_subtract_assignment( L1, L2, R1, R2 ); } @@ -402,7 +491,7 @@ void test_multiply_assignment( Left& L1, Left& L2, Right& R1, Right& R2 ) } TYPED_TEST( VectorBinaryOperationsTest, multiply_assignment ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; test_multiply_assignment( L1, L2, R1, R2 ); } @@ -426,29 +515,27 @@ void test_divide_assignment( Left& L1, Left& L2, Right& R1, Right& R2 ) } TYPED_TEST( VectorBinaryOperationsTest, divide_assignment ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; test_divide_assignment( L1, L2, R1, R2 ); } TYPED_TEST( VectorBinaryOperationsTest, scalarProduct ) { - // this test expects an odd size -// const int size = VECTOR_TEST_REDUCTION_SIZE % 2 ? VECTOR_TEST_REDUCTION_SIZE : VECTOR_TEST_REDUCTION_SIZE - 1; - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_REDUCTION_SIZE ); + this->reset( VECTOR_TEST_REDUCTION_SIZE ); #ifdef STATIC_VECTOR - setOscilatingSequence( L1, 1 ); - setConstantSequence( R1, 1 ); + setOscilatingSequence( this->L1, 1 ); + setConstantSequence( this->R1, 1 ); - const Left& L( L1 ); - const Right& R( R1 ); + const typename TestFixture::Left& L( this->L1 ); + const typename TestFixture::Right& R( this->R1 ); #else // we have to use _L1 and _R1 because L1 and R1 might be a const view - setOscilatingSequence( _L1, 1 ); - setConstantSequence( _R1, 1 ); + setOscilatingSequence( this->_L1, 1 ); + setConstantSequence( this->_R1, 1 ); - const Left L( _L1 ); - const Right R( _R1 ); + const typename TestFixture::Left L( this->_L1 ); + const typename TestFixture::Right R( this->_R1 ); #endif const int size = L.getSize(); @@ -470,7 +557,7 @@ TYPED_TEST( VectorBinaryOperationsTest, scalarProduct ) TYPED_TEST( VectorBinaryOperationsTest, min ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; // FIXME: does not work without TNL::, because std::min conflicts (why?!) @@ -488,7 +575,7 @@ TYPED_TEST( VectorBinaryOperationsTest, min ) TYPED_TEST( VectorBinaryOperationsTest, max ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; // FIXME: does not work without TNL::, because std::min conflicts (why?!) @@ -507,10 +594,10 @@ TYPED_TEST( VectorBinaryOperationsTest, max ) #if defined(HAVE_CUDA) && !defined(STATIC_VECTOR) TYPED_TEST( VectorBinaryOperationsTest, comparisonOnDifferentDevices ) { - SETUP_BINARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + SETUP_BINARY_TEST_ALIASES; - typename RightVector::HostType _R1_h; _R1_h = _R1; - typename Right::HostType R1_h( _R1_h ); + typename TestFixture::RightVector::HostType _R1_h; _R1_h = this->_R1; + typename TestFixture::Right::HostType R1_h( _R1_h ); // L1 and L2 are device vectors EXPECT_EQ( L1, R1_h ); @@ -518,10 +605,14 @@ TYPED_TEST( VectorBinaryOperationsTest, comparisonOnDifferentDevices ) } #endif +#ifdef HAVE_CUDA + #pragma pop +#endif + } // namespace binary_tests #endif // HAVE_GTEST -#ifndef STATIC_VECTOR +#if !defined(DISTRIBUTED_VECTOR) && !defined(STATIC_VECTOR) #include "../main.h" #endif diff --git a/src/UnitTests/Containers/VectorEvaluateAndReduceTest.cpp b/src/UnitTests/Containers/VectorEvaluateAndReduceTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19c19062d3e2bffcb35cd0f9d31f9f2130013912 --- /dev/null +++ b/src/UnitTests/Containers/VectorEvaluateAndReduceTest.cpp @@ -0,0 +1 @@ +#include "VectorEvaluateAndReduceTest.h" diff --git a/src/UnitTests/Containers/VectorEvaluateAndReduceTest.cu b/src/UnitTests/Containers/VectorEvaluateAndReduceTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..19c19062d3e2bffcb35cd0f9d31f9f2130013912 --- /dev/null +++ b/src/UnitTests/Containers/VectorEvaluateAndReduceTest.cu @@ -0,0 +1 @@ +#include "VectorEvaluateAndReduceTest.h" diff --git a/src/UnitTests/Containers/VectorTest-3.h b/src/UnitTests/Containers/VectorEvaluateAndReduceTest.h similarity index 100% rename from src/UnitTests/Containers/VectorTest-3.h rename to src/UnitTests/Containers/VectorEvaluateAndReduceTest.h diff --git a/src/UnitTests/Containers/VectorSequenceSetupFunctions.h b/src/UnitTests/Containers/VectorHelperFunctions.h similarity index 58% rename from src/UnitTests/Containers/VectorSequenceSetupFunctions.h rename to src/UnitTests/Containers/VectorHelperFunctions.h index b31037a4a0d848f3ec4b75681afad228cf91d08c..b1a596c6a4502effce2f9e0a593edf3a25e4ea23 100644 --- a/src/UnitTests/Containers/VectorSequenceSetupFunctions.h +++ b/src/UnitTests/Containers/VectorHelperFunctions.h @@ -1,6 +1,7 @@ #pragma once #include +#include template< typename Vector > void setLinearSequence( Vector& deviceVector ) @@ -11,8 +12,15 @@ void setLinearSequence( Vector& deviceVector ) typename Vector::HostType a; a.setLike( deviceVector ); #endif +#ifdef DISTRIBUTED_VECTOR + for( int i = 0; i < a.getLocalView().getSize(); i++ ) { + const auto gi = a.getLocalRange().getGlobalIndex( i ); + a[ gi ] = gi; + } +#else for( int i = 0; i < a.getSize(); i++ ) a[ i ] = i; +#endif deviceVector = a; } @@ -49,8 +57,15 @@ void setNegativeLinearSequence( Vector& deviceVector ) { typename Vector::HostType a; a.setLike( deviceVector ); +#ifdef DISTRIBUTED_VECTOR + for( int i = 0; i < a.getLocalView().getSize(); i++ ) { + const auto gi = a.getLocalRange().getGlobalIndex( i ); + a[ gi ] = -gi; + } +#else for( int i = 0; i < a.getSize(); i++ ) a[ i ] = -i; +#endif deviceVector = a; } @@ -64,8 +79,31 @@ void setOscilatingSequence( Vector& deviceVector, typename Vector::HostType a; a.setLike( deviceVector ); #endif - a[ 0 ] = v; - for( int i = 1; i < a.getSize(); i++ ) - a[ i ] = a[ i-1 ] * -1; +#ifdef DISTRIBUTED_VECTOR + for( int i = 0; i < a.getLocalView().getSize(); i++ ) { + const auto gi = a.getLocalRange().getGlobalIndex( i ); + a[ gi ] = v * std::pow( -1, gi ); + } +#else + for( int i = 0; i < a.getSize(); i++ ) + a[ i ] = v * std::pow( -1, i ); +#endif deviceVector = a; } + + +// specialization for V1 = view +template< typename V1, typename V2, + std::enable_if_t< TNL::IsViewType< V1 >::value, bool > = true > +void bindOrAssign( V1& v1, V2& v2 ) +{ + v1.bind( v2.getView() ); +} + +// specialization for V1 = vector +template< typename V1, typename V2, + std::enable_if_t< ! TNL::IsViewType< V1 >::value, bool > = true > +void bindOrAssign( V1& v1, V2& v2 ) +{ + v1 = v2; +} diff --git a/src/UnitTests/Containers/VectorPrefixSumTest.cpp b/src/UnitTests/Containers/VectorPrefixSumTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41ae5f65f082b27774cd6c31d249e7a763063634 --- /dev/null +++ b/src/UnitTests/Containers/VectorPrefixSumTest.cpp @@ -0,0 +1 @@ +#include "VectorPrefixSumTest.h" diff --git a/src/UnitTests/Containers/VectorPrefixSumTest.cu b/src/UnitTests/Containers/VectorPrefixSumTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..41ae5f65f082b27774cd6c31d249e7a763063634 --- /dev/null +++ b/src/UnitTests/Containers/VectorPrefixSumTest.cu @@ -0,0 +1 @@ +#include "VectorPrefixSumTest.h" diff --git a/src/UnitTests/Containers/VectorTest-2.h b/src/UnitTests/Containers/VectorPrefixSumTest.h similarity index 100% rename from src/UnitTests/Containers/VectorTest-2.h rename to src/UnitTests/Containers/VectorPrefixSumTest.h diff --git a/src/UnitTests/Containers/VectorTest-1.cpp b/src/UnitTests/Containers/VectorTest-1.cpp deleted file mode 100644 index b84e78f02e58c4703090dd06b9aca97b7d9c21e4..0000000000000000000000000000000000000000 --- a/src/UnitTests/Containers/VectorTest-1.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/*************************************************************************** - VectorTest-1.cpp - description - ------------------- - begin : Apr 30, 2019 - copyright : (C) 2019 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#include "VectorTest-1.h" diff --git a/src/UnitTests/Containers/VectorTest-1.cu b/src/UnitTests/Containers/VectorTest-1.cu deleted file mode 100644 index e3a4a6c149773a668f5c06f238d3796712bf095c..0000000000000000000000000000000000000000 --- a/src/UnitTests/Containers/VectorTest-1.cu +++ /dev/null @@ -1,11 +0,0 @@ -/*************************************************************************** - VectorTest-1.cu - description - ------------------- - begin : Apr 30, 2019 - copyright : (C) 2019 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#include "VectorTest-1.h" diff --git a/src/UnitTests/Containers/VectorTest-1.h b/src/UnitTests/Containers/VectorTest-1.h deleted file mode 100644 index ef096b03beeaed82b1ff0b6cdc2b219cee4326e9..0000000000000000000000000000000000000000 --- a/src/UnitTests/Containers/VectorTest-1.h +++ /dev/null @@ -1,292 +0,0 @@ -/*************************************************************************** - VectorTest-1.h - description - ------------------- - begin : Oct 25, 2010 - copyright : (C) 2010 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#ifdef HAVE_GTEST -#include "VectorTestSetup.h" - -constexpr int VECTOR_TEST_SIZE = 100; - -TYPED_TEST( VectorTest, constructors ) -{ - using VectorType = typename TestFixture::VectorType; - const int size = VECTOR_TEST_SIZE; - - VectorType empty_u; - VectorType empty_v( empty_u ); - EXPECT_EQ( empty_u.getSize(), 0 ); - EXPECT_EQ( empty_v.getSize(), 0 ); - - VectorType u( size ); - EXPECT_EQ( u.getSize(), size ); - - VectorType v( 10 ); - EXPECT_EQ( v.getSize(), 10 ); - - if( std::is_same< typename VectorType::DeviceType, Devices::Host >::value ) { - typename VectorType::ValueType data[ 10 ]; - VectorType w( data, 10 ); - EXPECT_NE( w.getData(), data ); - - VectorType z1( w ); - EXPECT_NE( z1.getData(), data ); - EXPECT_EQ( z1.getSize(), 10 ); - - VectorType z2( w, 1 ); - EXPECT_EQ( z2.getSize(), 9 ); - - VectorType z3( w, 2, 3 ); - EXPECT_EQ( z3.getSize(), 3 ); - } - - v = 1; - VectorType w( v ); - EXPECT_EQ( w.getSize(), v.getSize() ); - for( int i = 0; i < 10; i++ ) - EXPECT_EQ( v.getElement( i ), w.getElement( i ) ); - v.reset(); - EXPECT_EQ( w.getSize(), 10 ); - - VectorType a1 { 1, 2, 3 }; - EXPECT_EQ( a1.getElement( 0 ), 1 ); - EXPECT_EQ( a1.getElement( 1 ), 2 ); - EXPECT_EQ( a1.getElement( 2 ), 3 ); - - std::list< int > l = { 4, 5, 6 }; - VectorType a2( l ); - EXPECT_EQ( a2.getElement( 0 ), 4 ); - EXPECT_EQ( a2.getElement( 1 ), 5 ); - EXPECT_EQ( a2.getElement( 2 ), 6 ); - - std::vector< int > q = { 7, 8, 9 }; - - VectorType a3( q ); - EXPECT_EQ( a3.getElement( 0 ), 7 ); - EXPECT_EQ( a3.getElement( 1 ), 8 ); - EXPECT_EQ( a3.getElement( 2 ), 9 ); -} - -TEST( VectorSpecialCasesTest, defaultConstructors ) -{ - using ArrayType = Containers::Array< int, Devices::Host >; - using VectorViewType = VectorView< int, Devices::Host >; - using ArrayViewType = ArrayView< int, Devices::Host >; - - ArrayType a( 100 ); - a.setValue( 0 ); - - ArrayViewType a_view; - a_view.bind( a ); - - VectorViewType v_view; - v_view.bind( a ); - EXPECT_EQ( v_view.getData(), a_view.getData() ); -} - -TEST( VectorSpecialCasesTest, assignmentThroughView ) -{ - using VectorType = Containers::Vector< int, Devices::Host >; - using ViewType = VectorView< int, Devices::Host >; - - static_assert( HasSubscriptOperator< VectorType >::value, "Subscript operator detection by SFINAE does not work for Vector." ); - static_assert( HasSubscriptOperator< ViewType >::value, "Subscript operator detection by SFINAE does not work for VectorView." ); - - VectorType u( 100 ), v( 100 ); - ViewType u_view( u ), v_view( v ); - - u.setValue( 42 ); - v.setValue( 0 ); - v_view = u_view; - EXPECT_EQ( u_view.getData(), u.getData() ); - EXPECT_EQ( v_view.getData(), v.getData() ); - for( int i = 0; i < 100; i++ ) - EXPECT_EQ( v_view[ i ], 42 ); - - u.setValue( 42 ); - v.setValue( 0 ); - v_view = u; - EXPECT_EQ( u_view.getData(), u.getData() ); - EXPECT_EQ( v_view.getData(), v.getData() ); - for( int i = 0; i < 100; i++ ) - EXPECT_EQ( v_view[ i ], 42 ); -} - -TEST( VectorSpecialCasesTest, initializationOfVectorViewByArrayView ) -{ - using ArrayType = Containers::Array< int, Devices::Host >; - using VectorViewType = VectorView< const int, Devices::Host >; - using ArrayViewType = ArrayView< int, Devices::Host >; - - ArrayType a( 100 ); - a.setValue( 0 ); - ArrayViewType a_view( a ); - - VectorViewType v_view( a_view ); - EXPECT_EQ( v_view.getData(), a_view.getData() ); - EXPECT_EQ( sum( v_view ), 0 ); -} - -TYPED_TEST( VectorTest, addVector ) -{ - using VectorType = typename TestFixture::VectorType; - using VectorOperations = typename TestFixture::VectorOperations; - using ViewType = typename TestFixture::ViewType; - const int size = VECTOR_TEST_SIZE; - - VectorType x, y; - x.setSize( size ); - y.setSize( size ); - ViewType x_view( x ), y_view( y ); - - typename VectorType::HostType host_expected1( size ), host_expected2( size ); - for( int i = 0; i < size; i++ ) { - host_expected1.setElement( i, 2.0 + 3.0 * i ); - host_expected2.setElement( i, 1.0 + 3.0 * i ); - } - VectorType expected1, expected2; - expected1 = host_expected1; - expected2 = host_expected2; - - setConstantSequence( x, 1 ); - setLinearSequence( y ); - EXPECT_TRUE( 2.0 * x + 3.0 * y == expected1 ); - VectorOperations::addVector( x, y, 3.0, 2.0 ); - EXPECT_EQ( x, expected1 ); - - setConstantSequence( x, 1 ); - setLinearSequence( y ); - EXPECT_TRUE( x + 3.0 * y == expected2 ); - x.addVector( y, 3.0, 1.0 ); - EXPECT_EQ( x, expected2 ); - - setConstantSequence( x, 1 ); - setLinearSequence( y ); - EXPECT_TRUE( x_view + 3.0 * y_view == expected2 ); - x_view.addVector( y_view, 3.0, 1.0 ); - EXPECT_EQ( x, expected2 ); - - // multiplication by floating-point scalars which produces integer values - setConstantSequence( x, 2 ); - setConstantSequence( y, 4 ); - EXPECT_EQ( min( -1.5 * x + 2.5 * y ), 7 ); - EXPECT_EQ( max( -1.5 * x + 2.5 * y ), 7 ); - x.addVector( y, 2.5, -1.5 ); - EXPECT_EQ( min( x ), 7 ); - EXPECT_EQ( max( x ), 7 ); - -} - -TYPED_TEST( VectorTest, addVectors ) -{ - using VectorType = typename TestFixture::VectorType; - using VectorOperations = typename TestFixture::VectorOperations; - using ViewType = typename TestFixture::ViewType; - const int size = VECTOR_TEST_SIZE; - - VectorType x, y, z; - x.setSize( size ); - y.setSize( size ); - z.setSize( size ); - ViewType x_view( x ), y_view( y ), z_view( z ); - - typename VectorType::HostType host_expected1( size ), host_expected2( size ); - for( int i = 0; i < size; i++ ) { - host_expected1.setElement( i, 1.0 + 3.0 * i + 2.0 ); - host_expected2.setElement( i, 2.0 + 3.0 * i + 2.0 ); - } - VectorType expected1, expected2; - expected1 = host_expected1; - expected2 = host_expected2; - - setConstantSequence( x, 1 ); - setLinearSequence( y ); - setConstantSequence( z, 2 ); - EXPECT_TRUE( 3.0 * y + z + x == expected1 ); - VectorOperations::addVectors( x, y, 3.0, z, 1.0, 1.0 ); - EXPECT_EQ( x, expected1 ); - - setConstantSequence( x, 1 ); - setLinearSequence( y ); - setConstantSequence( z, 2 ); - EXPECT_TRUE( 3.0 * y + z + 2.0 * x == expected2 ); - x.addVectors( y, 3.0, z, 1.0, 2.0 ); - EXPECT_EQ( x, expected2 ); - - setConstantSequence( x, 1 ); - setLinearSequence( y ); - setConstantSequence( z, 2 ); - EXPECT_TRUE( 3.0 * y_view + z_view + 2.0 * x_view == expected2 ); - x_view.addVectors( y_view, 3.0, z_view, 1.0, 2.0 ); - EXPECT_EQ( x, expected2 ); - - // multiplication by floating-point scalars which produces integer values - setConstantSequence( x, 2 ); - setConstantSequence( y, 4 ); - setConstantSequence( z, 6 ); - EXPECT_EQ( min( 2.5 * y - 1.5 * z - 1.5 * x ), -2 ); - EXPECT_EQ( max( 2.5 * y - 1.5 * z - 1.5 * x ), -2 ); - x.addVectors( y, 2.5, z, -1.5, -1.5 ); - EXPECT_EQ( min( x ), -2 ); - EXPECT_EQ( max( x ), -2 ); -} - -TEST( VectorSpecialCasesTest, sumOfBoolVector ) -{ - using VectorType = Containers::Vector< bool, Devices::Host >; - using ViewType = VectorView< bool, Devices::Host >; - const float epsilon = 64 * std::numeric_limits< float >::epsilon(); - - VectorType v( 512 ), w( 512 ); - ViewType v_view( v ), w_view( w ); - v.setValue( true ); - w.setValue( false ); - - const int sum = TNL::sum( v ); - const int l1norm = lpNorm( v, 1.0 ); - const float l2norm = lpNorm( v, 2.0 ); - const float l3norm = lpNorm( v, 3.0 ); - EXPECT_EQ( sum, 512 ); - EXPECT_EQ( l1norm, 512 ); - EXPECT_NEAR( l2norm, std::sqrt( 512 ), epsilon ); - EXPECT_NEAR( l3norm, std::cbrt( 512 ), epsilon ); - - const int diff_sum = TNL::sum( v - w ); - const int diff_l1norm = lpNorm( v - w, 1.0 ); - const float diff_l2norm = lpNorm( v - w, 2.0 ); - const float diff_l3norm = lpNorm( v - w, 3.0 ); - EXPECT_EQ( diff_sum, 512 ); - EXPECT_EQ( diff_l1norm, 512 ); - EXPECT_NEAR( diff_l2norm, std::sqrt( 512 ), epsilon ); - EXPECT_NEAR( diff_l3norm, std::cbrt( 512 ), epsilon ); - - // test views - const int sum_view = TNL::sum( v_view ); - const int l1norm_view = lpNorm( v_view, 1.0 ); - const float l2norm_view = lpNorm( v_view, 2.0 ); - const float l3norm_view = lpNorm( v_view, 3.0 ); - EXPECT_EQ( sum_view, 512 ); - EXPECT_EQ( l1norm_view, 512 ); - EXPECT_NEAR( l2norm_view, std::sqrt( 512 ), epsilon ); - EXPECT_NEAR( l3norm_view, std::cbrt( 512 ), epsilon ); - - const int diff_sum_view = TNL::sum( v_view - w_view ); - const int diff_l1norm_view = lpNorm( v_view -w_view, 1.0 ); - const float diff_l2norm_view = lpNorm( v_view - w_view, 2.0 ); - const float diff_l3norm_view = lpNorm( v_view - w_view, 3.0 ); - EXPECT_EQ( diff_sum_view, 512 ); - EXPECT_EQ( diff_l1norm_view, 512 ); - EXPECT_NEAR( diff_l2norm_view, std::sqrt( 512 ), epsilon ); - EXPECT_NEAR( diff_l3norm_view, std::cbrt( 512 ), epsilon ); -} - -#endif // HAVE_GTEST - -#include "../main.h" diff --git a/src/UnitTests/Containers/VectorTest-2.cpp b/src/UnitTests/Containers/VectorTest-2.cpp deleted file mode 100644 index 02a1128891ec10487dde003104b906966247c732..0000000000000000000000000000000000000000 --- a/src/UnitTests/Containers/VectorTest-2.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/*************************************************************************** - VectorTest-2.cpp - description - ------------------- - begin : Apr 30, 2019 - copyright : (C) 2019 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#include "VectorTest-2.h" diff --git a/src/UnitTests/Containers/VectorTest-2.cu b/src/UnitTests/Containers/VectorTest-2.cu deleted file mode 100644 index d7f43ab6f663cdb2ecbe3cf86c70cae8f427dd28..0000000000000000000000000000000000000000 --- a/src/UnitTests/Containers/VectorTest-2.cu +++ /dev/null @@ -1,11 +0,0 @@ -/*************************************************************************** - VectorTest-2.cu - description - ------------------- - begin : Apr 30, 2019 - copyright : (C) 2019 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#include "VectorTest-2.h" diff --git a/src/UnitTests/Containers/VectorTest-3.cpp b/src/UnitTests/Containers/VectorTest-3.cpp deleted file mode 100644 index ccc29314dc98ea50ad55209a07e4786219411172..0000000000000000000000000000000000000000 --- a/src/UnitTests/Containers/VectorTest-3.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/*************************************************************************** - VectorTest-3.cpp - description - ------------------- - begin : Apr 30, 2019 - copyright : (C) 2019 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#include "VectorTest-3.h" diff --git a/src/UnitTests/Containers/VectorTest-3.cu b/src/UnitTests/Containers/VectorTest-3.cu deleted file mode 100644 index b922dbced7abe80604089d05a30a2812fa1d8cf3..0000000000000000000000000000000000000000 --- a/src/UnitTests/Containers/VectorTest-3.cu +++ /dev/null @@ -1,11 +0,0 @@ -/*************************************************************************** - VectorTest-3.cu - description - ------------------- - begin : Apr 30, 2019 - copyright : (C) 2019 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#include "VectorTest-3.h" diff --git a/src/UnitTests/Containers/VectorTest.cpp b/src/UnitTests/Containers/VectorTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..739be1eda0275a04766192ae1c1658a29d7ad61e --- /dev/null +++ b/src/UnitTests/Containers/VectorTest.cpp @@ -0,0 +1 @@ +#include "VectorTest.h" diff --git a/src/UnitTests/Containers/VectorTest.cu b/src/UnitTests/Containers/VectorTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..739be1eda0275a04766192ae1c1658a29d7ad61e --- /dev/null +++ b/src/UnitTests/Containers/VectorTest.cu @@ -0,0 +1 @@ +#include "VectorTest.h" diff --git a/src/UnitTests/Containers/VectorTest.h b/src/UnitTests/Containers/VectorTest.h new file mode 100644 index 0000000000000000000000000000000000000000..b6602ba141dbeb3a45470c58cf6130544b85d944 --- /dev/null +++ b/src/UnitTests/Containers/VectorTest.h @@ -0,0 +1,192 @@ +/*************************************************************************** + VectorTest-1.h - description + ------------------- + begin : Oct 25, 2010 + copyright : (C) 2010 by Tomas Oberhuber + email : tomas.oberhuber@fjfi.cvut.cz + ***************************************************************************/ + +/* See Copyright Notice in tnl/Copyright */ + +#pragma once + +#ifdef HAVE_GTEST +#include "VectorTestSetup.h" + +constexpr int VECTOR_TEST_SIZE = 100; + +TYPED_TEST( VectorTest, constructors ) +{ + using VectorType = typename TestFixture::VectorType; + const int size = VECTOR_TEST_SIZE; + + VectorType empty_u; + VectorType empty_v( empty_u ); + EXPECT_EQ( empty_u.getSize(), 0 ); + EXPECT_EQ( empty_v.getSize(), 0 ); + + VectorType u( size ); + EXPECT_EQ( u.getSize(), size ); + + VectorType v( 10 ); + EXPECT_EQ( v.getSize(), 10 ); + + if( std::is_same< typename VectorType::DeviceType, Devices::Host >::value ) { + typename VectorType::ValueType data[ 10 ]; + VectorType w( data, 10 ); + EXPECT_NE( w.getData(), data ); + + VectorType z1( w ); + EXPECT_NE( z1.getData(), data ); + EXPECT_EQ( z1.getSize(), 10 ); + + VectorType z2( w, 1 ); + EXPECT_EQ( z2.getSize(), 9 ); + + VectorType z3( w, 2, 3 ); + EXPECT_EQ( z3.getSize(), 3 ); + } + + v = 1; + VectorType w( v ); + EXPECT_EQ( w.getSize(), v.getSize() ); + for( int i = 0; i < 10; i++ ) + EXPECT_EQ( v.getElement( i ), w.getElement( i ) ); + v.reset(); + EXPECT_EQ( w.getSize(), 10 ); + + VectorType a1 { 1, 2, 3 }; + EXPECT_EQ( a1.getElement( 0 ), 1 ); + EXPECT_EQ( a1.getElement( 1 ), 2 ); + EXPECT_EQ( a1.getElement( 2 ), 3 ); + + std::list< int > l = { 4, 5, 6 }; + VectorType a2( l ); + EXPECT_EQ( a2.getElement( 0 ), 4 ); + EXPECT_EQ( a2.getElement( 1 ), 5 ); + EXPECT_EQ( a2.getElement( 2 ), 6 ); + + std::vector< int > q = { 7, 8, 9 }; + + VectorType a3( q ); + EXPECT_EQ( a3.getElement( 0 ), 7 ); + EXPECT_EQ( a3.getElement( 1 ), 8 ); + EXPECT_EQ( a3.getElement( 2 ), 9 ); +} + +TEST( VectorSpecialCasesTest, defaultConstructors ) +{ + using ArrayType = Containers::Array< int, Devices::Host >; + using VectorViewType = VectorView< int, Devices::Host >; + using ArrayViewType = ArrayView< int, Devices::Host >; + + ArrayType a( 100 ); + a.setValue( 0 ); + + ArrayViewType a_view; + a_view.bind( a ); + + VectorViewType v_view; + v_view.bind( a ); + EXPECT_EQ( v_view.getData(), a_view.getData() ); +} + +TEST( VectorSpecialCasesTest, assignmentThroughView ) +{ + using VectorType = Containers::Vector< int, Devices::Host >; + using ViewType = VectorView< int, Devices::Host >; + + static_assert( HasSubscriptOperator< VectorType >::value, "Subscript operator detection by SFINAE does not work for Vector." ); + static_assert( HasSubscriptOperator< ViewType >::value, "Subscript operator detection by SFINAE does not work for VectorView." ); + + VectorType u( 100 ), v( 100 ); + ViewType u_view( u ), v_view( v ); + + u.setValue( 42 ); + v.setValue( 0 ); + v_view = u_view; + EXPECT_EQ( u_view.getData(), u.getData() ); + EXPECT_EQ( v_view.getData(), v.getData() ); + for( int i = 0; i < 100; i++ ) + EXPECT_EQ( v_view[ i ], 42 ); + + u.setValue( 42 ); + v.setValue( 0 ); + v_view = u; + EXPECT_EQ( u_view.getData(), u.getData() ); + EXPECT_EQ( v_view.getData(), v.getData() ); + for( int i = 0; i < 100; i++ ) + EXPECT_EQ( v_view[ i ], 42 ); +} + +TEST( VectorSpecialCasesTest, initializationOfVectorViewByArrayView ) +{ + using ArrayType = Containers::Array< int, Devices::Host >; + using VectorViewType = VectorView< const int, Devices::Host >; + using ArrayViewType = ArrayView< int, Devices::Host >; + + ArrayType a( 100 ); + a.setValue( 0 ); + ArrayViewType a_view( a ); + + VectorViewType v_view( a_view ); + EXPECT_EQ( v_view.getData(), a_view.getData() ); + EXPECT_EQ( sum( v_view ), 0 ); +} + +TEST( VectorSpecialCasesTest, sumOfBoolVector ) +{ + using VectorType = Containers::Vector< bool, Devices::Host >; + using ViewType = typename VectorType::ViewType; + const double epsilon = 64 * std::numeric_limits< double >::epsilon(); + constexpr int size = 4999; + + VectorType v( size ); + ViewType v_view( v ); + v.setValue( true ); + + // normal sum and lpNorm rely on built-in integral promotion + const auto sum = TNL::sum( v ); + const auto l1norm = l1Norm( v ); + const auto l2norm = l2Norm( v ); + const auto l3norm = lpNorm( v, 3.0 ); + EXPECT_EQ( sum, size ); + EXPECT_EQ( l1norm, size ); + EXPECT_EQ( l2norm, std::sqrt( size ) ); + EXPECT_NEAR( l3norm, std::cbrt( size ), epsilon ); + + // explicit cast to double + const auto sum_cast = TNL::sum( cast( v ) ); + const auto l1norm_cast = l1Norm( cast( v ) ); + const auto l2norm_cast = l2Norm( cast( v ) ); + const auto l3norm_cast = lpNorm( cast( v ), 3.0 ); + EXPECT_EQ( sum_cast, size ); + EXPECT_EQ( l1norm_cast, size ); + EXPECT_EQ( l2norm_cast, std::sqrt( size ) ); + EXPECT_NEAR( l3norm_cast, std::cbrt( size ), epsilon ); + + // test views + // normal sum and lpNorm rely on built-in integral promotion + const auto sum_view = TNL::sum( v_view ); + const auto l1norm_view = l1Norm( v_view ); + const auto l2norm_view = l2Norm( v_view ); + const auto l3norm_view = lpNorm( v_view, 3.0 ); + EXPECT_EQ( sum_view, size ); + EXPECT_EQ( l1norm_view, size ); + EXPECT_EQ( l2norm_view, std::sqrt( size ) ); + EXPECT_NEAR( l3norm_view, std::cbrt( size ), epsilon ); + + // explicit cast to double + const auto sum_view_cast = TNL::sum( cast( v_view ) ); + const auto l1norm_view_cast = l1Norm( cast( v_view ) ); + const auto l2norm_view_cast = l2Norm( cast( v_view ) ); + const auto l3norm_view_cast = lpNorm( cast( v_view ), 3.0 ); + EXPECT_EQ( sum_view_cast, size ); + EXPECT_EQ( l1norm_view_cast, size); + EXPECT_EQ( l2norm_view_cast, std::sqrt( size ) ); + EXPECT_NEAR( l3norm_view_cast, std::cbrt( size ), epsilon ); +} + +#endif // HAVE_GTEST + +#include "../main.h" diff --git a/src/UnitTests/Containers/VectorTestSetup.h b/src/UnitTests/Containers/VectorTestSetup.h index 6c32fea7876f637135ce27fc68b51a07af432464..7338f9637d3178a4d9b567af59e6c201c419f30e 100644 --- a/src/UnitTests/Containers/VectorTestSetup.h +++ b/src/UnitTests/Containers/VectorTestSetup.h @@ -18,7 +18,7 @@ #include #include #include -#include "VectorSequenceSetupFunctions.h" +#include "VectorHelperFunctions.h" #include "gtest/gtest.h" diff --git a/src/UnitTests/Containers/VectorUnaryOperationsTest.h b/src/UnitTests/Containers/VectorUnaryOperationsTest.h index 89246ea93b5fe30d78465893ca1e49cfe583a3c8..a0aa2695f054295ec83ced0e7b9fa2af70249872 100644 --- a/src/UnitTests/Containers/VectorUnaryOperationsTest.h +++ b/src/UnitTests/Containers/VectorUnaryOperationsTest.h @@ -11,9 +11,21 @@ #pragma once #ifdef HAVE_GTEST -#include -#include -#include "VectorSequenceSetupFunctions.h" + +#if defined(DISTRIBUTED_VECTOR) + #include + #include + #include + #include + #include +#elif defined(STATIC_VECTOR) + #include +#else + #include + #include +#endif + +#include "VectorHelperFunctions.h" #include "gtest/gtest.h" @@ -23,11 +35,8 @@ using namespace TNL::Containers::Algorithms; namespace unary_tests { -constexpr int VECTOR_TEST_SIZE = 100; - -// should be small enough to have fast tests, but larger than minGPUReductionDataSize -// and large enough to require multiple CUDA blocks for reduction -constexpr int VECTOR_TEST_REDUCTION_SIZE = 5000; +// prime number to force non-uniform distribution in block-wise algorithms +constexpr int VECTOR_TEST_SIZE = 97; // test fixture for typed tests template< typename T > @@ -35,14 +44,44 @@ class VectorUnaryOperationsTest : public ::testing::Test { protected: using VectorOrView = T; -#ifndef STATIC_VECTOR +#ifdef STATIC_VECTOR + template< typename Real > + using Vector = StaticVector< VectorOrView::getSize(), Real >; +#else using NonConstReal = std::remove_const_t< typename VectorOrView::RealType >; - using VectorType = Vector< NonConstReal, typename VectorOrView::DeviceType, typename VectorOrView::IndexType >; + #ifdef DISTRIBUTED_VECTOR + using CommunicatorType = typename VectorOrView::CommunicatorType; + using VectorType = DistributedVector< NonConstReal, typename VectorOrView::DeviceType, typename VectorOrView::IndexType, CommunicatorType >; + template< typename Real > + using Vector = DistributedVector< Real, typename VectorOrView::DeviceType, typename VectorOrView::IndexType, CommunicatorType >; + #else + using VectorType = Containers::Vector< NonConstReal, typename VectorOrView::DeviceType, typename VectorOrView::IndexType >; + template< typename Real > + using Vector = Containers::Vector< Real, typename VectorOrView::DeviceType, typename VectorOrView::IndexType >; + #endif #endif }; // types for which VectorUnaryOperationsTest is instantiated -#ifdef STATIC_VECTOR +#if defined(DISTRIBUTED_VECTOR) + using VectorTypes = ::testing::Types< + #ifndef HAVE_CUDA + DistributedVector< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVectorView< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVectorView< const double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Host, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< double, Devices::Host, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< const double, Devices::Host, int, Communicators::NoDistrCommunicator > + #else + DistributedVector< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVectorView< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVectorView< const double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Cuda, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< double, Devices::Cuda, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< const double, Devices::Cuda, int, Communicators::NoDistrCommunicator > + #endif + >; +#elif defined(STATIC_VECTOR) using VectorTypes = ::testing::Types< StaticVector< 1, int >, StaticVector< 1, double >, @@ -89,11 +128,13 @@ TYPED_TEST_SUITE( VectorUnaryOperationsTest, VectorTypes ); #define SETUP_UNARY_VECTOR_TEST_FUNCTION( _, begin, end, function ) \ using VectorOrView = typename TestFixture::VectorOrView; \ using RealType = typename VectorOrView::RealType; \ + using ExpectedVector = typename TestFixture::template Vector< decltype(function(RealType{})) >; \ constexpr int size = VectorOrView::getSize(); \ \ - VectorOrView V1, expected; \ + VectorOrView V1; \ + ExpectedVector expected; \ \ - const double h = (end - begin) / size; \ + const double h = (double) (end - begin) / size; \ for( int i = 0; i < size; i++ ) \ { \ const RealType x = begin + i * h; \ @@ -101,12 +142,55 @@ TYPED_TEST_SUITE( VectorUnaryOperationsTest, VectorTypes ); expected[ i ] = function(x); \ } \ - #define SETUP_UNARY_VECTOR_TEST_REDUCTION \ +#elif defined(DISTRIBUTED_VECTOR) + #define SETUP_UNARY_VECTOR_TEST( _size ) \ + using VectorType = typename TestFixture::VectorType; \ using VectorOrView = typename TestFixture::VectorOrView; \ - constexpr int size = VectorOrView::getSize(); \ + constexpr int size = _size; \ + using CommunicatorType = typename VectorOrView::CommunicatorType; \ + const auto group = CommunicatorType::AllGroup; \ + using LocalRangeType = typename VectorOrView::LocalRangeType; \ + const LocalRangeType localRange = Partitioner< typename VectorOrView::IndexType, CommunicatorType >::splitRange( size, group ); \ \ - VectorOrView V1; \ - setLinearSequence( V1 ); \ + const int rank = CommunicatorType::GetRank(group); \ + const int nproc = CommunicatorType::GetSize(group); \ + \ + VectorType _V1, _V2; \ + _V1.setDistribution( localRange, size, group ); \ + _V2.setDistribution( localRange, size, group ); \ + \ + _V1 = 1; \ + _V2 = 2; \ + \ + VectorOrView V1( _V1 ), V2( _V2 ); \ + + #define SETUP_UNARY_VECTOR_TEST_FUNCTION( _size, begin, end, function ) \ + using VectorType = typename TestFixture::VectorType; \ + using VectorOrView = typename TestFixture::VectorOrView; \ + using RealType = typename VectorType::RealType; \ + using ExpectedVector = typename TestFixture::template Vector< decltype(function(RealType{})) >; \ + constexpr int size = _size; \ + using CommunicatorType = typename VectorOrView::CommunicatorType; \ + const auto group = CommunicatorType::AllGroup; \ + using LocalRangeType = typename VectorOrView::LocalRangeType; \ + const LocalRangeType localRange = Partitioner< typename VectorOrView::IndexType, CommunicatorType >::splitRange( size, group ); \ + \ + typename VectorType::HostType _V1h; \ + typename ExpectedVector::HostType expected_h; \ + _V1h.setDistribution( localRange, size, group ); \ + expected_h.setDistribution( localRange, size, group ); \ + \ + const double h = (double) (end - begin) / size; \ + for( int i = localRange.getBegin(); i < localRange.getEnd(); i++ ) \ + { \ + const RealType x = begin + i * h; \ + _V1h[ i ] = x; \ + expected_h[ i ] = function(x); \ + } \ + \ + VectorType _V1; _V1 = _V1h; \ + VectorOrView V1( _V1 ); \ + ExpectedVector expected; expected = expected_h; \ #else #define SETUP_UNARY_VECTOR_TEST( _size ) \ @@ -125,11 +209,13 @@ TYPED_TEST_SUITE( VectorUnaryOperationsTest, VectorTypes ); using VectorType = typename TestFixture::VectorType; \ using VectorOrView = typename TestFixture::VectorOrView; \ using RealType = typename VectorType::RealType; \ + using ExpectedVector = typename TestFixture::template Vector< decltype(function(RealType{})) >; \ constexpr int size = _size; \ \ - typename VectorType::HostType _V1h( size ), expected_h( size ); \ + typename VectorType::HostType _V1h( size ); \ + typename ExpectedVector::HostType expected_h( size ); \ \ - const double h = (end - begin) / size; \ + const double h = (double) (end - begin) / size; \ for( int i = 0; i < size; i++ ) \ { \ const RealType x = begin + i * h; \ @@ -139,16 +225,7 @@ TYPED_TEST_SUITE( VectorUnaryOperationsTest, VectorTypes ); \ VectorType _V1; _V1 = _V1h; \ VectorOrView V1( _V1 ); \ - VectorType expected; expected = expected_h; \ - - #define SETUP_UNARY_VECTOR_TEST_REDUCTION \ - using VectorType = typename TestFixture::VectorType; \ - using VectorOrView = typename TestFixture::VectorOrView; \ - constexpr int size = VECTOR_TEST_REDUCTION_SIZE; \ - \ - VectorType _V1( size ); \ - setLinearSequence( _V1 ); \ - VectorOrView V1( _V1 ); \ + ExpectedVector expected; expected = expected_h; \ #endif @@ -168,19 +245,32 @@ void expect_vectors_near( const Left& _v1, const Right& _v2 ) #else using LeftNonConstReal = std::remove_const_t< typename Left::RealType >; using RightNonConstReal = std::remove_const_t< typename Right::RealType >; +#ifdef DISTRIBUTED_VECTOR + using CommunicatorType = typename Left::CommunicatorType; + static_assert( std::is_same< typename Right::CommunicatorType, CommunicatorType >::value, + "CommunicatorType must be the same for both Left and Right vectors." ); + using LeftVector = DistributedVector< LeftNonConstReal, typename Left::DeviceType, typename Left::IndexType, CommunicatorType >; + using RightVector = DistributedVector< RightNonConstReal, typename Right::DeviceType, typename Right::IndexType, CommunicatorType >; +#else using LeftVector = Vector< LeftNonConstReal, typename Left::DeviceType, typename Left::IndexType >; using RightVector = Vector< RightNonConstReal, typename Right::DeviceType, typename Right::IndexType >; - using LeftHostVector = Vector< LeftNonConstReal, Devices::Host, typename Left::IndexType >; - using RightHostVector = Vector< RightNonConstReal, Devices::Host, typename Right::IndexType >; +#endif + using LeftHostVector = typename LeftVector::HostType; + using RightHostVector = typename RightVector::HostType; // first evaluate expressions LeftVector v1; v1 = _v1; RightVector v2; v2 = _v2; // then copy to host LeftHostVector v1_h; v1_h = v1; - RightHostVector v2_h; v2_h = v1; + RightHostVector v2_h; v2_h = v2; +#ifdef DISTRIBUTED_VECTOR + const auto localRange = v1.getLocalRange(); + for( int i = localRange.getBegin(); i < localRange.getEnd(); i++ ) +#else for( int i = 0; i < v1.getSize(); i++ ) - EXPECT_NEAR( v1_h[i], v2_h[i], 1e-6 ); +#endif + EXPECT_NEAR( v1_h[i], v2_h[i], 1e-6 ) << "i = " << i; #endif } @@ -188,8 +278,11 @@ TYPED_TEST( VectorUnaryOperationsTest, minus ) { SETUP_UNARY_VECTOR_TEST( VECTOR_TEST_SIZE ); + // vector or view EXPECT_EQ( -V1, -1 ); + // unary expression EXPECT_EQ( V2 * (-V1), -2 ); + // binary expression EXPECT_EQ( -(V1 + V1), -2 ); } @@ -199,278 +292,311 @@ TYPED_TEST( VectorUnaryOperationsTest, abs ) // vector or view EXPECT_EQ( abs(V1), V1 ); - // expression + // unary expression EXPECT_EQ( abs(-V1), V1 ); + // unary expression + EXPECT_EQ( abs(-V1-V1), V2 ); } TYPED_TEST( VectorUnaryOperationsTest, sin ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -VECTOR_TEST_SIZE, VECTOR_TEST_SIZE, TNL::sin ); -// EXPECT_EQ( sin(V1), expected ); + + // vector or view expect_vectors_near( sin(V1), expected ); + // binary expression + expect_vectors_near( sin(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( sin(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, asin ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -1.0, 1.0, TNL::asin ); -// EXPECT_EQ( asin(V1), expected ); + + // vector or view expect_vectors_near( asin(V1), expected ); + // binary expression + expect_vectors_near( asin(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( asin(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, cos ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -VECTOR_TEST_SIZE, VECTOR_TEST_SIZE, TNL::cos ); -// EXPECT_EQ( cos(V1), expected ); + + // vector or view expect_vectors_near( cos(V1), expected ); + // binary expression + expect_vectors_near( cos(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( cos(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, acos ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -1.0, 1.0, TNL::acos ); -// EXPECT_EQ( acos(V1), expected ); + + // vector or view expect_vectors_near( acos(V1), expected ); + // binary expression + expect_vectors_near( acos(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( acos(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, tan ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -1.5, 1.5, TNL::tan ); -// EXPECT_EQ( tan(V1), expected ); + + // vector or view expect_vectors_near( tan(V1), expected ); + // binary expression + expect_vectors_near( tan(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( tan(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, atan ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -VECTOR_TEST_SIZE, VECTOR_TEST_SIZE, TNL::atan ); -// EXPECT_EQ( atan(V1), expected ); + + // vector or view expect_vectors_near( atan(V1), expected ); + // binary expression + expect_vectors_near( atan(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( atan(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, sinh ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -10, 10, TNL::sinh ); -// EXPECT_EQ( sinh(V1), expected ); + + // vector or view expect_vectors_near( sinh(V1), expected ); + // binary expression + expect_vectors_near( sinh(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( sinh(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, asinh ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -VECTOR_TEST_SIZE, VECTOR_TEST_SIZE, TNL::asinh ); -// EXPECT_EQ( asinh(V1), expected ); + + // vector or view expect_vectors_near( asinh(V1), expected ); + // binary expression + expect_vectors_near( asinh(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( asinh(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, cosh ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -10, 10, TNL::cosh ); -// EXPECT_EQ( cosh(V1), expected ); + + // vector or view expect_vectors_near( cosh(V1), expected ); + // binary expression + expect_vectors_near( cosh(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( cosh(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, acosh ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, 1, VECTOR_TEST_SIZE, TNL::acosh ); -// EXPECT_EQ( acosh(V1), expected ); + + // vector or view expect_vectors_near( acosh(V1), expected ); + // binary expression + expect_vectors_near( acosh(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( acosh(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, tanh ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -VECTOR_TEST_SIZE, VECTOR_TEST_SIZE, TNL::tanh ); -// EXPECT_EQ( tanh(V1), expected ); + + // vector or view expect_vectors_near( tanh(V1), expected ); + // binary expression + expect_vectors_near( tanh(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( tanh(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, atanh ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -0.99, 0.99, TNL::atanh ); -// EXPECT_EQ( atanh(V1), expected ); + + // vector or view expect_vectors_near( atanh(V1), expected ); + // binary expression + expect_vectors_near( atanh(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( atanh(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, pow ) { - auto pow3 = [](int i) { return TNL::pow(i, 3); }; + // FIXME: for integer exponent, the test fails with CUDA +// auto pow3 = [](double i) { return TNL::pow(i, 3); }; + auto pow3 = [](double i) { return TNL::pow(i, 3.0); }; SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -VECTOR_TEST_SIZE, VECTOR_TEST_SIZE, pow3 ); -// EXPECT_EQ( pow(V1, 3), expected ); - expect_vectors_near( pow(V1, 3), expected ); + + // vector or view + expect_vectors_near( pow(V1, 3.0), expected ); + // binary expression + expect_vectors_near( pow(2 * V1 - V1, 3.0), expected ); + // unary expression + expect_vectors_near( pow(-(-V1), 3.0), expected ); } TYPED_TEST( VectorUnaryOperationsTest, exp ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -10, 10, TNL::exp ); -// EXPECT_EQ( exp(V1), expected ); + + // vector or view expect_vectors_near( exp(V1), expected ); + // binary expression + expect_vectors_near( exp(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( exp(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, sqrt ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, 0, VECTOR_TEST_SIZE, TNL::sqrt ); -// EXPECT_EQ( sqrt(V1), expected ); + + // vector or view expect_vectors_near( sqrt(V1), expected ); + // binary expression + expect_vectors_near( sqrt(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( sqrt(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, cbrt ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -VECTOR_TEST_SIZE, VECTOR_TEST_SIZE, TNL::cbrt ); -// EXPECT_EQ( cbrt(V1), expected ); + + // vector or view expect_vectors_near( cbrt(V1), expected ); + // binary expression + expect_vectors_near( cbrt(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( cbrt(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, log ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, 1, VECTOR_TEST_SIZE, TNL::log ); -// EXPECT_EQ( log(V1), expected ); + + // vector or view expect_vectors_near( log(V1), expected ); + // binary expression + expect_vectors_near( log(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( log(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, log10 ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, 1, VECTOR_TEST_SIZE, TNL::log10 ); -// EXPECT_EQ( log10(V1), expected ); + + // vector or view expect_vectors_near( log10(V1), expected ); + // binary expression + expect_vectors_near( log10(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( log10(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, log2 ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, 1, VECTOR_TEST_SIZE, TNL::log2 ); -// EXPECT_EQ( log2(V1), expected ); + + // vector or view expect_vectors_near( log2(V1), expected ); + // binary expression + expect_vectors_near( log2(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( log2(-(-V1)), expected ); } TYPED_TEST( VectorUnaryOperationsTest, floor ) { SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -3.0, 3.0, TNL::floor ); - EXPECT_EQ( floor(V1), expected ); -} - -TYPED_TEST( VectorUnaryOperationsTest, ceil ) -{ - SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -3.0, 3.0, TNL::ceil ); - EXPECT_EQ( ceil(V1), expected ); -} - -TYPED_TEST( VectorUnaryOperationsTest, sign ) -{ - SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -VECTOR_TEST_SIZE, VECTOR_TEST_SIZE, TNL::sign ); - EXPECT_EQ( sign(V1), expected ); -} - - -TYPED_TEST( VectorUnaryOperationsTest, max ) -{ - SETUP_UNARY_VECTOR_TEST_REDUCTION; // vector or view - EXPECT_EQ( max(V1), size - 1 ); - // unary expression - EXPECT_EQ( max(-V1), 0 ); + expect_vectors_near( floor(V1), expected ); // binary expression - EXPECT_EQ( max(V1 + 2), size - 1 + 2 ); -} - -TYPED_TEST( VectorUnaryOperationsTest, argMax ) -{ - SETUP_UNARY_VECTOR_TEST_REDUCTION; - - // vector or view - int arg = -1; - EXPECT_EQ( argMax(V1, arg), size - 1 ); - EXPECT_EQ( arg, size - 1 ); + expect_vectors_near( floor(2 * V1 - V1), expected ); // unary expression - arg = -1; - EXPECT_EQ( argMax(-V1, arg), 0 ); - EXPECT_EQ( arg, 0 ); - // expression - arg = -1; - EXPECT_EQ( argMax(V1 + 2, arg), size - 1 + 2 ); - EXPECT_EQ( arg, size - 1 ); + expect_vectors_near( floor(-(-V1)), expected ); } -TYPED_TEST( VectorUnaryOperationsTest, min ) +TYPED_TEST( VectorUnaryOperationsTest, ceil ) { - SETUP_UNARY_VECTOR_TEST_REDUCTION; + SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -3.0, 3.0, TNL::ceil ); // vector or view - EXPECT_EQ( min(V1), 0 ); - // unary expression - EXPECT_EQ( min(-V1), 1 - size ); + expect_vectors_near( ceil(V1), expected ); // binary expression - EXPECT_EQ( min(V1 + 2), 2 ); -} - -TYPED_TEST( VectorUnaryOperationsTest, argMin ) -{ - SETUP_UNARY_VECTOR_TEST_REDUCTION; - - // vector or view - int arg = -1; - EXPECT_EQ( argMin(V1, arg), 0 ); - EXPECT_EQ( arg, 0 ); + expect_vectors_near( ceil(2 * V1 - V1), expected ); // unary expression - arg = -1; - EXPECT_EQ( argMin(-V1, arg), 1 - size ); - EXPECT_EQ( arg, size - 1 ); - // binary expression - arg = -1; - EXPECT_EQ( argMin(V1 + 2, arg), 2 ); - EXPECT_EQ( arg, 0 ); + expect_vectors_near( ceil(-(-V1)), expected ); } -TYPED_TEST( VectorUnaryOperationsTest, sum ) +TYPED_TEST( VectorUnaryOperationsTest, sign ) { - SETUP_UNARY_VECTOR_TEST_REDUCTION; + SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, -VECTOR_TEST_SIZE, VECTOR_TEST_SIZE, TNL::sign ); // vector or view - EXPECT_EQ( sum(V1), 0.5 * size * (size - 1) ); - // unary expression - EXPECT_EQ( sum(-V1), - 0.5 * size * (size - 1) ); + expect_vectors_near( sign(V1), expected ); // binary expression - EXPECT_EQ( sum(V1 - 1), 0.5 * size * (size - 1) - size ); + expect_vectors_near( sign(2 * V1 - V1), expected ); + // unary expression + expect_vectors_near( sign(-(-V1)), expected ); } -TYPED_TEST( VectorUnaryOperationsTest, lpNorm ) +TYPED_TEST( VectorUnaryOperationsTest, cast ) { - SETUP_UNARY_VECTOR_TEST( VECTOR_TEST_REDUCTION_SIZE ); - using RealType = typename VectorOrView::RealType; - - const RealType epsilon = 64 * std::numeric_limits< RealType >::epsilon(); - - const RealType expectedL1norm = size; - const RealType expectedL2norm = std::sqrt( size ); - const RealType expectedL3norm = std::cbrt( size ); + auto identity = [](int i) { return i; }; + SETUP_UNARY_VECTOR_TEST_FUNCTION( VECTOR_TEST_SIZE, 1, VECTOR_TEST_SIZE, identity ); // vector or vector view - EXPECT_EQ( lpNorm(V1, 1.0), expectedL1norm ); - EXPECT_EQ( lpNorm(V1, 2.0), expectedL2norm ); - EXPECT_NEAR( lpNorm(V1, 3.0), expectedL3norm, epsilon ); - // unary expression - EXPECT_EQ( lpNorm(-V1, 1.0), expectedL1norm ); - EXPECT_EQ( lpNorm(-V1, 2.0), expectedL2norm ); - EXPECT_NEAR( lpNorm(-V1, 3.0), expectedL3norm, epsilon ); - // binary expression - EXPECT_EQ( lpNorm(2 * V1 - V1, 1.0), expectedL1norm ); - EXPECT_EQ( lpNorm(2 * V1 - V1, 2.0), expectedL2norm ); - EXPECT_NEAR( lpNorm(2 * V1 - V1, 3.0), expectedL3norm, epsilon ); -} + auto expression1 = cast(V1); + static_assert( std::is_same< typename decltype(expression1)::RealType, bool >::value, + "BUG: the cast function does not work for vector or vector view." ); + EXPECT_EQ( expression1, true ); -TYPED_TEST( VectorUnaryOperationsTest, product ) -{ - SETUP_UNARY_VECTOR_TEST( 16 ); + // binary expression + auto expression2( cast(V1 + V1) ); + static_assert( std::is_same< typename decltype(expression2)::RealType, bool >::value, + "BUG: the cast function does not work for binary expression." ); + // FIXME: expression2 cannot be reused, because expression templates for StaticVector and DistributedVector contain references and the test would crash in Release +// EXPECT_EQ( expression2, true ); + EXPECT_EQ( cast(V1 + V1), true ); - // vector or vector view - EXPECT_EQ( product(V2), std::exp2(size) ); // unary expression - EXPECT_EQ( product(-V2), std::exp2(size) * ( (size % 2) ? -1 : 1 ) ); - // binary expression - EXPECT_EQ( product(V1 + V1), std::exp2(size) ); + auto expression3( cast(-V1) ); + static_assert( std::is_same< typename decltype(expression3)::RealType, bool >::value, + "BUG: the cast function does not work for unary expression." ); + // FIXME: expression2 cannot be reused, because expression templates for StaticVector and DistributedVector contain references and the test would crash in Release +// EXPECT_EQ( expression3, true ); + EXPECT_EQ( cast(-V1), true ); } -// TODO: tests for logicalOr, binaryOr, logicalAnd, binaryAnd - } // namespace unary_tests #endif // HAVE_GTEST -#ifndef STATIC_VECTOR +#if !defined(DISTRIBUTED_VECTOR) && !defined(STATIC_VECTOR) #include "../main.h" #endif diff --git a/src/UnitTests/Containers/VectorVerticalOperationsTest.cpp b/src/UnitTests/Containers/VectorVerticalOperationsTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..376d6a0b71cfff6ee5b3f8a8aabf3f6aa730d601 --- /dev/null +++ b/src/UnitTests/Containers/VectorVerticalOperationsTest.cpp @@ -0,0 +1 @@ +#include "VectorVerticalOperationsTest.h" diff --git a/src/UnitTests/Containers/VectorVerticalOperationsTest.cu b/src/UnitTests/Containers/VectorVerticalOperationsTest.cu new file mode 100644 index 0000000000000000000000000000000000000000..376d6a0b71cfff6ee5b3f8a8aabf3f6aa730d601 --- /dev/null +++ b/src/UnitTests/Containers/VectorVerticalOperationsTest.cu @@ -0,0 +1 @@ +#include "VectorVerticalOperationsTest.h" diff --git a/src/UnitTests/Containers/VectorVerticalOperationsTest.h b/src/UnitTests/Containers/VectorVerticalOperationsTest.h new file mode 100644 index 0000000000000000000000000000000000000000..758ee1d50026dd0c23ccbf51f37c268732e5e16b --- /dev/null +++ b/src/UnitTests/Containers/VectorVerticalOperationsTest.h @@ -0,0 +1,338 @@ +/*************************************************************************** + VectorVerticalOperationsTest.h - description + ------------------- + begin : Aug 3, 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 + +#if defined(DISTRIBUTED_VECTOR) + #include + #include + #include + #include + #include +#elif defined(STATIC_VECTOR) + #include +#else + #include + #include +#endif + +#include "VectorHelperFunctions.h" + +#include "gtest/gtest.h" + +using namespace TNL; +using namespace TNL::Containers; +using namespace TNL::Containers::Algorithms; + +namespace vertical_tests { + +// should be small enough to have fast tests, but larger than minGPUReductionDataSize +// and large enough to require multiple CUDA blocks for reduction +constexpr int VECTOR_TEST_REDUCTION_SIZE = 4999; + +// test fixture for typed tests +template< typename T > +class VectorVerticalOperationsTest : public ::testing::Test +{ +protected: + using VectorOrView = T; +#ifdef STATIC_VECTOR + template< typename Real > + using Vector = StaticVector< VectorOrView::getSize(), Real >; +#else + using NonConstReal = std::remove_const_t< typename VectorOrView::RealType >; + #ifdef DISTRIBUTED_VECTOR + using CommunicatorType = typename VectorOrView::CommunicatorType; + using VectorType = DistributedVector< NonConstReal, typename VectorOrView::DeviceType, typename VectorOrView::IndexType, CommunicatorType >; + template< typename Real > + using Vector = DistributedVector< Real, typename VectorOrView::DeviceType, typename VectorOrView::IndexType, CommunicatorType >; + #else + using VectorType = Containers::Vector< NonConstReal, typename VectorOrView::DeviceType, typename VectorOrView::IndexType >; + template< typename Real > + using Vector = Containers::Vector< Real, typename VectorOrView::DeviceType, typename VectorOrView::IndexType >; + #endif +#endif + + VectorOrView V1; + +#ifndef STATIC_VECTOR + VectorType _V1; +#endif + + void reset( int size ) + { +#ifdef STATIC_VECTOR + setLinearSequence( V1 ); +#else + #ifdef DISTRIBUTED_VECTOR + const typename CommunicatorType::CommunicationGroup group = CommunicatorType::AllGroup; + using LocalRangeType = typename VectorOrView::LocalRangeType; + const LocalRangeType localRange = Partitioner< typename VectorOrView::IndexType, CommunicatorType >::splitRange( size, group ); + + const int rank = CommunicatorType::GetRank(group); + const int nproc = CommunicatorType::GetSize(group); + + _V1.setDistribution( localRange, size, group ); + #else + _V1.setSize( size ); + #endif + setLinearSequence( _V1 ); + bindOrAssign( V1, _V1 ); +#endif + } + + VectorVerticalOperationsTest() + { + reset( VECTOR_TEST_REDUCTION_SIZE ); + } +}; + +#define SETUP_VERTICAL_TEST_ALIASES \ + using VectorOrView = typename TestFixture::VectorOrView; \ + VectorOrView& V1 = this->V1; \ + const int size = V1.getSize(); \ + +// types for which VectorVerticalOperationsTest is instantiated +#if defined(DISTRIBUTED_VECTOR) + using VectorTypes = ::testing::Types< + #ifndef HAVE_CUDA + DistributedVector< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVectorView< double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVectorView< const double, Devices::Host, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Host, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< double, Devices::Host, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< const double, Devices::Host, int, Communicators::NoDistrCommunicator > + #else + DistributedVector< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVectorView< double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVectorView< const double, Devices::Cuda, int, Communicators::MpiCommunicator >, + DistributedVector< double, Devices::Cuda, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< double, Devices::Cuda, int, Communicators::NoDistrCommunicator >, + DistributedVectorView< const double, Devices::Cuda, int, Communicators::NoDistrCommunicator > + #endif + >; +#elif defined(STATIC_VECTOR) + using VectorTypes = ::testing::Types< + StaticVector< 1, int >, + StaticVector< 1, double >, + StaticVector< 2, int >, + StaticVector< 2, double >, + StaticVector< 3, int >, + StaticVector< 3, double >, + StaticVector< 4, int >, + StaticVector< 4, double >, + StaticVector< 5, int >, + StaticVector< 5, double > + >; +#else + using VectorTypes = ::testing::Types< + #ifndef HAVE_CUDA + Vector< int, Devices::Host >, + VectorView< int, Devices::Host >, + VectorView< const int, Devices::Host >, + Vector< double, Devices::Host >, + VectorView< double, Devices::Host > + #endif + #ifdef HAVE_CUDA + Vector< int, Devices::Cuda >, + VectorView< int, Devices::Cuda >, + VectorView< const int, Devices::Cuda >, + Vector< double, Devices::Cuda >, + VectorView< double, Devices::Cuda > + #endif + >; +#endif + +TYPED_TEST_SUITE( VectorVerticalOperationsTest, VectorTypes ); + +TYPED_TEST( VectorVerticalOperationsTest, max ) +{ + SETUP_VERTICAL_TEST_ALIASES; + + // vector or view + EXPECT_EQ( max(V1), size - 1 ); + // unary expression + EXPECT_EQ( max(-V1), 0 ); + // binary expression + EXPECT_EQ( max(V1 + 2), size - 1 + 2 ); +} + +TYPED_TEST( VectorVerticalOperationsTest, argMax ) +{ + SETUP_VERTICAL_TEST_ALIASES; + using RealType = typename TestFixture::VectorOrView::RealType; + + // vector or view + EXPECT_EQ( argMax(V1), std::make_pair(size - 1, (RealType) size - 1) ); + // unary expression + EXPECT_EQ( argMax(-V1), std::make_pair(0, (RealType) 0) ); + // expression + EXPECT_EQ( argMax(V1 + 2), std::make_pair(size - 1, (RealType) size - 1 + 2) ); +} + +TYPED_TEST( VectorVerticalOperationsTest, min ) +{ + SETUP_VERTICAL_TEST_ALIASES; + + // vector or view + EXPECT_EQ( min(V1), 0 ); + // unary expression + EXPECT_EQ( min(-V1), 1 - size ); + // binary expression + EXPECT_EQ( min(V1 + 2), 2 ); +} + +TYPED_TEST( VectorVerticalOperationsTest, argMin ) +{ + SETUP_VERTICAL_TEST_ALIASES; + using RealType = typename TestFixture::VectorOrView::RealType; + + // vector or view + EXPECT_EQ( argMin(V1), std::make_pair(0, (RealType) 0) ); + // unary expression + EXPECT_EQ( argMin(-V1), std::make_pair(size - 1, (RealType) 1 - size) ); + // binary expression + EXPECT_EQ( argMin(V1 + 2), std::make_pair(0, (RealType) 2) ); +} + +TYPED_TEST( VectorVerticalOperationsTest, sum ) +{ + SETUP_VERTICAL_TEST_ALIASES; + + // vector or view + EXPECT_EQ( sum(V1), 0.5 * size * (size - 1) ); + // unary expression + EXPECT_EQ( sum(-V1), - 0.5 * size * (size - 1) ); + // binary expression + EXPECT_EQ( sum(V1 - 1), 0.5 * size * (size - 1) - size ); +} + +TYPED_TEST( VectorVerticalOperationsTest, maxNorm ) +{ + SETUP_VERTICAL_TEST_ALIASES; + + // vector or view + EXPECT_EQ( maxNorm(V1), size - 1 ); + // unary expression + EXPECT_EQ( maxNorm(-V1), size - 1 ); + // binary expression + EXPECT_EQ( maxNorm(V1 - size), size ); +} + +TYPED_TEST( VectorVerticalOperationsTest, l1Norm ) +{ +#ifdef STATIC_VECTOR + setConstantSequence( this->V1, 1 ); + const typename TestFixture::VectorOrView& V1( this->V1 ); +#else + // we have to use _V1 because V1 might be a const view + setConstantSequence( this->_V1, 1 ); + const typename TestFixture::VectorOrView& V1( this->_V1 ); +#endif + const int size = V1.getSize(); + + // vector or vector view + EXPECT_EQ( l1Norm(V1), size ); + // unary expression + EXPECT_EQ( l1Norm(-V1), size ); + // binary expression + EXPECT_EQ( l1Norm(2 * V1 - V1), size ); +} + +TYPED_TEST( VectorVerticalOperationsTest, l2Norm ) +{ + using RealType = typename TestFixture::VectorOrView::RealType; +#ifdef STATIC_VECTOR + setConstantSequence( this->V1, 1 ); + const typename TestFixture::VectorOrView& V1( this->V1 ); +#else + // we have to use _V1 because V1 might be a const view + setConstantSequence( this->_V1, 1 ); + const typename TestFixture::VectorOrView& V1( this->_V1 ); +#endif + const int size = V1.getSize(); + + const auto expected = std::sqrt( (RealType) size ); + + // vector or vector view + EXPECT_EQ( l2Norm(V1), expected ); + // unary expression + EXPECT_EQ( l2Norm(-V1), expected ); + // binary expression + EXPECT_EQ( l2Norm(2 * V1 - V1), expected ); +} + +TYPED_TEST( VectorVerticalOperationsTest, lpNorm ) +{ + using RealType = typename TestFixture::VectorOrView::RealType; +#ifdef STATIC_VECTOR + setConstantSequence( this->V1, 1 ); + const typename TestFixture::VectorOrView& V1( this->V1 ); +#else + // we have to use _V1 because V1 might be a const view + setConstantSequence( this->_V1, 1 ); + const typename TestFixture::VectorOrView& V1( this->_V1 ); +#endif + const int size = V1.getSize(); + + const auto expectedL1norm = size; + const auto expectedL2norm = std::sqrt( (RealType) size ); + const auto expectedL3norm = std::cbrt( (RealType) size ); + + const auto epsilon = 64 * std::numeric_limits< decltype(expectedL3norm) >::epsilon(); + + // vector or vector view + EXPECT_EQ( lpNorm(V1, 1.0), expectedL1norm ); + EXPECT_EQ( lpNorm(V1, 2.0), expectedL2norm ); + EXPECT_NEAR( lpNorm(V1, 3.0), expectedL3norm, epsilon ); + // unary expression + EXPECT_EQ( lpNorm(-V1, 1.0), expectedL1norm ); + EXPECT_EQ( lpNorm(-V1, 2.0), expectedL2norm ); + EXPECT_NEAR( lpNorm(-V1, 3.0), expectedL3norm, epsilon ); + // binary expression + EXPECT_EQ( lpNorm(2 * V1 - V1, 1.0), expectedL1norm ); + EXPECT_EQ( lpNorm(2 * V1 - V1, 2.0), expectedL2norm ); + EXPECT_NEAR( lpNorm(2 * V1 - V1, 3.0), expectedL3norm, epsilon ); +} + +TYPED_TEST( VectorVerticalOperationsTest, product ) +{ + // VERY small size to avoid overflows + this->reset( 16 ); + +#ifdef STATIC_VECTOR + setConstantSequence( this->V1, 2 ); + const typename TestFixture::VectorOrView& V2( this->V1 ); +#else + // we have to use _V1 because V1 might be a const view + setConstantSequence( this->_V1, 2 ); + const typename TestFixture::VectorOrView& V2( this->_V1 ); +#endif + const int size = V2.getSize(); + + // vector or vector view + EXPECT_EQ( product(V2), std::exp2(size) ); + // unary expression + EXPECT_EQ( product(-V2), std::exp2(size) * ( (size % 2) ? -1 : 1 ) ); + // binary expression + EXPECT_EQ( product(2 * V2 - V2), std::exp2(size) ); +} + +// TODO: tests for logicalOr, binaryOr, logicalAnd, binaryAnd + +} // namespace vertical_tests + +#endif // HAVE_GTEST + +#if !defined(DISTRIBUTED_VECTOR) && !defined(STATIC_VECTOR) +#include "../main.h" +#endif diff --git a/src/UnitTests/Matrices/DenseMatrixTest.h b/src/UnitTests/Matrices/DenseMatrixTest.h index f1661c997ec528638a5d586cee530e803dfb499f..b796b786c9ca692d93a6b04ec966345249f2f3a8 100644 --- a/src/UnitTests/Matrices/DenseMatrixTest.h +++ b/src/UnitTests/Matrices/DenseMatrixTest.h @@ -1421,7 +1421,7 @@ using MatrixTypes = ::testing::Types #endif >; -TYPED_TEST_CASE( MatrixTest, MatrixTypes ); +TYPED_TEST_SUITE( MatrixTest, MatrixTypes ); TYPED_TEST( MatrixTest, setDimensionsTest ) { diff --git a/src/UnitTests/Matrices/DistributedMatrixTest.h b/src/UnitTests/Matrices/DistributedMatrixTest.h index a2170dd1e97751110cdc5c0edab1a91ec01acdae..7c74e77040e8d554b9ca641d0b9fb9f1e18dc741 100644 --- a/src/UnitTests/Matrices/DistributedMatrixTest.h +++ b/src/UnitTests/Matrices/DistributedMatrixTest.h @@ -11,7 +11,7 @@ void setLinearSequence( Vector& deviceVector, typename Vector::RealType offset = { typename Vector::HostType a; a.setLike( deviceVector ); - for( int i = 0; i < a.getLocalVectorView().getSize(); i++ ) { + for( int i = 0; i < a.getLocalView().getSize(); i++ ) { const auto gi = a.getLocalRange().getGlobalIndex( i ); a[ gi ] = gi + offset; } @@ -108,7 +108,7 @@ using DistributedMatrixTypes = ::testing::Types< #endif >; -TYPED_TEST_CASE( DistributedMatrixTest, DistributedMatrixTypes ); +TYPED_TEST_SUITE( DistributedMatrixTest, DistributedMatrixTypes ); TYPED_TEST( DistributedMatrixTest, checkSumOfLocalSizes ) { @@ -213,8 +213,8 @@ TYPED_TEST( DistributedMatrixTest, vectorProduct_globalInput ) this->matrix.vectorProduct( inVector, outVector ); EXPECT_EQ( outVector, this->rowLengths ) - << "outVector.getLocalVectorView() = " << outVector.getLocalVectorView() - << ",\nthis->rowLengths.getLocalVectorView() = " << this->rowLengths.getLocalVectorView(); + << "outVector.getLocalView() = " << outVector.getLocalView() + << ",\nthis->rowLengths.getLocalView() = " << this->rowLengths.getLocalView(); } TYPED_TEST( DistributedMatrixTest, vectorProduct_distributedInput ) @@ -230,8 +230,8 @@ TYPED_TEST( DistributedMatrixTest, vectorProduct_distributedInput ) this->matrix.vectorProduct( inVector, outVector ); EXPECT_EQ( outVector, this->rowLengths ) - << "outVector.getLocalVectorView() = " << outVector.getLocalVectorView() - << ",\nthis->rowLengths.getLocalVectorView() = " << this->rowLengths.getLocalVectorView(); + << "outVector.getLocalView() = " << outVector.getLocalView() + << ",\nthis->rowLengths.getLocalView() = " << this->rowLengths.getLocalView(); } #endif // HAVE_GTEST diff --git a/src/UnitTests/Matrices/SparseMatrixTest_AdEllpack.h b/src/UnitTests/Matrices/SparseMatrixTest_AdEllpack.h index f6ab325b03b4f989993d58c1cb27f9e3cad38c71..bbdc010e87457b65f2ad871860c27e42f417f48c 100644 --- a/src/UnitTests/Matrices/SparseMatrixTest_AdEllpack.h +++ b/src/UnitTests/Matrices/SparseMatrixTest_AdEllpack.h @@ -56,7 +56,7 @@ using AdEllpackMatrixTypes = ::testing::Types #endif >; -TYPED_TEST_CASE( AdEllpackMatrixTest, AdEllpackMatrixTypes); +TYPED_TEST_SUITE( AdEllpackMatrixTest, AdEllpackMatrixTypes); TYPED_TEST( AdEllpackMatrixTest, setDimensionsTest ) { diff --git a/src/UnitTests/Matrices/SparseMatrixTest_BiEllpack.h b/src/UnitTests/Matrices/SparseMatrixTest_BiEllpack.h index c3dd6abb4e372ff70184075fcb243fd22e3c4cd8..112bf337b681092c48ff44154ec2755e22bf5411 100644 --- a/src/UnitTests/Matrices/SparseMatrixTest_BiEllpack.h +++ b/src/UnitTests/Matrices/SparseMatrixTest_BiEllpack.h @@ -56,7 +56,7 @@ using BiEllpackMatrixTypes = ::testing::Types //#endif >; -TYPED_TEST_CASE( BiEllpackMatrixTest, BiEllpackMatrixTypes); +TYPED_TEST_SUITE( BiEllpackMatrixTest, BiEllpackMatrixTypes); TYPED_TEST( BiEllpackMatrixTest, setDimensionsTest ) { diff --git a/src/UnitTests/Matrices/SparseMatrixTest_CSR.h b/src/UnitTests/Matrices/SparseMatrixTest_CSR.h index 9707f6b8419ba98a3e5153b58ffaebd1d99718c9..cbf1c824ebe0feb9bca6a9051a3fb68984ccd1a7 100644 --- a/src/UnitTests/Matrices/SparseMatrixTest_CSR.h +++ b/src/UnitTests/Matrices/SparseMatrixTest_CSR.h @@ -55,7 +55,7 @@ using CSRMatrixTypes = ::testing::Types #endif >; -TYPED_TEST_CASE( CSRMatrixTest, CSRMatrixTypes); +TYPED_TEST_SUITE( CSRMatrixTest, CSRMatrixTypes); TYPED_TEST( CSRMatrixTest, setDimensionsTest ) { diff --git a/src/UnitTests/Matrices/SparseMatrixTest_ChunkedEllpack.h b/src/UnitTests/Matrices/SparseMatrixTest_ChunkedEllpack.h index 1845255d3ad5e6113cf00b4296e99ca840d25fdc..6717ea85ae02a88c35ad57f4bb7a04cfe8eb58be 100644 --- a/src/UnitTests/Matrices/SparseMatrixTest_ChunkedEllpack.h +++ b/src/UnitTests/Matrices/SparseMatrixTest_ChunkedEllpack.h @@ -60,7 +60,7 @@ using ChEllpackMatrixTypes = ::testing::Types #endif >; -TYPED_TEST_CASE( ChunkedEllpackMatrixTest, ChEllpackMatrixTypes); +TYPED_TEST_SUITE( ChunkedEllpackMatrixTest, ChEllpackMatrixTypes); TYPED_TEST( ChunkedEllpackMatrixTest, setDimensionsTest ) { diff --git a/src/UnitTests/Matrices/SparseMatrixTest_Ellpack.h b/src/UnitTests/Matrices/SparseMatrixTest_Ellpack.h index f20208b7c525dd259549c6d6132582ecd7164654..6ba65df5ef1ef8a6ea73eed5514e0b02b0d90b82 100644 --- a/src/UnitTests/Matrices/SparseMatrixTest_Ellpack.h +++ b/src/UnitTests/Matrices/SparseMatrixTest_Ellpack.h @@ -55,7 +55,7 @@ using EllpackMatrixTypes = ::testing::Types #endif >; -TYPED_TEST_CASE( EllpackMatrixTest, EllpackMatrixTypes ); +TYPED_TEST_SUITE( EllpackMatrixTest, EllpackMatrixTypes ); TYPED_TEST( EllpackMatrixTest, setDimensionsTest ) { diff --git a/src/UnitTests/Matrices/SparseMatrixTest_SlicedEllpack.h b/src/UnitTests/Matrices/SparseMatrixTest_SlicedEllpack.h index 5341847711ee9a9d5194fa17f7e8be57b6fb640c..dc570fc95302a98d77782ba32a8accabeb9a40b1 100644 --- a/src/UnitTests/Matrices/SparseMatrixTest_SlicedEllpack.h +++ b/src/UnitTests/Matrices/SparseMatrixTest_SlicedEllpack.h @@ -55,7 +55,7 @@ using SlicedEllpackMatrixTypes = ::testing::Types #endif >; -TYPED_TEST_CASE( SlicedEllpackMatrixTest, SlicedEllpackMatrixTypes ); +TYPED_TEST_SUITE( SlicedEllpackMatrixTest, SlicedEllpackMatrixTypes ); TYPED_TEST( SlicedEllpackMatrixTest, setDimensionsTest ) {