diff --git a/src/TNL/Containers/DistributedVector.h b/src/TNL/Containers/DistributedVector.h index db4e46e68616244399e85fa7903ebe53a1e30585..be9ff657f1cd3c8ad49bf6af8a0aa09fc9242c6a 100644 --- a/src/TNL/Containers/DistributedVector.h +++ b/src/TNL/Containers/DistributedVector.h @@ -134,8 +134,15 @@ public: void scan( IndexType begin = 0, IndexType end = 0 ); }; +// Enable expression templates for DistributedVector +namespace Expressions { + template< typename Real, typename Device, typename Index, typename Communicator > + struct HasEnabledDistributedExpressionTemplates< DistributedVector< Real, Device, Index, Communicator > > + : std::true_type + {}; +} // namespace Expressions + } // namespace Containers } // namespace TNL #include <TNL/Containers/DistributedVector.hpp> -#include <TNL/Containers/DistributedVectorExpressions.h> diff --git a/src/TNL/Containers/DistributedVectorExpressions.h b/src/TNL/Containers/DistributedVectorExpressions.h deleted file mode 100644 index 0d6d73e670eb2c745d6b4158da8cb8ec1ab165a7..0000000000000000000000000000000000000000 --- a/src/TNL/Containers/DistributedVectorExpressions.h +++ /dev/null @@ -1,936 +0,0 @@ -/*************************************************************************** - DistributedVectorExpressions.h - description - ------------------- - begin : Jul 1, 2019 - copyright : (C) 2019 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once -#ifndef DOXYGEN_ONLY - -#include <TNL/Containers/Expressions/DistributedExpressionTemplates.h> - -#include "DistributedVector.h" - -namespace TNL { -namespace Containers { - -//// -// Addition -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator+( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Addition >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator+( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Addition >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator+( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator+( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator+( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b ); -} - -//// -// Subtraction -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator-( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Subtraction >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator-( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator-( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator-( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator-( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b ); -} - -//// -// Multiplication -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator*( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Multiplication >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator*( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator*( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator*( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator*( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b ); -} - -//// -// Division -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator/( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Division >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator/( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Division >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator/( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator/( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator/( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b ); -} - -//// -// Comparison operations - operator == -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator==( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::EQ( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator==( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::EQ( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool -operator==( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool -operator==( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool -operator==( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); -} - -//// -// Comparison operations - operator != -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator!=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::NE( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator!=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::NE( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool -operator!=( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool -operator!=( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVector< Real2, Device2, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool -operator!=( const DistributedVector< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); -} - -//// -// Comparison operations - operator < -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LT( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator<( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -//// -// Comparison operations - operator <= -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LE( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator<=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -//// -// Comparison operations - operator > -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GT( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator>( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -//// -// Comparison operations - operator >= -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>=( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GE( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>=( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator>=( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -//// -// Minus -template< typename Real, typename Device, typename Index, typename Communicator > -auto -operator-( const DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Expressions::Minus >( a ); -} - -//// -// Scalar product -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -Real -operator,( const DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedExpressionSum( a * b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -Real -operator,( const ET& a, const DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedExpressionSum( a * b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator,( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedExpressionSum( a * b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator,( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedExpressionSum( a * b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator,( const DistributedVector< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedExpressionSum( a * b ); -} - -} //namespace Containers - -//// -// All functions are supposed to be in namespace TNL - -//// -// Min -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -min( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Min >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -min( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -min( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -min( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -min( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -//// -// Max -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -max( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Max >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -max( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -max( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -max( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -max( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -//// -// Dot product - the same as scalar product, just for convenience -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -dot( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return (a, b); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -dot( const ET& a, const Containers::DistributedVector< Real, Device, Index, Communicator >& b ) -{ - return (a, b); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -dot( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return (a, b); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -dot( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVector< Real2, Device, Index, Communicator >& b ) -{ - return (a, b); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -dot( const Containers::DistributedVector< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return (a, b); -} - - -//// -// Abs -template< typename Real, typename Device, typename Index, typename Communicator > -auto -abs( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a ); -} - -//// -// Power -template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType > -auto -pow( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const ExpType& exp ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ExpType, Containers::Expressions::Pow >( a, exp ); -} - -//// -// Exp -template< typename Real, typename Device, typename Index, typename Communicator > -auto -exp( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a ); -} - -//// -// Sqrt -template< typename Real, typename Device, typename Index, typename Communicator > -auto -sqrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a ); -} - -//// -// Cbrt -template< typename Real, typename Device, typename Index, typename Communicator > -auto -cbrt( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a ); -} - -//// -// Log -template< typename Real, typename Device, typename Index, typename Communicator > -auto -log( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a ); -} - -//// -// Log10 -template< typename Real, typename Device, typename Index, typename Communicator > -auto -log10( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a ); -} - -//// -// Log2 -template< typename Real, typename Device, typename Index, typename Communicator > -auto -log2( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a ); -} - -//// -// Sine -template< typename Real, typename Device, typename Index, typename Communicator > -auto -sin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a ); -} - -//// -// Cosine -template< typename Real, typename Device, typename Index, typename Communicator > -auto -cos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a ); -} - -//// -// Tangent -template< typename Real, typename Device, typename Index, typename Communicator > -auto -tan( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a ); -} - -//// -// Asin -template< typename Real, typename Device, typename Index, typename Communicator > -auto -asin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a ); -} - -//// -// Acos -template< typename Real, typename Device, typename Index, typename Communicator > -auto -acos( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a ); -} - -//// -// Atan -template< typename Real, typename Device, typename Index, typename Communicator > -auto -atan( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a ); -} - -//// -// Sinh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -sinh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a ); -} - -//// -// Cosh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -cosh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a ); -} - -//// -// Tanh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -tanh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a ); -} - -//// -// Asinh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -asinh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a ); -} - -//// -// Acosh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -acosh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a ); -} - -//// -// Atanh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -atanh( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a ); -} - -//// -// Floor -template< typename Real, typename Device, typename Index, typename Communicator > -auto -floor( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a ); -} - -//// -// Ceil -template< typename Real, typename Device, typename Index, typename Communicator > -auto -ceil( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a ); -} - -//// -// Sign -template< typename Real, typename Device, typename Index, typename Communicator > -auto -sign( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a ); -} - -//// -// Cast -template< typename ResultType, typename Real, typename Device, typename Index, typename Communicator, - // workaround: templated type alias cannot be declared at block level - template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation > -auto -cast( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a ); -} - -//// -// Vertical operations - min -template< typename Real, - typename Device, - typename Index, typename Communicator > -Real -min( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionMin( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -std::pair< Index, std::decay_t< Real > > -argMin( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionArgMin( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -Real -max( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionMax( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -std::pair< Index, std::decay_t< Real > > -argMax( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionArgMax( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -sum( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionSum( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -maxNorm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return max( abs( a ) ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -l1Norm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionL1Norm( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -l2Norm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return TNL::sqrt( Containers::Expressions::DistributedExpressionL2Norm( a ) ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator, - typename Real2 > -auto -lpNorm( const Containers::DistributedVector< Real, Device, Index, Communicator >& a, const Real2& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( Containers::Expressions::DistributedExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -product( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionProduct( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -logicalOr( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionLogicalOr( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -binaryOr( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionBinaryOr( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -logicalAnd( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionLogicalAnd( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -binaryAnd( const Containers::DistributedVector< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionBinaryAnd( a ); -} - -} // namespace TNL -#endif // DOXYGEN_ONLY diff --git a/src/TNL/Containers/DistributedVectorView.h b/src/TNL/Containers/DistributedVectorView.h index 70452c50d17b8a08004a3ad162005154eb228ba8..72bc7588120d0527f6d4505a231fe37b33ba2dce 100644 --- a/src/TNL/Containers/DistributedVectorView.h +++ b/src/TNL/Containers/DistributedVectorView.h @@ -13,6 +13,7 @@ #pragma once #include <TNL/Containers/DistributedArrayView.h> +#include <TNL/Containers/Expressions/DistributedExpressionTemplates.h> #include <TNL/Containers/VectorView.h> namespace TNL { @@ -137,8 +138,15 @@ public: void scan( IndexType begin = 0, IndexType end = 0 ); }; +// Enable expression templates for DistributedVector +namespace Expressions { + template< typename Real, typename Device, typename Index, typename Communicator > + struct HasEnabledDistributedExpressionTemplates< DistributedVectorView< Real, Device, Index, Communicator > > + : std::true_type + {}; +} // namespace Expressions + } // namespace Containers } // namespace TNL #include <TNL/Containers/DistributedVectorView.hpp> -#include <TNL/Containers/DistributedVectorViewExpressions.h> diff --git a/src/TNL/Containers/DistributedVectorViewExpressions.h b/src/TNL/Containers/DistributedVectorViewExpressions.h deleted file mode 100644 index 27936df1021412705a0728c38e0ed2b82b73231b..0000000000000000000000000000000000000000 --- a/src/TNL/Containers/DistributedVectorViewExpressions.h +++ /dev/null @@ -1,718 +0,0 @@ -/*************************************************************************** - DistributedVectorViewExpressions.h - description - ------------------- - begin : Jun 28, 2019 - copyright : (C) 2019 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once -#ifndef DOXYGEN_ONLY - -#include <TNL/Containers/Expressions/DistributedExpressionTemplates.h> -#include <TNL/Exceptions/NotImplementedError.h> - -#include "DistributedVectorView.h" - -namespace TNL { -namespace Containers { - -//// -// Addition -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator+( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Addition >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator+( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Addition >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator+( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Addition >( a, b ); -} - -//// -// Subtraction -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator-( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Subtraction >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator-( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator-( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Subtraction >( a, b ); -} - -//// -// Multiplication -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator*( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Multiplication >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator*( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator*( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Multiplication >( a, b ); -} - -//// -// Division -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator/( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Expressions::Division >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator/( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Expressions::Division >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator/( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Expressions::Division >( a, b ); -} - -//// -// Comparison operations - operator == -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator==( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::EQ( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator==( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::EQ( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool -operator==( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); -} - -//// -// Comparison operations - operator != -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator!=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::NE( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator!=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::NE( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Communicator > -bool -operator!=( const DistributedVectorView< Real1, Device1, Index, Communicator >& a, const DistributedVectorView< Real2, Device2, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); -} - -//// -// Comparison operations - operator < -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LT( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator<( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -//// -// Comparison operations - operator <= -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::LE( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator<=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -//// -// Comparison operations - operator > -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GT( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator>( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -//// -// Comparison operations - operator >= -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>=( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, ET >::GE( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>=( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< ET, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -bool -operator>=( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -//// -// Minus -template< typename Real, typename Device, typename Index, typename Communicator > -auto -operator-( const DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Expressions::Minus >( a ); -} - -//// -// Scalar product -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator,( const DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Expressions::DistributedExpressionSum( a * b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator,( const ET& a, const DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedExpressionSum( a * b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -operator,( const DistributedVectorView< Real1, Device, Index, Communicator >& a, const DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Expressions::DistributedExpressionSum( a * b ); -} - -} // namespace Containers - -//// -// All functions are supposed to be in namespace TNL - -//// -// Min -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -min( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Min >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -min( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -min( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -//// -// Max -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -max( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, ET, Containers::Expressions::Max >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -max( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< ET, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Communicator > -auto -max( const Containers::DistributedVectorView< Real1, Device, Index, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index, Communicator >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -//// -// Dot product - the same as scalar product, just for convenience -template< typename Real, typename Device, typename Index, typename Communicator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -dot( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ET& b ) -{ - return (a, b); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Communicator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -dot( const ET& a, const Containers::DistributedVectorView< Real, Device, Index, Communicator >& b ) -{ - return (a, b); -} - -template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2, typename Communicator > -auto -dot( const Containers::DistributedVectorView< Real1, Device, Index1, Communicator >& a, const Containers::DistributedVectorView< Real2, Device, Index2, Communicator >& b ) -{ - return (a, b); -} - -//// -// Abs -template< typename Real, typename Device, typename Index, typename Communicator > -auto -abs( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a ); -} - - -//// -// Power -template< typename Real, typename Device, typename Index, typename Communicator, typename ExpType > -auto -pow( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const ExpType& exp ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< Containers::DistributedVectorView< Real, Device, Index, Communicator >, ExpType, Containers::Expressions::Pow >( a, exp ); -} - -//// -// Exp -template< typename Real, typename Device, typename Index, typename Communicator > -auto -exp( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a ); -} - -//// -// Sqrt -template< typename Real, typename Device, typename Index, typename Communicator > -auto -sqrt( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a ); -} - -//// -// Cbrt -template< typename Real, typename Device, typename Index, typename Communicator > -auto -cbrt( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a ); -} - -//// -// Log -template< typename Real, typename Device, typename Index, typename Communicator > -auto -log( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a ); -} - -//// -// Log10 -template< typename Real, typename Device, typename Index, typename Communicator > -auto -log10( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a ); -} - -//// -// Log2 -template< typename Real, typename Device, typename Index, typename Communicator > -auto -log2( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a ); -} - -//// -// Sine -template< typename Real, typename Device, typename Index, typename Communicator > -auto -sin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a ); -} - -//// -// Cosine -template< typename Real, typename Device, typename Index, typename Communicator > -auto -cos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a ); -} - -//// -// Tangent -template< typename Real, typename Device, typename Index, typename Communicator > -auto -tan( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a ); -} - -//// -// Asin -template< typename Real, typename Device, typename Index, typename Communicator > -auto -asin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a ); -} - -//// -// Acos -template< typename Real, typename Device, typename Index, typename Communicator > -auto -acos( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a ); -} - -//// -// Atan -template< typename Real, typename Device, typename Index, typename Communicator > -auto -atan( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a ); -} - -//// -// Sinh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -sinh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a ); -} - -//// -// Cosh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -cosh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a ); -} - -//// -// Tanh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -tanh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a ); -} - -//// -// Asinh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -asinh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a ); -} - -//// -// Acosh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -acosh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a ); -} - -//// -// Atanh -template< typename Real, typename Device, typename Index, typename Communicator > -auto -atanh( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a ); -} - -//// -// Floor -template< typename Real, typename Device, typename Index, typename Communicator > -auto -floor( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a ); -} - -//// -// Ceil -template< typename Real, typename Device, typename Index, typename Communicator > -auto -ceil( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a ); -} - -//// -// Sign -template< typename Real, typename Device, typename Index, typename Communicator > -auto -sign( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a ); -} - -//// -// Cast -template< typename ResultType, typename Real, typename Device, typename Index, typename Communicator, - // workaround: templated type alias cannot be declared at block level - template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation > -auto -cast( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a ); -} - -//// -// Vertical operations - min -template< typename Real, typename Device, typename Index, typename Communicator > -Real -min( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionMin( a ); -} - -template< typename Real, typename Device, typename Index, typename Communicator > -std::pair< Index, std::decay_t< Real > > -argMin( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionArgMin( a ); -} - -template< typename Real, typename Device, typename Index, typename Communicator > -Real -max( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionMax( a ); -} - -template< typename Real, typename Device, typename Index, typename Communicator > -std::pair< Index, std::decay_t< Real > > -argMax( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionArgMax( a ); -} - -template< typename Real, typename Device, typename Index, typename Communicator > -auto -sum( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionSum( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -maxNorm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return max( abs( a ) ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -l1Norm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionL1Norm( a ); -} - -template< typename Real, - typename Device, - typename Index, typename Communicator > -auto -l2Norm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return TNL::sqrt( Containers::Expressions::DistributedExpressionL2Norm( a ) ); -} - -template< typename Real, typename Device, typename Index, typename Communicator, typename Real2 > -auto -lpNorm( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a, const Real2& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( Containers::Expressions::DistributedExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< typename Real, typename Device, typename Index, typename Communicator > -auto -product( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionProduct( a ); -} - -template< typename Real, typename Device, typename Index, typename Communicator > -auto -logicalOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionLogicalOr( a ); -} - -template< typename Real, typename Device, typename Index, typename Communicator > -auto -binaryOr( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionBinaryOr( a ); -} - -template< typename Real, typename Device, typename Index, typename Communicator > -auto -logicalAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionLogicalAnd( a ); -} - -template< typename Real, typename Device, typename Index, typename Communicator > -auto -binaryAnd( const Containers::DistributedVectorView< Real, Device, Index, Communicator >& a ) -{ - return Containers::Expressions::DistributedExpressionBinaryAnd( a ); -} - -} // namespace TNL -#endif // DOXYGEN_ONLY diff --git a/src/TNL/Containers/Expressions/Comparison.h b/src/TNL/Containers/Expressions/Comparison.h index 98e39ad8c561240f2ac0522844dd362059ebf710..40b823a1840e6b5d5458f18bbf3e2e9341b2403c 100644 --- a/src/TNL/Containers/Expressions/Comparison.h +++ b/src/TNL/Containers/Expressions/Comparison.h @@ -25,13 +25,14 @@ namespace Expressions { // Non-static comparison template< typename T1, typename T2, - ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, - ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > + ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(), + ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() > struct Comparison; template< typename T1, typename T2, - bool BothAreVectors = IsArrayType< T1 >::value && IsArrayType< T2 >::value > + bool BothAreNonstaticVectors = IsArrayType< T1 >::value && IsArrayType< T2 >::value && + ! IsStaticArrayType< T1 >::value && ! IsStaticArrayType< T2 >::value > struct VectorComparison; // If both operands are vectors we compare them using array operations. @@ -64,7 +65,9 @@ struct VectorComparison< T1, T2, false > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] == b[ i ]; }; + const auto view_a = a.getConstView(); + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] == view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } }; @@ -94,7 +97,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] > b[ i ]; }; + const auto view_a = a.getConstView(); + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] > view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } @@ -107,7 +112,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] >= b[ i ]; }; + const auto view_a = a.getConstView(); + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] >= view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } @@ -120,7 +127,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] < b[ i ]; }; + const auto view_a = a.getConstView(); + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] < view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } @@ -133,7 +142,9 @@ struct Comparison< T1, T2, VectorExpressionVariable, VectorExpressionVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] <= b[ i ]; }; + const auto view_a = a.getConstView(); + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] <= view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } }; @@ -149,7 +160,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a == b[ i ]; }; + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a == view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true ); } @@ -163,7 +175,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a > b[ i ]; }; + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a > view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true ); } @@ -172,7 +185,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a >= b[ i ]; }; + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a >= view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true ); } @@ -181,7 +195,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a < b[ i ]; }; + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a < view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true ); } @@ -190,7 +205,8 @@ struct Comparison< T1, T2, ArithmeticVariable, VectorExpressionVariable > using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a <= b[ i ]; }; + const auto view_b = b.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a <= view_b[ i ]; }; return Algorithms::Reduction< DeviceType >::reduce( b.getSize(), std::logical_and<>{}, fetch, true ); } }; @@ -206,7 +222,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] == b; }; + const auto view_a = a.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] == b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } @@ -220,7 +237,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] > b; }; + const auto view_a = a.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] > b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } @@ -229,7 +247,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] >= b; }; + const auto view_a = a.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] >= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } @@ -238,7 +257,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] < b; }; + const auto view_a = a.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] < b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } @@ -247,7 +267,8 @@ struct Comparison< T1, T2, VectorExpressionVariable, ArithmeticVariable > using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return a[ i ] <= b; }; + const auto view_a = a.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) -> bool { return view_a[ i ] <= b; }; return Algorithms::Reduction< DeviceType >::reduce( a.getSize(), std::logical_and<>{}, fetch, true ); } }; diff --git a/src/TNL/Containers/Expressions/DistributedComparison.h b/src/TNL/Containers/Expressions/DistributedComparison.h index b5e0e96a9d756f55edb7bf15652ad1d0d34bc5d6..4cecc92bb9b3823db92df893c289c0233d26bb14 100644 --- a/src/TNL/Containers/Expressions/DistributedComparison.h +++ b/src/TNL/Containers/Expressions/DistributedComparison.h @@ -21,8 +21,8 @@ namespace Expressions { // Non-static comparison template< typename T1, typename T2, - ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, - ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > + ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(), + ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() > struct DistributedComparison; ///// diff --git a/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h b/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h index 355689039884e8e05caff040e232ffbcf26119ba..27c92e0e92cdaf2338cf62d15d266d096fede6b0 100644 --- a/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h +++ b/src/TNL/Containers/Expressions/DistributedExpressionTemplates.h @@ -22,15 +22,12 @@ namespace Expressions { //// // Distributed unary expression template template< typename T1, - template< typename > class Operation, - ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value > -struct DistributedUnaryExpressionTemplate -{}; + template< typename > class Operation > +struct DistributedUnaryExpressionTemplate; template< typename T1, - template< typename > class Operation, - ExpressionVariableType T1Type > -struct IsExpressionTemplate< DistributedUnaryExpressionTemplate< T1, Operation, T1Type > > + template< typename > class Operation > +struct HasEnabledDistributedExpressionTemplates< DistributedUnaryExpressionTemplate< T1, Operation > > : std::true_type {}; @@ -39,8 +36,8 @@ struct IsExpressionTemplate< DistributedUnaryExpressionTemplate< T1, Operation, template< typename T1, typename T2, template< typename, typename > class Operation, - ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, - ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > + ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(), + ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() > struct DistributedBinaryExpressionTemplate {}; @@ -49,7 +46,7 @@ template< typename T1, template< typename, typename > class Operation, ExpressionVariableType T1Type, ExpressionVariableType T2Type > -struct IsExpressionTemplate< DistributedBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > > +struct HasEnabledDistributedExpressionTemplates< DistributedBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > > : std::true_type {}; @@ -234,7 +231,7 @@ protected: // Distributed unary expression template template< typename T1, template< typename > class Operation > -struct DistributedUnaryExpressionTemplate< T1, Operation, VectorExpressionVariable > +struct DistributedUnaryExpressionTemplate { using RealType = decltype( Operation< typename T1::RealType >:: evaluate( std::declval<T1>()[0] ) ); @@ -284,1909 +281,649 @@ protected: const T1& operand; }; +#ifndef DOXYGEN_ONLY + //// -// Output stream -template< typename T1, - typename T2, - template< typename, typename > class Operation > -std::ostream& operator<<( std::ostream& str, const DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression ) +// Binary expressions addition +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > +auto +operator+( const ET1& a, const ET2& b ) { - str << "[ "; - for( int i = 0; i < expression.getSize() - 1; i++ ) - str << expression.getElement( i ) << ", "; - str << expression.getElement( expression.getSize() - 1 ) << " ]"; - return str; + return DistributedBinaryExpressionTemplate< ET1, ET2, Addition >( a, b ); } -template< typename T, - template< typename > class Operation > -std::ostream& operator<<( std::ostream& str, const DistributedUnaryExpressionTemplate< T, Operation >& expression ) +//// +// Binary expression subtraction +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > +auto +operator-( const ET1& a, const ET2& b ) { - str << "[ "; - for( int i = 0; i < expression.getSize() - 1; i++ ) - str << expression.getElement( i ) << ", "; - str << expression.getElement( expression.getSize() - 1 ) << " ]"; - return str; + return DistributedBinaryExpressionTemplate< ET1, ET2, Subtraction >( a, b ); } //// -// Operators are supposed to be in the same namespace as the expression templates - -#ifndef DOXYGEN_ONLY - -//// -// Binary expressions addition -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Binary expression multiplication +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > auto -operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +operator*( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return DistributedBinaryExpressionTemplate< ET1, ET2, Multiplication >( a, b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Binary expression division +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > auto -operator+( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +operator/( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return DistributedBinaryExpressionTemplate< ET1, ET2, Division >( a, b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -auto -operator+( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) +//// +// Comparison operator == +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > +bool +operator==( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return DistributedComparison< ET1, ET2 >::EQ( a, b ); } -template< typename T1, - template< typename > class Operation > -auto -operator+( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) +//// +// Comparison operator != +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > +bool +operator!=( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return DistributedComparison< ET1, ET2 >::NE( a, b ); } -template< typename T1, - template< typename > class Operation > -auto -operator+( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) +//// +// Comparison operator < +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > +bool +operator<( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return DistributedComparison< ET1, ET2 >::LT( a, b ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -operator+( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +//// +// Comparison operator <= +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > +bool +operator<=( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return DistributedComparison< ET1, ET2 >::LE( a, b ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -operator+( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +//// +// Comparison operator > +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > +bool +operator>( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return DistributedComparison< ET1, ET2 >::GT( a, b ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -operator+( const DistributedUnaryExpressionTemplate< L1,LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +//// +// Comparison operator >= +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > +bool +operator>=( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return DistributedComparison< ET1, ET2 >::GE( a, b ); } //// -// Binary expression subtraction -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Scalar product +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > auto -operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +operator,( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return DistributedExpressionSum( a * b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > auto -operator-( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +dot( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return (a, b); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Unary expression minus +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator-( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) +operator-( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Minus >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Binary expression min +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > auto -operator-( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) +min( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return DistributedBinaryExpressionTemplate< ET1, ET2, Min >( a, b ); } -template< typename T1, - template< typename > class Operation > +//// +// Binary expression max +template< typename ET1, typename ET2, + typename..., typename = EnableIfDistributedBinaryExpression_t< ET1, ET2 >, typename = void, typename = void > auto -operator-( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) +max( const ET1& a, const ET2& b ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return DistributedBinaryExpressionTemplate< ET1, ET2, Max >( a, b ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Abs +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator-( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +abs( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Abs >( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Pow +template< typename ET1, typename Real, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +pow( const ET1& a, const Real& exp ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return DistributedBinaryExpressionTemplate< ET1, Real, Pow >( a, exp ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Exp +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator-( const DistributedUnaryExpressionTemplate< L1,LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +exp( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Exp >( a ); } //// -// Binary expression multiplication -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Sqrt +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +sqrt( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Sqrt >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Cbrt +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator*( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +cbrt( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Cbrt >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Log +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator*( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) +log( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Log >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Log10 +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator*( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) +log10( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Log10 >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Log2 +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator*( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) +log2( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Log2 >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Sin +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator*( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +sin( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Sin >( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Cos +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator*( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) +cos( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Cos >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Tan +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator*( const DistributedUnaryExpressionTemplate< L1,LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +tan( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Tan >( a ); } //// -// Binary expression division -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Asin +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +asin( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Asin >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Acos +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator/( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +acos( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Acos >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Atan +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator/( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) +atan( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Atan >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Sinh +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator/( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) +sinh( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Sinh >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Cosh +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator/( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) +cosh( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Cosh >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Tanh +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator/( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +tanh( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Tanh >( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Asinh +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator/( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +asinh( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Asinh >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Acosh +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > auto -operator/( const DistributedUnaryExpressionTemplate< L1,LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +acosh( const ET1& a ) { - return DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Acosh >( a ); } //// -// Comparison operator == -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +// Atanh +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +atanh( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Atanh >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator==( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +//// +// Floor +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +floor( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Floor >( a ); } -template< typename T1, - template< typename > class Operation > -bool -operator==( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) +//// +// Ceil +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +ceil( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Ceil >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator==( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) +//// +// Sign +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +sign( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return DistributedUnaryExpressionTemplate< ET1, Sign >( a ); } -template< typename T1, - template< typename > class Operation > -bool -operator==( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) +//// +// Cast +template< typename ResultType, + typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, + // workaround: templated type alias cannot be declared at block level + template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation, + typename = void, typename = void > +auto +cast( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return DistributedUnaryExpressionTemplate< ET1, CastOperation >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator==( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +//// +// Vertical operations +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +min( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return DistributedExpressionMin( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator==( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +argMin( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return DistributedExpressionArgMin( a ); } -//// -// Comparison operator != -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +max( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return DistributedExpressionMax( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator!=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +argMax( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return DistributedExpressionArgMax( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +sum( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return DistributedExpressionSum( a ); } -template< typename T1, - template< typename > class Operation > -bool -operator!=( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +maxNorm( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return max( abs( a ) ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator!=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +l1Norm( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return sum( abs( a ) ); } -template< typename T1, - template< typename > class Operation > -bool -operator!=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +l2Norm( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + using TNL::sqrt; + return sqrt( sum( a * a ) ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator!=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +template< typename ET1, + typename Real, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +lpNorm( const ET1& a, const Real& p ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + if( p == 1.0 ) + return l1Norm( a ); + if( p == 2.0 ) + return l2Norm( a ); + using TNL::pow; + return pow( sum( pow( abs( a ), p ) ), 1.0 / p ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator!=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +product( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return DistributedExpressionProduct( a ); } -//// -// Comparison operator < -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +logicalOr( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return DistributedExpressionLogicalOr( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator<( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +logicalAnd( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return DistributedExpressionLogicalAnd( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator<( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +binaryOr( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return DistributedExpressionBinaryOr( a ); } -template< typename T1, - template< typename > class Operation > -bool -operator<( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) +template< typename ET1, + typename..., typename = EnableIfDistributedUnaryExpression_t< ET1 >, typename = void, typename = void > +auto +binaryAnd( const ET1& a ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return DistributedExpressionBinaryAnd( a ); } +//// +// Output stream template< typename T1, typename T2, template< typename, typename > class Operation > -bool -operator<( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) +std::ostream& operator<<( std::ostream& str, const DistributedBinaryExpressionTemplate< T1, T2, Operation >& expression ) { - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + str << "[ "; + for( int i = 0; i < expression.getSize() - 1; i++ ) + str << expression.getElement( i ) << ", "; + str << expression.getElement( expression.getSize() - 1 ) << " ]"; + return str; } -template< typename T1, - template< typename > class Operation > -bool -operator<( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator<( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator<( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -//// -// Comparison operator <= -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator<=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator<=( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator<=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator<=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator<=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator<=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -//// -// Comparison operator > -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator>( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator>( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator>( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator>( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator>( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator>( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -//// -// Comparison operator >= -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator>=( const DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator>=( const DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator>=( const typename DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, +template< typename T, template< typename > class Operation > -bool -operator>=( const typename DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const DistributedUnaryExpressionTemplate< T1, Operation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator>=( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator>=( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return DistributedComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -//// -// Unary operations - -//// -// Minus -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -operator-( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -operator-( const DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a ); -} - -//// -// Scalar product -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return DistributedExpressionSum( a * b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -operator,( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1, ROperation >& b ) -{ - return DistributedExpressionSum( a * b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -operator,( const DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return DistributedExpressionSum( a * b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -operator,( const DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const DistributedUnaryExpressionTemplate< R1,ROperation >& b ) +std::ostream& operator<<( std::ostream& str, const DistributedUnaryExpressionTemplate< T, Operation >& expression ) { - return DistributedExpressionSum( a * b ); + str << "[ "; + for( int i = 0; i < expression.getSize() - 1; i++ ) + str << expression.getElement( i ) << ", "; + str << expression.getElement( expression.getSize() - 1 ) << " ]"; + return str; } #endif // DOXYGEN_ONLY } // namespace Expressions -} // namespace Containers - -//// -// All operations are supposed to be in namespace TNL - -#ifndef DOXYGEN_ONLY - -//// -// Binary expression min -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -auto -min( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -auto -min( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -auto -min( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -auto -min( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const typename Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -//// -// Binary expression max -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -auto -max( const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -auto -max( const typename Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -auto -max( const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& a, - const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} -template< typename T1, - template< typename > class Operation > -auto -max( const typename Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >::RealType& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< T1, Operation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} +// Make all operators visible in the TNL::Containers namespace to be considered +// even for DistributedVector and DistributedVectorView +using Expressions::operator+; +using Expressions::operator-; +using Expressions::operator*; +using Expressions::operator/; +using Expressions::operator,; +using Expressions::operator==; +using Expressions::operator!=; +using Expressions::operator<; +using Expressions::operator<=; +using Expressions::operator>; +using Expressions::operator>=; + +// Make all functions visible in the TNL::Containers namespace +using Expressions::dot; +using Expressions::min; +using Expressions::max; +using Expressions::abs; +using Expressions::pow; +using Expressions::exp; +using Expressions::sqrt; +using Expressions::cbrt; +using Expressions::log; +using Expressions::log10; +using Expressions::log2; +using Expressions::sin; +using Expressions::cos; +using Expressions::tan; +using Expressions::asin; +using Expressions::acos; +using Expressions::atan; +using Expressions::sinh; +using Expressions::cosh; +using Expressions::tanh; +using Expressions::asinh; +using Expressions::acosh; +using Expressions::atanh; +using Expressions::floor; +using Expressions::ceil; +using Expressions::sign; +using Expressions::cast; +using Expressions::argMin; +using Expressions::argMax; +using Expressions::sum; +using Expressions::maxNorm; +using Expressions::l1Norm; +using Expressions::l2Norm; +using Expressions::lpNorm; +using Expressions::product; +using Expressions::logicalAnd; +using Expressions::logicalOr; +using Expressions::binaryAnd; +using Expressions::binaryOr; -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1,LOperation >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -//// -// Abs -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -abs( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -abs( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a ); -} - -//// -// Pow -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename Real > -auto -pow( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp ); -} - -template< typename L1, - template< typename > class LOperation, - typename Real > -auto -pow( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, const Real& exp ) -{ - return Containers::Expressions::DistributedBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp ); -} - -//// -// Exp -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -exp( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -exp( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a ); -} - -//// -// Sqrt -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sqrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sqrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a ); -} - -//// -// Cbrt -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -cbrt( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -cbrt( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a ); -} - -//// -// Log -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -log( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -log( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a ); -} - -//// -// Log10 -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -log10( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -log10( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a ); -} - -//// -// Log2 -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -log2( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -log2( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a ); -} - -//// -// Sin -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a ); -} - -//// -// Cos -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -cos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -cos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a ); -} - -//// -// Tan -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -tan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -tan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a ); -} - -//// -// Asin -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -asin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -asin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a ); -} - -//// -// Acos -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -acos( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -acos( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a ); -} - -//// -// Atan -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -atan( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -atan( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a ); -} - -//// -// Sinh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sinh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sinh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a ); -} - -//// -// Cosh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -cosh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -cosh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a ); -} - -//// -// Tanh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -tanh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -tanh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a ); -} - -//// -// Asinh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -asinh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -asinh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a ); -} - -//// -// Acosh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -acosh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -acosh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a ); -} - -//// -// Atanh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -atanh( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -atanh( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a ); -} - -//// -// Floor -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -floor( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -floor( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a ); -} - -//// -// Ceil -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -ceil( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -ceil( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a ); -} - -//// -// Sign -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sign( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sign( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a ); -} - -//// -// Cast -template< typename ResultType, - typename L1, - typename L2, - template< typename, typename > class LOperation, - // workaround: templated type alias cannot be declared at block level - template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > -auto -cast( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a ); -} - -template< typename ResultType, - typename L1, - template< typename > class LOperation, - // workaround: templated type alias cannot be declared at block level - template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > -auto -cast( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::DistributedUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a ); -} - -//// -// Vertical operations - min -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -min( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionMin( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -min( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionMin( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -argMin( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionArgMin( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -argMin( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionArgMin( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -max( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionMax( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -max( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionMax( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -argMax( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionArgMax( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -argMax( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionArgMax( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sum( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionSum( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sum( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionSum( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -maxNorm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return max( abs( a ) ); -} - -template< typename L1, - template< typename > class LOperation > -auto -maxNorm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return max( abs( a ) ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -l1Norm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionL1Norm( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -l1Norm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionL1Norm( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -l2Norm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return TNL::sqrt( DistributedExpressionL2Norm( a ) ); -} - -template< typename L1, - template< typename > class LOperation > -auto -l2Norm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return TNL::sqrt( DistributedExpressionL2Norm( a ) ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename Real > -auto -lpNorm( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( DistributedExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< typename L1, - template< typename > class LOperation, - typename Real > -auto -lpNorm( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, const Real& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( DistributedExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -product( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionProduct( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -product( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionProduct( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -logicalOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionLogicalOr( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -logicalOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionLogicalOr( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -logicalAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionLogicalAnd( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -logicalAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionLogicalAnd( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -binaryOr( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionBinaryOr( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -binaryOr( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionBinaryOr( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -binaryAnd( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return DistributedExpressionBinaryAnd( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -binaryAnd( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return DistributedExpressionBinaryAnd( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return (a, b); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation >& b ) -{ - return (a, b); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -dot( const Containers::Expressions::DistributedUnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::DistributedBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return (a, b); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -dot( const Containers::Expressions::DistributedBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::DistributedUnaryExpressionTemplate< R1, ROperation >& b ) -{ - return (a, b); -} - -#endif // DOXYGEN_ONLY +} // namespace Containers +// Make all functions visible in the main TNL namespace +using Containers::dot; +using Containers::min; +using Containers::max; +using Containers::abs; +using Containers::pow; +using Containers::exp; +using Containers::sqrt; +using Containers::cbrt; +using Containers::log; +using Containers::log10; +using Containers::log2; +using Containers::sin; +using Containers::cos; +using Containers::tan; +using Containers::asin; +using Containers::acos; +using Containers::atan; +using Containers::sinh; +using Containers::cosh; +using Containers::tanh; +using Containers::asinh; +using Containers::acosh; +using Containers::atanh; +using Containers::floor; +using Containers::ceil; +using Containers::sign; +using Containers::cast; +using Containers::argMin; +using Containers::argMax; +using Containers::sum; +using Containers::maxNorm; +using Containers::l1Norm; +using Containers::l2Norm; +using Containers::lpNorm; +using Containers::product; +using Containers::logicalAnd; +using Containers::logicalOr; +using Containers::binaryAnd; +using Containers::binaryOr; //// // Evaluation with reduction diff --git a/src/TNL/Containers/Expressions/DistributedVerticalOperations.h b/src/TNL/Containers/Expressions/DistributedVerticalOperations.h index 43940417bb0aa7fa97afe17e4fee3e4ce703a819..178a5c03c50a36ff9c62e35e38a4a0aa68860532 100644 --- a/src/TNL/Containers/Expressions/DistributedVerticalOperations.h +++ b/src/TNL/Containers/Expressions/DistributedVerticalOperations.h @@ -148,51 +148,6 @@ auto DistributedExpressionSum( const Expression& expression ) -> std::decay_t< d return result; } -template< typename Expression > -auto DistributedExpressionL1Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] ) > -{ - using ResultType = std::decay_t< decltype( expression[0] ) >; - using IndexType = typename Expression::IndexType; - using CommunicatorType = typename Expression::CommunicatorType; - - ResultType result = 0; - if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const ResultType localResult = ExpressionL1Norm( expression.getConstLocalView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() ); - } - return result; -} - -template< typename Expression > -auto DistributedExpressionL2Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) > -{ - using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >; - using IndexType = typename Expression::IndexType; - using CommunicatorType = typename Expression::CommunicatorType; - - ResultType result = 0; - if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const ResultType localResult = ExpressionL2Norm( expression.getConstLocalView() ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() ); - } - return result; -} - -template< typename Expression, typename Real > -auto DistributedExpressionLpNorm( const Expression& expression, const Real& p ) -> std::decay_t< decltype( TNL::pow( expression[0], p ) ) > -{ - using ResultType = std::decay_t< decltype( TNL::pow( expression[0], p ) ) >; - using IndexType = typename Expression::IndexType; - using CommunicatorType = typename Expression::CommunicatorType; - - ResultType result = 0; - if( expression.getCommunicationGroup() != CommunicatorType::NullGroup ) { - const ResultType localResult = ExpressionLpNorm( expression.getConstLocalView(), p ); - CommunicatorType::Allreduce( &localResult, &result, 1, MPI_SUM, expression.getCommunicationGroup() ); - } - return result; -} - template< typename Expression > auto DistributedExpressionProduct( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) > { diff --git a/src/TNL/Containers/Expressions/ExpressionTemplates.h b/src/TNL/Containers/Expressions/ExpressionTemplates.h index a0980baf6cf8ee751444df7d27205dfa9260f593..0cbb69342cb035c26dd2e4fc2740ae3d568afbf5 100644 --- a/src/TNL/Containers/Expressions/ExpressionTemplates.h +++ b/src/TNL/Containers/Expressions/ExpressionTemplates.h @@ -24,40 +24,35 @@ namespace TNL { namespace Containers { namespace Expressions { -//// -// Non-static unary expression template template< typename T1, - template< typename > class Operation, - ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value > -struct UnaryExpressionTemplate -{}; + template< typename > class Operation > +struct UnaryExpressionTemplate; template< typename T1, - template< typename > class Operation, - ExpressionVariableType T1Type > -struct IsExpressionTemplate< UnaryExpressionTemplate< T1, Operation, T1Type > > + template< typename > class Operation > +struct HasEnabledExpressionTemplates< UnaryExpressionTemplate< T1, Operation > > : std::true_type {}; -//// -// Non-static binary expression template template< typename T1, typename T2, template< typename, typename > class Operation, - ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, - ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > -struct BinaryExpressionTemplate -{}; + ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(), + ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() > +struct BinaryExpressionTemplate; template< typename T1, typename T2, template< typename, typename > class Operation, ExpressionVariableType T1Type, ExpressionVariableType T2Type > -struct IsExpressionTemplate< BinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > > +struct HasEnabledExpressionTemplates< BinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > > : std::true_type {}; + +//// +// Non-static binary expression template template< typename T1, typename T2, template< typename, typename > class Operation > @@ -67,6 +62,7 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ve evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; + using ConstViewType = BinaryExpressionTemplate; static_assert( std::is_same< typename T1::DeviceType, typename T2::DeviceType >::value, "Attempt to mix operands which have different DeviceType." ); @@ -74,7 +70,7 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ve "Attempt to mix static and non-static operands in binary expression templates." ); BinaryExpressionTemplate( const T1& a, const T2& b ) - : op1( a ), op2( b ) + : op1( a.getConstView() ), op2( b.getConstView() ) { TNL_ASSERT_EQ( op1.getSize(), op2.getSize(), "Attempt to mix operands with different sizes." ); @@ -97,9 +93,14 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ve return op1.getSize(); } + ConstViewType getConstView() const + { + return *this; + } + protected: - const T1 op1; - const T2 op2; + const typename T1::ConstViewType op1; + const typename T2::ConstViewType op2; }; template< typename T1, @@ -111,9 +112,10 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ar evaluate( std::declval<T1>()[0], std::declval<T2>() ) ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; + using ConstViewType = BinaryExpressionTemplate; BinaryExpressionTemplate( const T1& a, const T2& b ) - : op1( a ), op2( b ) {} + : op1( a.getConstView() ), op2( b ) {} RealType getElement( const IndexType i ) const { @@ -132,8 +134,13 @@ struct BinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, Ar return op1.getSize(); } + ConstViewType getConstView() const + { + return *this; + } + protected: - const T1 op1; + const typename T1::ConstViewType op1; const T2 op2; }; @@ -146,9 +153,10 @@ struct BinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorEx evaluate( std::declval<T1>(), std::declval<T2>()[0] ) ); using DeviceType = typename T2::DeviceType; using IndexType = typename T2::IndexType; + using ConstViewType = BinaryExpressionTemplate; BinaryExpressionTemplate( const T1& a, const T2& b ) - : op1( a ), op2( b ) {} + : op1( a ), op2( b.getConstView() ) {} RealType getElement( const IndexType i ) const { @@ -167,24 +175,30 @@ struct BinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, VectorEx return op2.getSize(); } + ConstViewType getConstView() const + { + return *this; + } + protected: const T1 op1; - const T2 op2; + const typename T2::ConstViewType op2; }; //// // Non-static unary expression template template< typename T1, template< typename > class Operation > -struct UnaryExpressionTemplate< T1, Operation, VectorExpressionVariable > +struct UnaryExpressionTemplate { using RealType = decltype( Operation< typename T1::RealType >:: evaluate( std::declval<T1>()[0] ) ); using DeviceType = typename T1::DeviceType; using IndexType = typename T1::IndexType; + using ConstViewType = UnaryExpressionTemplate; UnaryExpressionTemplate( const T1& a ) - : operand( a ) {} + : operand( a.getConstView() ) {} RealType getElement( const IndexType i ) const { @@ -203,1913 +217,658 @@ struct UnaryExpressionTemplate< T1, Operation, VectorExpressionVariable > return operand.getSize(); } + ConstViewType getConstView() const + { + return *this; + } + protected: - const T1 operand; + const typename T1::ConstViewType operand; }; +#ifndef DOXYGEN_ONLY + //// -// Output stream -template< typename T1, - typename T2, - template< typename, typename > class Operation > -std::ostream& operator<<( std::ostream& str, const BinaryExpressionTemplate< T1, T2, Operation >& expression ) +// Binary expressions addition +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > +auto +operator+( const ET1& a, const ET2& b ) { - str << "[ "; - for( int i = 0; i < expression.getSize() - 1; i++ ) - str << expression.getElement( i ) << ", "; - str << expression.getElement( expression.getSize() - 1 ) << " ]"; - return str; + return BinaryExpressionTemplate< ET1, ET2, Addition >( a, b ); } -template< typename T, - template< typename > class Operation > -std::ostream& operator<<( std::ostream& str, const UnaryExpressionTemplate< T, Operation >& expression ) +//// +// Binary expression subtraction +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > +auto +operator-( const ET1& a, const ET2& b ) { - str << "[ "; - for( int i = 0; i < expression.getSize() - 1; i++ ) - str << expression.getElement( i ) << ", "; - str << expression.getElement( expression.getSize() - 1 ) << " ]"; - return str; + return BinaryExpressionTemplate< ET1, ET2, Subtraction >( a, b ); } //// -// Operators are supposed to be in the same namespace as the expression templates - -#ifndef DOXYGEN_ONLY - -//// -// Binary expressions addition -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Binary expression multiplication +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > auto -operator+( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +operator*( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return BinaryExpressionTemplate< ET1, ET2, Multiplication >( a, b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Binary expression division +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > auto -operator+( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +operator/( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return BinaryExpressionTemplate< ET1, ET2, Division >( a, b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -auto -operator+( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) +//// +// Comparison operator == +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > +bool +operator==( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return Comparison< ET1, ET2 >::EQ( a, b ); } -template< typename T1, - template< typename > class Operation > -auto -operator+( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) +//// +// Comparison operator != +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > +bool +operator!=( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return Comparison< ET1, ET2 >::NE( a, b ); } -template< typename T1, - template< typename > class Operation > -auto -operator+( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) +//// +// Comparison operator < +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > +bool +operator<( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return Comparison< ET1, ET2 >::LT( a, b ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -operator+( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +//// +// Comparison operator <= +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > +bool +operator<=( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return Comparison< ET1, ET2 >::LE( a, b ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -operator+( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +//// +// Comparison operator > +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > +bool +operator>( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return Comparison< ET1, ET2 >::GT( a, b ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -operator+( const UnaryExpressionTemplate< L1,LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +//// +// Comparison operator >= +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > +bool +operator>=( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return Comparison< ET1, ET2 >::GE( a, b ); } //// -// Binary expression subtraction -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Scalar product +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > auto -operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +operator,( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return ExpressionSum( a * b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > auto -operator-( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +dot( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return (a, b); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Unary expression minus +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator-( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) +operator-( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return UnaryExpressionTemplate< ET1, Minus >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Binary expression min +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > auto -operator-( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) +min( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return BinaryExpressionTemplate< ET1, ET2, Min >( a, b ); } -template< typename T1, - template< typename > class Operation > +//// +// Binary expression max +template< typename ET1, typename ET2, + typename..., typename = EnableIfBinaryExpression_t< ET1, ET2 >, typename = void > auto -operator-( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) +max( const ET1& a, const ET2& b ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return BinaryExpressionTemplate< ET1, ET2, Max >( a, b ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Abs +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator-( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +abs( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return UnaryExpressionTemplate< ET1, Abs >( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Pow +template< typename ET1, typename Real, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +pow( const ET1& a, const Real& exp ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return BinaryExpressionTemplate< ET1, Real, Pow >( a, exp ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Exp +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator-( const UnaryExpressionTemplate< L1,LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +exp( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return UnaryExpressionTemplate< ET1, Exp >( a ); } //// -// Binary expression multiplication -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Sqrt +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator*( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +sqrt( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return UnaryExpressionTemplate< ET1, Sqrt >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Cbrt +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator*( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +cbrt( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return UnaryExpressionTemplate< ET1, Cbrt >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Log +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator*( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) +log( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return UnaryExpressionTemplate< ET1, Log >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Log10 +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator*( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) +log10( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return UnaryExpressionTemplate< ET1, Log10 >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Log2 +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator*( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) +log2( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return UnaryExpressionTemplate< ET1, Log2 >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Sin +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator*( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +sin( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return UnaryExpressionTemplate< ET1, Sin >( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Cos +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator*( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1, ROperation >& b ) +cos( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return UnaryExpressionTemplate< ET1, Cos >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Tan +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator*( const UnaryExpressionTemplate< L1,LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +tan( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return UnaryExpressionTemplate< ET1, Tan >( a ); } //// -// Binary expression division -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Asin +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator/( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +asin( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return UnaryExpressionTemplate< ET1, Asin >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Acos +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator/( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +acos( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return UnaryExpressionTemplate< ET1, Acos >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Atan +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator/( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) +atan( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return UnaryExpressionTemplate< ET1, Atan >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Sinh +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator/( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) +sinh( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return UnaryExpressionTemplate< ET1, Sinh >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Cosh +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator/( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) +cosh( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return UnaryExpressionTemplate< ET1, Cosh >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Tanh +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator/( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +tanh( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return UnaryExpressionTemplate< ET1, Tanh >( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Asinh +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator/( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +asinh( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return UnaryExpressionTemplate< ET1, Asinh >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Acosh +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator/( const UnaryExpressionTemplate< L1,LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +acosh( const ET1& a ) { - return BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return UnaryExpressionTemplate< ET1, Acosh >( a ); } //// -// Comparison operator == -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator==( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +// Atanh +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +atanh( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return UnaryExpressionTemplate< ET1, Atanh >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator==( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +//// +// Floor +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +floor( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return UnaryExpressionTemplate< ET1, Floor >( a ); } -template< typename T1, - template< typename > class Operation > -bool -operator==( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) +//// +// Ceil +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +ceil( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return UnaryExpressionTemplate< ET1, Ceil >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator==( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) +//// +// Sign +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +sign( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return UnaryExpressionTemplate< ET1, Sign >( a ); } -template< typename T1, - template< typename > class Operation > -bool -operator==( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) +//// +// Cast +template< typename ResultType, + typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, + // workaround: templated type alias cannot be declared at block level + template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation, + typename = void > +auto +cast( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return UnaryExpressionTemplate< ET1, CastOperation >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator==( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +//// +// Vertical operations +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +min( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return ExpressionMin( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator==( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +argMin( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return ExpressionArgMin( a ); } -//// -// Comparison operator != -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator!=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +max( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return ExpressionMax( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator!=( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +argMax( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return ExpressionArgMax( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator!=( const UnaryExpressionTemplate< L1, LOperation >& a, - const UnaryExpressionTemplate< R1, ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +sum( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return ExpressionSum( a ); } -template< typename T1, - template< typename > class Operation > -bool -operator!=( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +maxNorm( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return max( abs( a ) ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator!=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +l1Norm( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return sum( abs( a ) ); } -template< typename T1, - template< typename > class Operation > -bool -operator!=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +l2Norm( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + using TNL::sqrt; + return sqrt( sum( a * a ) ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator!=( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +template< typename ET1, + typename Real, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +lpNorm( const ET1& a, const Real& p ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + if( p == 1.0 ) + return l1Norm( a ); + if( p == 2.0 ) + return l2Norm( a ); + using TNL::pow; + return pow( sum( pow( abs( a ), p ) ), 1.0 / p ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator!=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +product( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return ExpressionProduct( a ); } -//// -// Comparison operator < -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator<( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > +auto +logicalAnd( const ET1& a ) { - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return ExpressionLogicalAnd( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator<( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator<( const UnaryExpressionTemplate< L1, LOperation >& a, - const UnaryExpressionTemplate< R1, ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator<( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator<( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator<( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator<( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator<( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} - -//// -// Comparison operator <= -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator<=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator<=( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator<=( const UnaryExpressionTemplate< L1, LOperation >& a, - const UnaryExpressionTemplate< R1, ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator<=( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator<=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator<=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator<=( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator<=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -//// -// Comparison operator > -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator>( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator>( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator>( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator>( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator>( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator>( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator>( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -//// -// Comparison operator >= -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator>=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator>=( const BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator>=( const UnaryExpressionTemplate< T1, Operation >& a, - const typename UnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -bool -operator>=( const typename BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const BinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -bool -operator>=( const typename UnaryExpressionTemplate< T1, Operation >::RealType& a, - const UnaryExpressionTemplate< T1, Operation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -bool -operator>=( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -bool -operator>=( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Comparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -//// -// Unary operations - -//// -// Minus -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -operator-( const BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return UnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -operator-( const UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return UnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a ); -} - -//// -// Scalar product -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -operator,( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return ExpressionSum( a * b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator,( const UnaryExpressionTemplate< L1, LOperation >& a, - const UnaryExpressionTemplate< R1, ROperation >& b ) +logicalOr( const ET1& a ) { - return ExpressionSum( a * b ); + return ExpressionLogicalOr( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator,( const UnaryExpressionTemplate< L1, LOperation >& a, - const BinaryExpressionTemplate< R1, R2, ROperation >& b ) +binaryAnd( const ET1& a ) { - return ExpressionSum( a * b ); + return ExpressionBinaryAnd( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +template< typename ET1, + typename..., typename = EnableIfUnaryExpression_t< ET1 >, typename = void > auto -operator,( const BinaryExpressionTemplate< L1, L2, LOperation >& a, - const UnaryExpressionTemplate< R1,ROperation >& b ) +binaryOr( const ET1& a ) { - return ExpressionSum( a * b ); + return ExpressionBinaryOr( a ); } #endif // DOXYGEN_ONLY -} // namespace Expressions -} // namespace Containers - -//// -// All operations are supposed to be in namespace TNL - -#ifndef DOXYGEN_ONLY - //// -// Binary expression min -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -auto -min( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - +// Output stream template< typename T1, typename T2, template< typename, typename > class Operation > -auto -min( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -auto -min( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a, - const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b ) +std::ostream& operator<<( std::ostream& str, const BinaryExpressionTemplate< T1, T2, Operation >& expression ) { - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); + str << "[ "; + for( int i = 0; i < expression.getSize() - 1; i++ ) + str << expression.getElement( i ) << ", "; + str << expression.getElement( expression.getSize() - 1 ) << " ]"; + return str; } -template< typename T1, +template< typename T, template< typename > class Operation > -auto -min( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a, - const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -min( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, - const typename Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -min( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a, - const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b ) +std::ostream& operator<<( std::ostream& str, const UnaryExpressionTemplate< T, Operation >& expression ) { - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); + str << "[ "; + for( int i = 0; i < expression.getSize() - 1; i++ ) + str << expression.getElement( i ) << ", "; + str << expression.getElement( expression.getSize() - 1 ) << " ]"; + return str; } -//// -// Binary expression max -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} +} // namespace Expressions -template< typename T1, - typename T2, - template< typename, typename > class Operation > -auto -max( const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& a, - const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} +// Make all operators visible in the TNL::Containers namespace to be considered +// even for Vector and VectorView +using Expressions::operator+; +using Expressions::operator-; +using Expressions::operator*; +using Expressions::operator/; +using Expressions::operator,; +using Expressions::operator==; +using Expressions::operator!=; +using Expressions::operator<; +using Expressions::operator<=; +using Expressions::operator>; +using Expressions::operator>=; + +// Make all functions visible in the TNL::Containers namespace +using Expressions::dot; +using Expressions::min; +using Expressions::max; +using Expressions::abs; +using Expressions::pow; +using Expressions::exp; +using Expressions::sqrt; +using Expressions::cbrt; +using Expressions::log; +using Expressions::log10; +using Expressions::log2; +using Expressions::sin; +using Expressions::cos; +using Expressions::tan; +using Expressions::asin; +using Expressions::acos; +using Expressions::atan; +using Expressions::sinh; +using Expressions::cosh; +using Expressions::tanh; +using Expressions::asinh; +using Expressions::acosh; +using Expressions::atanh; +using Expressions::floor; +using Expressions::ceil; +using Expressions::sign; +using Expressions::cast; +using Expressions::argMin; +using Expressions::argMax; +using Expressions::sum; +using Expressions::maxNorm; +using Expressions::l1Norm; +using Expressions::l2Norm; +using Expressions::lpNorm; +using Expressions::product; +using Expressions::logicalAnd; +using Expressions::logicalOr; +using Expressions::binaryAnd; +using Expressions::binaryOr; -template< typename T1, - typename T2, - template< typename, typename > class Operation > -auto -max( const typename Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const Containers::Expressions::BinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -auto -max( const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& a, - const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -auto -max( const typename Containers::Expressions::UnaryExpressionTemplate< T1, Operation >::RealType& a, - const Containers::Expressions::UnaryExpressionTemplate< T1, Operation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -max( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -max( const Containers::Expressions::UnaryExpressionTemplate< L1,LOperation >& a, - const Containers::Expressions::UnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -//// -// Abs -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -abs( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -abs( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a ); -} - -//// -// Pow -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename Real > -auto -pow( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp ); -} - -template< typename L1, - template< typename > class LOperation, - typename Real > -auto -pow( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Real& exp ) -{ - return Containers::Expressions::BinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp ); -} - -//// -// Exp -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -exp( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -exp( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a ); -} - -//// -// Sqrt -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sqrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sqrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a ); -} - -//// -// Cbrt -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -cbrt( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -cbrt( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a ); -} - -//// -// Log -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -log( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -log( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a ); -} - -//// -// Log10 -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -log10( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -log10( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a ); -} - -//// -// Log2 -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -log2( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -log2( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a ); -} - -//// -// Sin -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a ); -} - -//// -// Cos -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -cos( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -cos( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a ); -} - -//// -// Tan -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -tan( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -tan( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a ); -} - -//// -// Asin -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -asin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -asin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a ); -} - -//// -// Acos -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -acos( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -acos( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a ); -} - -//// -// Atan -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -atan( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -atan( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a ); -} - -//// -// Sinh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sinh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sinh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a ); -} - -//// -// Cosh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -cosh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -cosh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a ); -} - -//// -// Tanh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -tanh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -tanh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a ); -} - -//// -// Asinh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -asinh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -asinh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a ); -} - -//// -// Acosh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -acosh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -acosh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a ); -} - -//// -// Atanh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -atanh( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -atanh( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a ); -} - -//// -// Floor -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -floor( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -floor( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a ); -} - -//// -// Ceil -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -ceil( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -ceil( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a ); -} - -//// -// Sign -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sign( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sign( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a ); -} - -//// -// Cast -template< typename ResultType, - typename L1, - typename L2, - template< typename, typename > class LOperation, - // workaround: templated type alias cannot be declared at block level - template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > -auto -cast( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a ); -} - -template< typename ResultType, - typename L1, - template< typename > class LOperation, - // workaround: templated type alias cannot be declared at block level - template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > -auto -cast( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a ); -} - -//// -// Vertical operations - min -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -min( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionMin( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -min( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionMin( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -argMin( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionArgMin( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -argMin( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionArgMin( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -max( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionMax( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -max( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionMax( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -argMax( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionArgMax( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -argMax( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionArgMax( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -sum( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionSum( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -sum( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionSum( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -maxNorm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return max( abs( a ) ); -} - -template< typename L1, - template< typename > class LOperation > -auto -maxNorm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return max( abs( a ) ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -l1Norm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionL1Norm( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -l1Norm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionL1Norm( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -l2Norm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return TNL::sqrt( ExpressionL2Norm( a ) ); -} - -template< typename L1, - template< typename > class LOperation > -auto -l2Norm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return TNL::sqrt( ExpressionL2Norm( a ) ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename Real > -auto -lpNorm( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( ExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< typename L1, - template< typename > class LOperation, - typename Real > -auto -lpNorm( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, const Real& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( ExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -product( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionProduct( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -product( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionProduct( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -logicalOr( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionLogicalOr( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -logicalOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionLogicalOr( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -logicalAnd( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionLogicalAnd( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -logicalAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionLogicalAnd( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -binaryOr( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionBinaryOr( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -binaryOr( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionBinaryOr( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -binaryAnd( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return ExpressionBinaryAnd( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -binaryAnd( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a ) -{ - return ExpressionBinaryAnd( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -dot( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return (a, b); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -dot( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >& b ) -{ - return (a, b); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -auto -dot( const Containers::Expressions::UnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::BinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return (a, b); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -auto -dot( const Containers::Expressions::BinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::UnaryExpressionTemplate< R1, ROperation >& b ) -{ - return (a, b); -} - -#endif // DOXYGEN_ONLY +} // namespace Containers +// Make all functions visible in the main TNL namespace +using Containers::dot; +using Containers::min; +using Containers::max; +using Containers::abs; +using Containers::pow; +using Containers::exp; +using Containers::sqrt; +using Containers::cbrt; +using Containers::log; +using Containers::log10; +using Containers::log2; +using Containers::sin; +using Containers::cos; +using Containers::tan; +using Containers::asin; +using Containers::acos; +using Containers::atan; +using Containers::sinh; +using Containers::cosh; +using Containers::tanh; +using Containers::asinh; +using Containers::acosh; +using Containers::atanh; +using Containers::floor; +using Containers::ceil; +using Containers::sign; +using Containers::cast; +using Containers::argMin; +using Containers::argMax; +using Containers::sum; +using Containers::maxNorm; +using Containers::l1Norm; +using Containers::l2Norm; +using Containers::lpNorm; +using Containers::product; +using Containers::logicalAnd; +using Containers::logicalOr; +using Containers::binaryAnd; +using Containers::binaryOr; //// // Evaluation with reduction diff --git a/src/TNL/Containers/Expressions/ExpressionVariableType.h b/src/TNL/Containers/Expressions/ExpressionVariableType.h index ad9ab830ed30f1cbfc4f2701140ffb1efcb819e7..2095a4352c9874f6315f01dbaf475be2f1a66006 100644 --- a/src/TNL/Containers/Expressions/ExpressionVariableType.h +++ b/src/TNL/Containers/Expressions/ExpressionVariableType.h @@ -10,8 +10,7 @@ #pragma once -#include <TNL/TypeTraits.h> -#include <TNL/Devices/Host.h> +#include <TNL/Containers/Expressions/TypeTraits.h> namespace TNL { namespace Containers { @@ -19,41 +18,24 @@ namespace Expressions { enum ExpressionVariableType { ArithmeticVariable, VectorExpressionVariable, OtherVariable }; -template< typename T, - bool IsArithmetic = std::is_arithmetic< T >::value, - bool IsVector = HasSubscriptOperator< T >::value > -struct ExpressionVariableTypeGetter +template< typename T, typename V = T > +constexpr ExpressionVariableType +getExpressionVariableType() { - static constexpr ExpressionVariableType value = OtherVariable; -}; - -template< typename T > -struct ExpressionVariableTypeGetter< T, true, false > -{ - static constexpr ExpressionVariableType value = ArithmeticVariable; -}; - -template< typename T > -struct ExpressionVariableTypeGetter< T, false, true > -{ - static constexpr ExpressionVariableType value = VectorExpressionVariable; -}; - -//// -// Non-static expression templates might be passed on GPU, for example. In this -// case, we cannot store ET operands using references but we need to make copies. -template< typename T, - typename Device > -struct OperandType -{ - using type = std::add_const_t< std::remove_reference_t< T > >; -}; - -template< typename T > -struct OperandType< T, Devices::Host > -{ - using type = std::add_const_t< std::add_lvalue_reference_t< T > >; -}; + if( std::is_arithmetic< std::decay_t< T > >::value ) + return ArithmeticVariable; + // vectors must be considered as an arithmetic type when used as RealType in another vector + if( IsArithmeticSubtype< T, V >::value ) + return ArithmeticVariable; + if( HasEnabledExpressionTemplates< T >::value || + HasEnabledStaticExpressionTemplates< T >::value || + HasEnabledDistributedExpressionTemplates< T >::value + ) + return VectorExpressionVariable; + if( IsArrayType< T >::value || IsStaticArrayType< T >::value ) + return VectorExpressionVariable; + return OtherVariable; +} } // namespace Expressions } // namespace Containers diff --git a/src/TNL/Containers/Expressions/HorizontalOperations.h b/src/TNL/Containers/Expressions/HorizontalOperations.h index 95a712f45e9e60e9a45bf42aa19f491aac101647..47b85d6e719d78382ac8c9d0f7c728bd9813715d 100644 --- a/src/TNL/Containers/Expressions/HorizontalOperations.h +++ b/src/TNL/Containers/Expressions/HorizontalOperations.h @@ -60,9 +60,9 @@ template< typename T1, typename T2 > struct Min { __cuda_callable__ - static auto evaluate( const T1& a, const T2& b ) -> decltype( TNL::min( a , b ) ) + static auto evaluate( const T1& a, const T2& b ) -> decltype( min( a , b ) ) { - return TNL::min( a, b ); + return min( a, b ); } }; @@ -70,9 +70,9 @@ template< typename T1, typename T2 > struct Max { __cuda_callable__ - static auto evaluate( const T1& a, const T2& b ) -> decltype( TNL::max( a, b ) ) + static auto evaluate( const T1& a, const T2& b ) -> decltype( max( a, b ) ) { - return TNL::max( a, b ); + return max( a, b ); } }; @@ -90,9 +90,9 @@ template< typename T1 > struct Abs { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::abs( a ) ) + static auto evaluate( const T1& a ) -> decltype( abs( a ) ) { - return TNL::abs( a ); + return abs( a ); } }; @@ -100,9 +100,9 @@ template< typename T1, typename T2 > struct Pow { __cuda_callable__ - static auto evaluate( const T1& a, const T2& exp ) -> decltype( TNL::pow( a, exp ) ) + static auto evaluate( const T1& a, const T2& exp ) -> decltype( pow( a, exp ) ) { - return TNL::pow( a, exp ); + return pow( a, exp ); } }; @@ -110,9 +110,9 @@ template< typename T1 > struct Exp { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::exp( a ) ) + static auto evaluate( const T1& a ) -> decltype( exp( a ) ) { - return TNL::exp( a ); + return exp( a ); } }; @@ -120,9 +120,9 @@ template< typename T1 > struct Sqrt { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::sqrt( a ) ) + static auto evaluate( const T1& a ) -> decltype( sqrt( a ) ) { - return TNL::sqrt( a ); + return sqrt( a ); } }; @@ -130,9 +130,9 @@ template< typename T1 > struct Cbrt { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::cbrt( a ) ) + static auto evaluate( const T1& a ) -> decltype( cbrt( a ) ) { - return TNL::cbrt( a ); + return cbrt( a ); } }; @@ -140,9 +140,9 @@ template< typename T1 > struct Log { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::log( a ) ) + static auto evaluate( const T1& a ) -> decltype( log( a ) ) { - return TNL::log( a ); + return log( a ); } }; @@ -150,9 +150,9 @@ template< typename T1 > struct Log10 { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::log10( a ) ) + static auto evaluate( const T1& a ) -> decltype( log10( a ) ) { - return TNL::log10( a ); + return log10( a ); } }; @@ -160,9 +160,9 @@ template< typename T1 > struct Log2 { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::log2( a ) ) + static auto evaluate( const T1& a ) -> decltype( log2( a ) ) { - return TNL::log2( a ); + return log2( a ); } }; @@ -170,9 +170,9 @@ template< typename T1 > struct Sin { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::sin( a ) ) + static auto evaluate( const T1& a ) -> decltype( sin( a ) ) { - return TNL::sin( a ); + return sin( a ); } }; @@ -180,9 +180,9 @@ template< typename T1 > struct Cos { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::cos( a ) ) + static auto evaluate( const T1& a ) -> decltype( cos( a ) ) { - return TNL::cos( a ); + return cos( a ); } }; @@ -190,9 +190,9 @@ template< typename T1 > struct Tan { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::tan( a ) ) + static auto evaluate( const T1& a ) -> decltype( tan( a ) ) { - return TNL::tan( a ); + return tan( a ); } }; @@ -200,9 +200,9 @@ template< typename T1 > struct Asin { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::asin( a ) ) + static auto evaluate( const T1& a ) -> decltype( asin( a ) ) { - return TNL::asin( a ); + return asin( a ); } }; @@ -210,9 +210,9 @@ template< typename T1 > struct Acos { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::acos( a ) ) + static auto evaluate( const T1& a ) -> decltype( acos( a ) ) { - return TNL::acos( a ); + return acos( a ); } }; @@ -220,9 +220,9 @@ template< typename T1 > struct Atan { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::atan( a ) ) + static auto evaluate( const T1& a ) -> decltype( atan( a ) ) { - return TNL::atan( a ); + return atan( a ); } }; @@ -230,9 +230,9 @@ template< typename T1 > struct Sinh { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::sinh( a ) ) + static auto evaluate( const T1& a ) -> decltype( sinh( a ) ) { - return TNL::sinh( a ); + return sinh( a ); } }; @@ -240,9 +240,9 @@ template< typename T1 > struct Cosh { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::cosh( a ) ) + static auto evaluate( const T1& a ) -> decltype( cosh( a ) ) { - return TNL::cosh( a ); + return cosh( a ); } }; @@ -250,9 +250,9 @@ template< typename T1 > struct Tanh { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::tanh( a ) ) + static auto evaluate( const T1& a ) -> decltype( tanh( a ) ) { - return TNL::tanh( a ); + return tanh( a ); } }; @@ -260,9 +260,9 @@ template< typename T1 > struct Asinh { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::asinh( a ) ) + static auto evaluate( const T1& a ) -> decltype( asinh( a ) ) { - return TNL::asinh( a ); + return asinh( a ); } }; @@ -270,9 +270,9 @@ template< typename T1 > struct Acosh { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::acosh( a ) ) + static auto evaluate( const T1& a ) -> decltype( acosh( a ) ) { - return TNL::acosh( a ); + return acosh( a ); } }; @@ -280,9 +280,9 @@ template< typename T1 > struct Atanh { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::atanh( a ) ) + static auto evaluate( const T1& a ) -> decltype( atanh( a ) ) { - return TNL::atanh( a ); + return atanh( a ); } }; @@ -290,9 +290,9 @@ template< typename T1 > struct Floor { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::floor( a ) ) + static auto evaluate( const T1& a ) -> decltype( floor( a ) ) { - return TNL::floor( a ); + return floor( a ); } }; @@ -300,9 +300,9 @@ template< typename T1 > struct Ceil { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::ceil( a ) ) + static auto evaluate( const T1& a ) -> decltype( ceil( a ) ) { - return TNL::ceil( a ); + return ceil( a ); } }; @@ -310,9 +310,9 @@ template< typename T1 > struct Sign { __cuda_callable__ - static auto evaluate( const T1& a ) -> decltype( TNL::sign( a ) ) + static auto evaluate( const T1& a ) -> decltype( sign( a ) ) { - return TNL::sign( a ); + return sign( a ); } }; diff --git a/src/TNL/Containers/Expressions/StaticComparison.h b/src/TNL/Containers/Expressions/StaticComparison.h index d12f1c12bdd0a5a4f63f1e3f507141d675f34706..af1bf17baf52579c7a586173215e7051069e3fff 100644 --- a/src/TNL/Containers/Expressions/StaticComparison.h +++ b/src/TNL/Containers/Expressions/StaticComparison.h @@ -19,8 +19,8 @@ namespace Expressions { template< typename T1, typename T2, - ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, - ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > + ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(), + ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() > struct StaticComparison; ///// diff --git a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h index d08f2b02b76fe0c47b1ac4d141a6d6f9d85b5586..d2f01822bfbfa2876ef4f4e6fd07eab4a201bc1b 100644 --- a/src/TNL/Containers/Expressions/StaticExpressionTemplates.h +++ b/src/TNL/Containers/Expressions/StaticExpressionTemplates.h @@ -25,32 +25,28 @@ namespace Containers { namespace Expressions { template< typename T1, - template< typename > class Operation, - ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value > -struct StaticUnaryExpressionTemplate -{}; + template< typename > class Operation > +struct StaticUnaryExpressionTemplate; template< typename T1, - template< typename > class Operation, - ExpressionVariableType T1Type > -struct IsExpressionTemplate< StaticUnaryExpressionTemplate< T1, Operation, T1Type > > + template< typename > class Operation > +struct HasEnabledStaticExpressionTemplates< StaticUnaryExpressionTemplate< T1, Operation > > : std::true_type {}; template< typename T1, typename T2, template< typename, typename > class Operation, - ExpressionVariableType T1Type = ExpressionVariableTypeGetter< T1 >::value, - ExpressionVariableType T2Type = ExpressionVariableTypeGetter< T2 >::value > -struct StaticBinaryExpressionTemplate -{}; + ExpressionVariableType T1Type = getExpressionVariableType< T1, T2 >(), + ExpressionVariableType T2Type = getExpressionVariableType< T2, T1 >() > +struct StaticBinaryExpressionTemplate; template< typename T1, typename T2, template< typename, typename > class Operation, ExpressionVariableType T1Type, ExpressionVariableType T2Type > -struct IsExpressionTemplate< StaticBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > > +struct HasEnabledStaticExpressionTemplates< StaticBinaryExpressionTemplate< T1, T2, Operation, T1Type, T2Type > > : std::true_type {}; @@ -62,6 +58,7 @@ template< typename T1, template< typename, typename > class Operation > struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariable, VectorExpressionVariable > { + using VectorOperandType = T1; using RealType = decltype( Operation< typename T1::RealType, typename T2::RealType >:: evaluate( std::declval<T1>()[0], std::declval<T2>()[0] ) ); @@ -115,6 +112,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariab static_assert( IsStaticArrayType< T1 >::value, "Left-hand side operand of static expression is not static, i.e. based on static vector." ); + using VectorOperandType = T1; using RealType = decltype( Operation< typename T1::RealType, T2 >:: evaluate( std::declval<T1>()[0], std::declval<T2>() ) ); @@ -150,7 +148,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, VectorExpressionVariab protected: const T1& op1; - const T2& op2; + const T2 op2; }; template< typename T1, @@ -161,6 +159,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, Ve static_assert( IsStaticArrayType< T2 >::value, "Right-hand side operand of static expression is not static, i.e. based on static vector." ); + using VectorOperandType = T2; using RealType = decltype( Operation< T1, typename T2::RealType >:: evaluate( std::declval<T1>(), std::declval<T2>()[0] ) ); @@ -195,7 +194,7 @@ struct StaticBinaryExpressionTemplate< T1, T2, Operation, ArithmeticVariable, Ve } protected: - const T1& op1; + const T1 op1; const T2& op2; }; @@ -203,8 +202,9 @@ protected: // Static unary expression template template< typename T1, template< typename > class Operation > -struct StaticUnaryExpressionTemplate< T1, Operation, VectorExpressionVariable > +struct StaticUnaryExpressionTemplate { + using VectorOperandType = T1; using RealType = decltype( Operation< typename T1::RealType >:: evaluate( std::declval<T1>()[0] ) ); @@ -246,1020 +246,586 @@ protected: //// // Binary expressions addition -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ auto -operator+( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +operator+( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return StaticBinaryExpressionTemplate< ET1, ET2, Addition >( a, b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Binary expression subtraction +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ auto -operator+( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +operator-( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return StaticBinaryExpressionTemplate< ET1, ET2, Subtraction >( a, b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Binary expression multiplication +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ auto -operator+( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) +operator*( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return StaticBinaryExpressionTemplate< ET1, ET2, Multiplication >( a, b ); } -template< typename T1, - template< typename > class Operation > +//// +// Binary expression division +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ auto -operator+( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) +operator/( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return StaticBinaryExpressionTemplate< ET1, ET2, Division >( a, b ); } -template< typename T1, - template< typename > class Operation > +//// +// Comparison operator == +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ -auto -operator+( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) +bool +operator==( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return StaticComparison< ET1, ET2 >::EQ( a, b ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Comparison operator != +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ -auto -operator+( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +bool +operator!=( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return StaticComparison< ET1, ET2 >::NE( a, b ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Comparison operator < +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ -auto -operator+( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1, ROperation >& b ) +bool +operator<( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return StaticComparison< ET1, ET2 >::LT( a, b ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Comparison operator <= +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ -auto -operator+( const StaticUnaryExpressionTemplate< L1,LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) +bool +operator<=( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Addition >( a, b ); + return StaticComparison< ET1, ET2 >::LE( a, b ); } //// -// Binary expression subtraction -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Comparison operator > +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ -auto -operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +bool +operator>( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return StaticComparison< ET1, ET2 >::GT( a, b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Comparison operator >= +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ -auto -operator-( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +bool +operator>=( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return Expressions::StaticComparison< ET1, ET2 >::GE( a, b ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Scalar product +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ auto -operator-( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) +operator,( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return StaticExpressionSum( a * b ); } -template< typename T1, - template< typename > class Operation > +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ auto -operator-( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) +dot( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return (a, b); } -template< typename T1, - template< typename > class Operation > +//// +// Unary expression minus +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator-( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) +operator-( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Minus >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Binary expression min +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ auto -operator-( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +min( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< ET1, ET2, Min >( a, b ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Binary expression max +template< typename ET1, typename ET2, + typename..., typename = EnableIfStaticBinaryExpression_t< ET1, ET2 > > __cuda_callable__ auto -operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) +max( const ET1& a, const ET2& b ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return StaticBinaryExpressionTemplate< ET1, ET2, Max >( a, b ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Abs +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator-( const StaticUnaryExpressionTemplate< L1,LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) +abs( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Subtraction >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Abs >( a ); } //// -// Binary expression multiplication -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Pow +template< typename ET1, typename Real, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator*( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +pow( const ET1& a, const Real& exp ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return StaticBinaryExpressionTemplate< ET1, Real, Pow >( a, exp ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Exp +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator*( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +exp( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Exp >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Sqrt +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator*( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) +sqrt( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Sqrt >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Cbrt +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator*( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) +cbrt( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Cbrt >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Log +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator*( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) +log( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Log >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Log10 +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator*( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +log10( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Log10 >( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Log2 +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator*( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1, ROperation >& b ) +log2( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Log2 >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Sin +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator*( const StaticUnaryExpressionTemplate< L1,LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) +sin( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Multiplication >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Sin >( a ); } //// -// Binary expression division -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Cos +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator/( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +cos( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Cos >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Tan +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator/( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +tan( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Tan >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Asin +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator/( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) +asin( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Asin >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Acos +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator/( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) +acos( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Acos >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Atan +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator/( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) +atan( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Atan >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Sinh +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator/( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +sinh( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Sinh >( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Cosh +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator/( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) +cosh( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Cosh >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Tanh +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ auto -operator/( const StaticUnaryExpressionTemplate< L1,LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) +tanh( const ET1& a ) { - return StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Division >( a, b ); + return StaticUnaryExpressionTemplate< ET1, Tanh >( a ); } //// -// Comparison operator == -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -bool -operator==( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > +// Asinh +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator==( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +auto +asinh( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return StaticUnaryExpressionTemplate< ET1, Asinh >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Acosh +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator==( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) +auto +acosh( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return StaticUnaryExpressionTemplate< ET1, Acosh >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Atanh +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator==( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) +auto +atanh( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return StaticUnaryExpressionTemplate< ET1, Atanh >( a ); } -template< typename T1, - template< typename > class Operation > +//// +// Floor +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator==( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) +auto +floor( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return StaticUnaryExpressionTemplate< ET1, Floor >( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +//// +// Ceil +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator==( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +auto +ceil( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return StaticUnaryExpressionTemplate< ET1, Ceil >( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +//// +// Sign +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator==( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) +auto +sign( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::EQ( a, b ); + return StaticUnaryExpressionTemplate< ET1, Sign >( a ); } //// -// Comparison operator != -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +// Cast +template< typename ResultType, + typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 >, + // workaround: templated type alias cannot be declared at block level + template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > __cuda_callable__ -bool -operator!=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +auto +cast( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return StaticUnaryExpressionTemplate< ET1, CastOperation >( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +//// +// Vertical operations +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator!=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +auto +min( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return StaticExpressionMin( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator!=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticUnaryExpressionTemplate< R1, ROperation >& b ) +auto +argMin( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return StaticExpressionArgMin( a ); } -template< typename T1, - template< typename > class Operation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator!=( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) +auto +max( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return StaticExpressionMax( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator!=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) +auto +argMax( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return StaticExpressionArgMax( a ); } -template< typename T1, - template< typename > class Operation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator!=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) +auto +sum( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return StaticExpressionSum( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator!=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +auto +maxNorm( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return max( abs( a ) ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator!=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) +auto +l1Norm( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::NE( a, b ); + return sum( abs( a ) ); } -//// -// Comparison operator < -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator<( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +auto +l2Norm( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + using TNL::sqrt; + return sqrt( sum( a * a ) ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +template< typename ET1, + typename Real, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator<( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +auto +lpNorm( const ET1& a, const Real& p ) +// since (1.0 / p) has type double, TNL::pow returns double +-> double +//-> RemoveET< decltype(pow( StaticExpressionLpNorm( a, p ), 1.0 / p )) > { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + if( p == 1.0 ) + return l1Norm( a ); + if( p == 2.0 ) + return l2Norm( a ); + using TNL::pow; + return pow( sum( pow( abs( a ), p ) ), 1.0 / p ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator<( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticUnaryExpressionTemplate< R1, ROperation >& b ) +auto +product( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return StaticExpressionProduct( a ); } -template< typename T1, - template< typename > class Operation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator<( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) +auto +logicalAnd( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return StaticExpressionLogicalAnd( a ); } -template< typename T1, - typename T2, - template< typename, typename > class Operation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator<( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) +auto +logicalOr( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return StaticExpressionLogicalOr( a ); } -template< typename T1, - template< typename > class Operation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator<( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) +auto +binaryAnd( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return StaticExpressionBinaryAnd( a ); } -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > +template< typename ET1, + typename..., typename = EnableIfStaticUnaryExpression_t< ET1 > > __cuda_callable__ -bool -operator<( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) +auto +binaryOr( const ET1& a ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); + return StaticExpressionBinaryOr( a ); } -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -bool -operator<( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LT( a, b ); -} +#endif // DOXYGEN_ONLY //// -// Comparison operator <= -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -bool -operator<=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - +// Output stream template< typename T1, typename T2, template< typename, typename > class Operation > -__cuda_callable__ -bool -operator<=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) +std::ostream& operator<<( std::ostream& str, const StaticBinaryExpressionTemplate< T1, T2, Operation >& expression ) { - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -bool -operator<=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticUnaryExpressionTemplate< R1, ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -bool -operator<=( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -__cuda_callable__ -bool -operator<=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -bool -operator<=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -bool -operator<=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -bool -operator<=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::LE( a, b ); -} - -//// -// Comparison operator > -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -bool -operator>( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -__cuda_callable__ -bool -operator>( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -bool -operator>( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -__cuda_callable__ -bool -operator>( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -bool -operator>( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -bool -operator>( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -bool -operator>( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GT( a, b ); -} - -//// -// Comparison operator >= -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -bool -operator>=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -__cuda_callable__ -bool -operator>=( const StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -bool -operator>=( const StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -__cuda_callable__ -bool -operator>=( const typename StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -bool -operator>=( const typename StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const StaticUnaryExpressionTemplate< T1, Operation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -bool -operator>=( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -bool -operator>=( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return StaticComparison< std::decay_t<decltype(a)>, std::decay_t<decltype(b)> >::GE( a, b ); -} - -//// -// Unary operations - -//// -// Minus -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -operator-( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -operator-( const StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Minus >( a ); -} - -//// -// Scalar product -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -auto -operator,( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return StaticExpressionSum( a * b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -auto -operator,( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticUnaryExpressionTemplate< R1, ROperation >& b ) -{ - return StaticExpressionSum( a * b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -auto -operator,( const StaticUnaryExpressionTemplate< L1, LOperation >& a, - const StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return StaticExpressionSum( a * b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -auto -operator,( const StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return StaticExpressionSum( a * b ); -} - -#endif // DOXYGEN_ONLY - -//// -// Output stream -template< typename T1, - typename T2, - template< typename, typename > class Operation > -std::ostream& operator<<( std::ostream& str, const StaticBinaryExpressionTemplate< T1, T2, Operation >& expression ) -{ - str << "[ "; - for( int i = 0; i < expression.getSize() - 1; i++ ) - str << expression[ i ] << ", "; - str << expression[ expression.getSize() - 1 ] << " ]"; - return str; + str << "[ "; + for( int i = 0; i < expression.getSize() - 1; i++ ) + str << expression[ i ] << ", "; + str << expression[ expression.getSize() - 1 ] << " ]"; + return str; } template< typename T, @@ -1274,1008 +840,104 @@ std::ostream& operator<<( std::ostream& str, const StaticUnaryExpressionTemplate } } // namespace Expressions -} // namespace Containers - -//// -// All operations are supposed to be in namespace TNL - -#ifndef DOXYGEN_ONLY - -//// -// Binary expression min -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -auto -min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -__cuda_callable__ -auto -min( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - typename T2, - template< typename, typename > class Operation > -__cuda_callable__ -auto -min( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -auto -min( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -auto -min( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -auto -min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -auto -min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -auto -min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1,LOperation >& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Min >( a, b ); -} -//// -// Binary expression max -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -auto -max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} +// Make all operators visible in the TNL::Containers namespace to be considered +// even for StaticVector +using Expressions::operator+; +using Expressions::operator-; +using Expressions::operator*; +using Expressions::operator/; +using Expressions::operator,; +using Expressions::operator==; +using Expressions::operator!=; +using Expressions::operator<; +using Expressions::operator<=; +using Expressions::operator>; +using Expressions::operator>=; + +// Make all functions visible in the TNL::Containers namespace +using Expressions::dot; +using Expressions::min; +using Expressions::max; +using Expressions::abs; +using Expressions::pow; +using Expressions::exp; +using Expressions::sqrt; +using Expressions::cbrt; +using Expressions::log; +using Expressions::log10; +using Expressions::log2; +using Expressions::sin; +using Expressions::cos; +using Expressions::tan; +using Expressions::asin; +using Expressions::acos; +using Expressions::atan; +using Expressions::sinh; +using Expressions::cosh; +using Expressions::tanh; +using Expressions::asinh; +using Expressions::acosh; +using Expressions::atanh; +using Expressions::floor; +using Expressions::ceil; +using Expressions::sign; +using Expressions::cast; +using Expressions::argMin; +using Expressions::argMax; +using Expressions::sum; +using Expressions::maxNorm; +using Expressions::l1Norm; +using Expressions::l2Norm; +using Expressions::lpNorm; +using Expressions::product; +using Expressions::logicalAnd; +using Expressions::logicalOr; +using Expressions::binaryAnd; +using Expressions::binaryOr; -template< typename T1, - typename T2, - template< typename, typename > class Operation > -__cuda_callable__ -auto -max( const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& a, - const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} +} // namespace Containers -template< typename T1, - typename T2, - template< typename, typename > class Operation > -__cuda_callable__ -auto -max( const typename Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >::RealType& a, - const Containers::Expressions::StaticBinaryExpressionTemplate< T1, T2, Operation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -auto -max( const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& a, - const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename T1, - template< typename > class Operation > -__cuda_callable__ -auto -max( const typename Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >::RealType& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< T1, Operation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -auto -max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -auto -max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -auto -max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1,LOperation >& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, std::decay_t<decltype(b)>, Containers::Expressions::Max >( a, b ); -} - -//// -// Abs -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -abs( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -abs( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Abs >( a ); -} - -//// -// Pow -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename Real > -__cuda_callable__ -auto -pow( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& exp ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp ); -} - -template< typename L1, - template< typename > class LOperation, - typename Real > -__cuda_callable__ -auto -pow( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Real& exp ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< std::decay_t<decltype(a)>, Real, Containers::Expressions::Pow >( a, exp ); -} - -//// -// Exp -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -exp( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -exp( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Exp >( a ); -} - -//// -// Sqrt -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -sqrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -sqrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sqrt >( a ); -} - -//// -// Cbrt -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -cbrt( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -cbrt( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cbrt >( a ); -} - -//// -// Log -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -log( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -log( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log >( a ); -} - -//// -// Log10 -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -log10( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -log10( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log10 >( a ); -} - -//// -// Log2 -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -log2( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -log2( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Log2 >( a ); -} - -//// -// Sin -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -sin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -sin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sin >( a ); -} - -//// -// Cos -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -cos( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -cos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cos >( a ); -} - -//// -// Tan -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -tan( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -tan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tan >( a ); -} - -//// -// Asin -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -asin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -asin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asin >( a ); -} - -//// -// Acos -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -acos( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -acos( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acos >( a ); -} - -//// -// Atan -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -atan( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -atan( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atan >( a ); -} - -//// -// Sinh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -sinh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -sinh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sinh >( a ); -} - -//// -// Cosh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -cosh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -cosh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Cosh >( a ); -} - -//// -// Tanh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -tanh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -tanh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Tanh >( a ); -} - -//// -// Asinh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -asinh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -asinh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Asinh >( a ); -} - -//// -// Acosh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -acosh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -acosh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Acosh >( a ); -} - -//// -// Atanh -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -atanh( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -atanh( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Atanh >( a ); -} - -//// -// Floor -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -floor( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -floor( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Floor >( a ); -} - -//// -// Ceil -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -ceil( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -ceil( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Ceil >( a ); -} - -//// -// Sign -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -sign( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -sign( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Containers::Expressions::Sign >( a ); -} - -//// -// Cast -template< typename ResultType, - typename L1, - typename L2, - template< typename, typename > class LOperation, - // workaround: templated type alias cannot be declared at block level - template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > -__cuda_callable__ -auto -cast( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a ); -} - -template< typename ResultType, - typename L1, - template< typename > class LOperation, - // workaround: templated type alias cannot be declared at block level - template<typename> class CastOperation = Containers::Expressions::Cast< ResultType >::template Operation > -__cuda_callable__ -auto -cast( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, CastOperation >( a ); -} - -//// -// Vertical operations - min -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -min( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticExpressionMin( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -min( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticExpressionMin( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -argMin( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticExpressionArgMin( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -argMin( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticExpressionArgMin( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -max( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticExpressionMax( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -max( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticExpressionMax( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -argMax( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticExpressionArgMax( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -argMax( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticExpressionArgMax( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -sum( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticExpressionSum( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -sum( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticExpressionSum( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -maxNorm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return max( abs( a ) ); -} - -template< typename L1, - template< typename > class LOperation > -auto -maxNorm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return max( abs( a ) ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -l1Norm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticExpressionL1Norm( a ); -} - -template< typename L1, - template< typename > class LOperation > -auto -l1Norm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticExpressionL1Norm( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -auto -l2Norm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return TNL::sqrt( StaticExpressionL2Norm( a ) ); -} - -template< typename L1, - template< typename > class LOperation > -auto -l2Norm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return TNL::sqrt( StaticExpressionL2Norm( a ) ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename Real > -__cuda_callable__ -auto -lpNorm( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, const Real& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( StaticExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< typename L1, - template< typename > class LOperation, - typename Real > -__cuda_callable__ -auto -lpNorm( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, const Real& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( StaticExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -product( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticExpressionProduct( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -product( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticExpressionProduct( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -logicalOr( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticExpressionLogicalOr( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -logicalOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticExpressionLogicalOr( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation > -__cuda_callable__ -auto -binaryOr( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a ) -{ - return StaticExpressionBinaryOr( a ); -} - -template< typename L1, - template< typename > class LOperation > -__cuda_callable__ -auto -binaryOr( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a ) -{ - return StaticExpressionBinaryOr( a ); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -auto -dot( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return (a, b); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -auto -dot( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< R1, ROperation >& b ) -{ - return (a, b); -} - -template< typename L1, - template< typename > class LOperation, - typename R1, - typename R2, - template< typename, typename > class ROperation > -__cuda_callable__ -auto -dot( const Containers::Expressions::StaticUnaryExpressionTemplate< L1, LOperation >& a, - const Containers::Expressions::StaticBinaryExpressionTemplate< R1, R2, ROperation >& b ) -{ - return (a, b); -} - -template< typename L1, - typename L2, - template< typename, typename > class LOperation, - typename R1, - template< typename > class ROperation > -__cuda_callable__ -auto -dot( const Containers::Expressions::StaticBinaryExpressionTemplate< L1, L2, LOperation >& a, - const Containers::Expressions::StaticUnaryExpressionTemplate< R1,ROperation >& b ) -{ - return (a, b); -} - -#endif // DOXYGEN_ONLY +// Make all functions visible in the main TNL namespace +using Containers::dot; +using Containers::min; +using Containers::max; +using Containers::abs; +using Containers::pow; +using Containers::exp; +using Containers::sqrt; +using Containers::cbrt; +using Containers::log; +using Containers::log10; +using Containers::log2; +using Containers::sin; +using Containers::cos; +using Containers::tan; +using Containers::asin; +using Containers::acos; +using Containers::atan; +using Containers::sinh; +using Containers::cosh; +using Containers::tanh; +using Containers::asinh; +using Containers::acosh; +using Containers::atanh; +using Containers::floor; +using Containers::ceil; +using Containers::sign; +using Containers::cast; +using Containers::argMin; +using Containers::argMax; +using Containers::sum; +using Containers::maxNorm; +using Containers::l1Norm; +using Containers::l2Norm; +using Containers::lpNorm; +using Containers::product; +using Containers::logicalAnd; +using Containers::logicalOr; +using Containers::binaryAnd; +using Containers::binaryOr; //// // Evaluation with reduction diff --git a/src/TNL/Containers/Expressions/StaticVerticalOperations.h b/src/TNL/Containers/Expressions/StaticVerticalOperations.h index 7c8477f4d8068373ce99b0366192d15bc1ea6b03..7deec166d95b6f05e6ac50c8d1e1494dfd2b5e97 100644 --- a/src/TNL/Containers/Expressions/StaticVerticalOperations.h +++ b/src/TNL/Containers/Expressions/StaticVerticalOperations.h @@ -11,6 +11,7 @@ #pragma once #include <TNL/Math.h> +#include <TNL/Containers/Expressions/TypeTraits.h> //// // By vertical operations we mean those applied across vector elements or @@ -24,9 +25,10 @@ template< typename Expression > __cuda_callable__ auto StaticExpressionMin( const Expression& expression ) { - auto aux = expression[ 0 ]; + using ResultType = RemoveET< typename Expression::RealType >; + ResultType aux = expression[ 0 ]; for( int i = 1; i < expression.getSize(); i++ ) - aux = TNL::min( aux, expression[ i ] ); + aux = min( aux, expression[ i ] ); return aux; } @@ -34,8 +36,9 @@ template< typename Expression > __cuda_callable__ auto StaticExpressionArgMin( const Expression& expression ) { + using ResultType = RemoveET< typename Expression::RealType >; int arg = 0; - auto value = expression[ 0 ]; + ResultType value = expression[ 0 ]; for( int i = 1; i < expression.getSize(); i++ ) { if( expression[ i ] < value ) @@ -51,9 +54,10 @@ template< typename Expression > __cuda_callable__ auto StaticExpressionMax( const Expression& expression ) { - auto aux = expression[ 0 ]; + using ResultType = RemoveET< typename Expression::RealType >; + ResultType aux = expression[ 0 ]; for( int i = 1; i < expression.getSize(); i++ ) - aux = TNL::max( aux, expression[ i ] ); + aux = max( aux, expression[ i ] ); return aux; } @@ -61,8 +65,9 @@ template< typename Expression > __cuda_callable__ auto StaticExpressionArgMax( const Expression& expression ) { + using ResultType = RemoveET< typename Expression::RealType >; int arg = 0; - auto value = expression[ 0 ]; + ResultType value = expression[ 0 ]; for( int i = 1; i < expression.getSize(); i++ ) { if( expression[ i ] > value ) @@ -78,47 +83,19 @@ template< typename Expression > __cuda_callable__ auto StaticExpressionSum( const Expression& expression ) { - auto aux = expression[ 0 ]; + using ResultType = RemoveET< typename Expression::RealType >; + ResultType aux = expression[ 0 ]; for( int i = 1; i < expression.getSize(); i++ ) aux += expression[ i ]; return aux; } -template< typename Expression > -__cuda_callable__ -auto StaticExpressionL1Norm( const Expression& expression ) -{ - auto aux = TNL::abs( expression[ 0 ] ); - for( int i = 1; i < expression.getSize(); i++ ) - aux += TNL::abs( expression[ i ] ); - return aux; -} - -template< typename Expression > -__cuda_callable__ -auto StaticExpressionL2Norm( const Expression& expression ) -{ - auto aux = expression[ 0 ] * expression[ 0 ]; - for( int i = 1; i < expression.getSize(); i++ ) - aux += expression[ i ] * expression[ i ]; - return aux; -} - -template< typename Expression, typename Real > -__cuda_callable__ -auto StaticExpressionLpNorm( const Expression& expression, const Real& p ) -{ - auto aux = TNL::pow( TNL::abs( expression[ 0 ] ), p ); - for( int i = 1; i < expression.getSize(); i++ ) - aux += TNL::pow( TNL::abs( expression[ i ] ), p ); - return aux; -} - template< typename Expression > __cuda_callable__ auto StaticExpressionProduct( const Expression& expression ) { - auto aux = expression[ 0 ]; + using ResultType = RemoveET< typename Expression::RealType >; + ResultType aux = expression[ 0 ]; for( int i = 1; i < expression.getSize(); i++ ) aux *= expression[ i ]; return aux; diff --git a/src/TNL/Containers/Expressions/TypeTraits.h b/src/TNL/Containers/Expressions/TypeTraits.h index 606bb337aeb3438fdce861b54e949376652b8616..1024bb4653ecd28aa577494395520991c50f7e42 100644 --- a/src/TNL/Containers/Expressions/TypeTraits.h +++ b/src/TNL/Containers/Expressions/TypeTraits.h @@ -10,23 +10,115 @@ #pragma once -#include <type_traits> +#include <TNL/TypeTraits.h> namespace TNL { namespace Containers { namespace Expressions { +// trait classes used for the enabling of expression templates template< typename T > -struct IsExpressionTemplate : std::false_type +struct HasEnabledExpressionTemplates : std::false_type {}; template< typename T > -struct IsNumericExpression -: std::integral_constant< bool, - std::is_arithmetic< T >::value || - IsExpressionTemplate< T >::value > +struct HasEnabledStaticExpressionTemplates : std::false_type {}; +template< typename T > +struct HasEnabledDistributedExpressionTemplates : std::false_type +{}; + + +// type aliases for enabling specific operators and functions using SFINAE +template< typename ET1 > +using EnableIfStaticUnaryExpression_t = std::enable_if_t< + HasEnabledStaticExpressionTemplates< ET1 >::value >; + +template< typename ET1, typename ET2 > +using EnableIfStaticBinaryExpression_t = std::enable_if_t< + HasEnabledStaticExpressionTemplates< ET1 >::value || + HasEnabledStaticExpressionTemplates< ET2 >::value >; + +template< typename ET1 > +using EnableIfUnaryExpression_t = std::enable_if_t< + HasEnabledExpressionTemplates< ET1 >::value >; + +template< typename ET1, typename ET2 > +using EnableIfBinaryExpression_t = std::enable_if_t< + // we need to avoid ambiguity with operators defined in Array (e.g. Array::operator==) + // so the first operand must not be Array + ( + HasAddAssignmentOperator< ET1 >::value || + HasEnabledExpressionTemplates< ET1 >::value || + std::is_arithmetic< ET1 >::value + ) && + ( + HasEnabledExpressionTemplates< ET2 >::value || + HasEnabledExpressionTemplates< ET1 >::value + ) >; + +template< typename ET1 > +using EnableIfDistributedUnaryExpression_t = std::enable_if_t< + HasEnabledDistributedExpressionTemplates< ET1 >::value >; + +template< typename ET1, typename ET2 > +using EnableIfDistributedBinaryExpression_t = std::enable_if_t< + // we need to avoid ambiguity with operators defined in Array (e.g. Array::operator==) + // so the first operand must not be Array + ( + HasAddAssignmentOperator< ET1 >::value || + HasEnabledDistributedExpressionTemplates< ET1 >::value || + std::is_arithmetic< ET1 >::value + ) && + ( + HasEnabledDistributedExpressionTemplates< ET2 >::value || + HasEnabledDistributedExpressionTemplates< ET1 >::value + ) >; + + +// helper trait class for proper classification of expression operands using getExpressionVariableType +template< typename T, typename V, + bool enabled = IsVectorType< V >::value > +struct IsArithmeticSubtype +: public std::integral_constant< bool, + // TODO: use std::is_assignable? + std::is_same< T, typename V::RealType >::value > +{}; + +template< typename T > +struct IsArithmeticSubtype< T, T, true > +: public std::false_type +{}; + +template< typename T > +struct IsArithmeticSubtype< T, T, false > +: public std::false_type +{}; + +template< typename T, typename V > +struct IsArithmeticSubtype< T, V, false > +: public std::is_arithmetic< T > +{}; + + +// helper trait class (used in unit tests) +template< typename R, bool enabled = ! HasEnabledStaticExpressionTemplates< R >::value > +struct RemoveExpressionTemplate +{ + using type = R; +}; + +template< typename R > +struct RemoveExpressionTemplate< R, false > +{ +// using type = StaticVector< R::getSize(), typename RemoveExpressionTemplate< typename R::RealType >::type >; + using type = typename RemoveExpressionTemplate< typename R::VectorOperandType >::type; +}; + +template< typename R > +using RemoveET = typename RemoveExpressionTemplate< R >::type; + } // namespace Expressions } // namespace Containers } // namespace TNL diff --git a/src/TNL/Containers/Expressions/VerticalOperations.h b/src/TNL/Containers/Expressions/VerticalOperations.h index 84d362e8aab01b704cdefac44ae0d7e0e6a7150d..f9e184e03a326b99853136e2e6e74c0916588ed8 100644 --- a/src/TNL/Containers/Expressions/VerticalOperations.h +++ b/src/TNL/Containers/Expressions/VerticalOperations.h @@ -31,7 +31,8 @@ auto ExpressionMin( const Expression& expression ) -> std::decay_t< decltype( ex using ResultType = std::decay_t< decltype( expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; auto reduction = [] __cuda_callable__ ( const ResultType& a, const ResultType& b ) { return TNL::min( a, b ); }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, fetch, std::numeric_limits< ResultType >::max() ); } @@ -43,7 +44,8 @@ auto ExpressionArgMin( const Expression& expression ) using ResultType = std::decay_t< decltype( expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; auto reduction = [] __cuda_callable__ ( IndexType& aIdx, const IndexType& bIdx, ResultType& a, const ResultType& b ) { if( a > b ) { a = b; @@ -61,7 +63,8 @@ auto ExpressionMax( const Expression& expression ) -> std::decay_t< decltype( ex using ResultType = std::decay_t< decltype( expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; auto reduction = [] __cuda_callable__ ( const ResultType& a, const ResultType& b ) { return TNL::max( a, b ); }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), reduction, fetch, std::numeric_limits< ResultType >::lowest() ); } @@ -73,7 +76,8 @@ auto ExpressionArgMax( const Expression& expression ) using ResultType = std::decay_t< decltype( expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; auto reduction = [] __cuda_callable__ ( IndexType& aIdx, const IndexType& bIdx, ResultType& a, const ResultType& b ) { if( a < b ) { a = b; @@ -91,37 +95,8 @@ auto ExpressionSum( const Expression& expression ) -> std::decay_t< decltype( ex using ResultType = std::decay_t< decltype( expression[0] + expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 ); -} - -template< typename Expression > -auto ExpressionL1Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] + expression[0] ) > -{ - using ResultType = std::decay_t< decltype( expression[0] + expression[0] ) >; - using IndexType = typename Expression::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::abs( expression[ i ] ); }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 ); -} - -template< typename Expression > -auto ExpressionL2Norm( const Expression& expression ) -> std::decay_t< decltype( expression[0] * expression[0] ) > -{ - using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >; - using IndexType = typename Expression::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ] * expression[ i ]; }; - return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 ); -} - -template< typename Expression, typename Real > -auto ExpressionLpNorm( const Expression& expression, const Real& p ) -> std::decay_t< decltype( TNL::pow( expression[0], p ) ) > -{ - using ResultType = std::decay_t< decltype( TNL::pow( expression[0], p ) ) >; - using IndexType = typename Expression::IndexType; - - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return TNL::pow( TNL::abs( expression[ i ] ), p ); }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::plus<>{}, fetch, (ResultType) 0 ); } @@ -131,7 +106,8 @@ auto ExpressionProduct( const Expression& expression ) -> std::decay_t< decltype using ResultType = std::decay_t< decltype( expression[0] * expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::multiplies<>{}, fetch, (ResultType) 1 ); } @@ -141,7 +117,8 @@ auto ExpressionLogicalAnd( const Expression& expression ) -> std::decay_t< declt using ResultType = std::decay_t< decltype( expression[0] && expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::logical_and<>{}, fetch, std::numeric_limits< ResultType >::max() ); } @@ -151,7 +128,8 @@ auto ExpressionLogicalOr( const Expression& expression ) -> std::decay_t< declty using ResultType = std::decay_t< decltype( expression[0] || expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::logical_or<>{}, fetch, (ResultType) 0 ); } @@ -161,7 +139,8 @@ auto ExpressionBinaryAnd( const Expression& expression ) -> std::decay_t< declty using ResultType = std::decay_t< decltype( expression[0] & expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::bit_and<>{}, fetch, std::numeric_limits< ResultType >::max() ); } @@ -171,7 +150,8 @@ auto ExpressionBinaryOr( const Expression& expression ) -> std::decay_t< decltyp using ResultType = std::decay_t< decltype( expression[0] | expression[0] ) >; using IndexType = typename Expression::IndexType; - auto fetch = [=] __cuda_callable__ ( IndexType i ) { return expression[ i ]; }; + const auto view = expression.getConstView(); + auto fetch = [=] __cuda_callable__ ( IndexType i ) { return view[ i ]; }; return Algorithms::Reduction< typename Expression::DeviceType >::reduce( expression.getSize(), std::bit_or<>{}, fetch, (ResultType) 0 ); } diff --git a/src/TNL/Containers/StaticVector.h b/src/TNL/Containers/StaticVector.h index 2fe136ac951d4c02bb339e4c0edcee43f3c3b7d8..60b6a60f873b2e6b6ffecd8ee0089ddc54931799 100644 --- a/src/TNL/Containers/StaticVector.h +++ b/src/TNL/Containers/StaticVector.h @@ -172,11 +172,18 @@ public: operator StaticVector< Size, OtherReal >() const; }; +// Enable expression templates for StaticVector +namespace Expressions { + template< int Size, typename Real > + struct HasEnabledStaticExpressionTemplates< StaticVector< Size, Real > > + : std::true_type + {}; +} // namespace Expressions + } // namespace Containers } // namespace TNL #include <TNL/Containers/StaticVector.hpp> -#include <TNL/Containers/StaticVectorExpressions.h> // TODO: move to some other source file namespace TNL { diff --git a/src/TNL/Containers/StaticVectorExpressions.h b/src/TNL/Containers/StaticVectorExpressions.h deleted file mode 100644 index fdaf7cf70fb5a894bce285bac7f4bc6a359ab878..0000000000000000000000000000000000000000 --- a/src/TNL/Containers/StaticVectorExpressions.h +++ /dev/null @@ -1,774 +0,0 @@ -/*************************************************************************** - StaticVectorExpressions.h - description - ------------------- - begin : Apr 19, 2019 - copyright : (C) 2019 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once -#ifndef DOXYGEN_ONLY - -#include <TNL/Containers/Expressions/StaticExpressionTemplates.h> - -#include "StaticVector.h" - -namespace TNL { -namespace Containers { -// operators must be defined in the same namespace as the first operand, otherwise -// they may not be considered by the compiler (e.g. inside pybind11's macros) -// namespace Containers { Overriden operators should be in namespace TNL - -//// -// Addition -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator+( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Addition >( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator+( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Addition >( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -auto -operator+( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Addition >( a, b ); -} - -//// -// Subtraction -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator-( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Subtraction >( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator-( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Subtraction >( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -auto -operator-( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Subtraction >( a, b ); -} - -//// -// Multiplication -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator*( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Multiplication >( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator*( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Multiplication >( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -auto -operator*( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Multiplication >( a, b ); -} - -//// -// Division -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator/( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real >, ET, Expressions::Division >( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator/( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< ET, StaticVector< Size, Real >, Expressions::Division >( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -auto -operator/( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticBinaryExpressionTemplate< StaticVector< Size, Real1 >, StaticVector< Size, Real2 >, Expressions::Division >( a, b ); -} - -//// -// Comparison operations - operator == -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator==( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::EQ( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator==( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::EQ( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -bool operator==( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::EQ( a, b ); -} - -//// -// Comparison operations - operator != -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator!=( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::NE( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator!=( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::NE( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -bool operator!=( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::NE( a, b ); -} - -//// -// Comparison operations - operator < -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator<( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::LT( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator<( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::LT( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -bool operator<( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::LT( a, b ); -} - -//// -// Comparison operations - operator <= -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator<=( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::LE( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator<=( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::LE( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -bool operator<=( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::LE( a, b ); -} - -//// -// Comparison operations - operator > -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator>( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::GT( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator>( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::GT( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -bool operator>( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::GT( a, b ); -} - -//// -// Comparison operations - operator >= -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator>=( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real >, ET >::GE( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -bool operator>=( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Expressions::StaticComparison< ET, StaticVector< Size, Real > >::GE( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -bool operator>=( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Expressions::StaticComparison< StaticVector< Size, Real1 >, StaticVector< Size, Real2 > >::GE( a, b ); -} - -//// -// Minus -template< int Size, typename Real > -__cuda_callable__ -auto -operator-( const StaticVector< Size, Real >& a ) -{ - return Expressions::StaticUnaryExpressionTemplate< StaticVector< Size, Real >, Expressions::Minus >( a ); -} - -//// -// Scalar product -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator,( const StaticVector< Size, Real >& a, const ET& b ) -{ - return Containers::Expressions::StaticExpressionSum( a * b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -operator,( const ET& a, const StaticVector< Size, Real >& b ) -{ - return Containers::Expressions::StaticExpressionSum( a * b ); -} - -template< typename Real1, int Size, typename Real2 > -__cuda_callable__ -auto -operator,( const StaticVector< Size, Real1 >& a, const StaticVector< Size, Real2 >& b ) -{ - return Containers::Expressions::StaticExpressionSum( a * b ); -} - -} // namespace Containers - -//// -// Min -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -min( const Containers::StaticVector< Size, Real >& a, const ET& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ET, Containers::Expressions::Min >( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -min( const ET& a, const Containers::StaticVector< Size, Real >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< ET, Containers::StaticVector< Size, Real >, Containers::Expressions::Min >( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -auto -min( const Containers::StaticVector< Size, Real1 >& a, const Containers::StaticVector< Size, Real2 >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real1 >, Containers::StaticVector< Size, Real2 >, Containers::Expressions::Min >( a, b ); -} - -//// -// Max -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -max( const Containers::StaticVector< Size, Real >& a, const ET& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ET, Containers::Expressions::Max >( a, b ); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -max( const ET& a, const Containers::StaticVector< Size, Real >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< ET, Containers::StaticVector< Size, Real >, Containers::Expressions::Max >( a, b ); -} - -template< int Size, typename Real1, typename Real2 > -__cuda_callable__ -auto -max( const Containers::StaticVector< Size, Real1 >& a, const Containers::StaticVector< Size, Real2 >& b ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real1 >, Containers::StaticVector< Size, Real2 >, Containers::Expressions::Max >( a, b ); -} - -//// -// Dot product - the same as scalar product, just for convenience -template< int Size, typename Real, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -dot( const Containers::StaticVector< Size, Real >& a, const ET& b ) -{ - return (a, b); -} - -template< typename ET, int Size, typename Real, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -__cuda_callable__ -auto -dot( const ET& a, const Containers::StaticVector< Size, Real >& b ) -{ - return (a, b); -} - -template< typename Real1, int Size, typename Real2 > -__cuda_callable__ -auto -dot( const Containers::StaticVector< Size, Real1 >& a, const Containers::StaticVector< Size, Real2 >& b ) -{ - return (a, b); -} - - -//// -// Abs -template< int Size, typename Real > -__cuda_callable__ -auto -abs( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Abs >( a ); -} - -//// -// Power -template< int Size, typename Real, typename ExpType > -__cuda_callable__ -auto -pow( const Containers::StaticVector< Size, Real >& a, const ExpType& exp ) -{ - return Containers::Expressions::StaticBinaryExpressionTemplate< Containers::StaticVector< Size, Real >, ExpType, Containers::Expressions::Pow >( a, exp ); -} - -//// -// Exp -template< int Size, typename Real > -__cuda_callable__ -auto -exp( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Exp >( a ); -} - -//// -// Sqrt -template< int Size, typename Real > -__cuda_callable__ -auto -sqrt( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sqrt >( a ); -} - -//// -// Cbrt -template< int Size, typename Real > -__cuda_callable__ -auto -cbrt( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Cbrt >( a ); -} - -//// -// Log -template< int Size, typename Real > -__cuda_callable__ -auto -log( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Log >( a ); -} - -//// -// Log10 -template< int Size, typename Real > -__cuda_callable__ -auto -log10( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Log10 >( a ); -} - -//// -// Log2 -template< int Size, typename Real > -__cuda_callable__ -auto -log2( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Log2 >( a ); -} - -//// -// Sine -template< int Size, typename Real > -__cuda_callable__ -auto -sin( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sin >( a ); -} - -//// -// Cosine -template< int Size, typename Real > -__cuda_callable__ -auto -cos( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Cos >( a ); -} - -//// -// Tangent -template< int Size, typename Real > -__cuda_callable__ -auto -tan( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Tan >( a ); -} - -//// -// Asin -template< int Size, typename Real > -__cuda_callable__ -auto -asin( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Asin >( a ); -} - -//// -// Acos -template< int Size, typename Real > -__cuda_callable__ -auto -acos( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Acos >( a ); -} - -//// -// Atan -template< int Size, typename Real > -__cuda_callable__ -auto -atan( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Atan >( a ); -} - -//// -// Sinh -template< int Size, typename Real > -__cuda_callable__ -auto -sinh( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sinh >( a ); -} - -//// -// Cosh -template< int Size, typename Real > -__cuda_callable__ -auto -cosh( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Cosh >( a ); -} - -//// -// Tanh -template< int Size, typename Real > -__cuda_callable__ -auto -tanh( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Tanh >( a ); -} - -//// -// Asinh -template< int Size, typename Real > -__cuda_callable__ -auto -asinh( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Asinh >( a ); -} - -//// -// Acosh -template< int Size, typename Real > -__cuda_callable__ -auto -acosh( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Acosh >( a ); -} - -//// -// Atanh -template< int Size, typename Real > -__cuda_callable__ -auto -atanh( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Atanh >( a ); -} - -//// -// Floor -template< int Size, typename Real > -__cuda_callable__ -auto -floor( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Floor >( a ); -} - -//// -// Ceil -template< int Size, typename Real > -__cuda_callable__ -auto -ceil( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Ceil >( a ); -} - -//// -// Sign -template< int Size, typename Real > -__cuda_callable__ -auto -sign( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< Containers::StaticVector< Size, Real >, Containers::Expressions::Sign >( a ); -} - -//// -// Cast -template< typename ResultType, int Size, typename Real, - // workaround: templated type alias cannot be declared at block level - template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation > -auto -__cuda_callable__ -cast( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticUnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a ); -} - -//// -// Vertical operations - min -template< int Size, typename Real > -__cuda_callable__ -auto -min( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionMin( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -std::pair< int, Real > -argMin( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionArgMin( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -max( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionMax( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -std::pair< int, Real > -argMax( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionArgMax( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -sum( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionSum( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -maxNorm( const Containers::StaticVector< Size, Real >& a ) -{ - return max( abs( a ) ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -l1Norm( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionL1Norm( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -l2Norm( const Containers::StaticVector< Size, Real >& a ) -{ - return TNL::sqrt( Containers::Expressions::StaticExpressionL2Norm( a ) ); -} - -template< int Size, typename Real, typename Real2 > -__cuda_callable__ -auto -lpNorm( const Containers::StaticVector< Size, Real >& a, const Real2& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( Containers::Expressions::StaticExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -product( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionProduct( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -logicalOr( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionLogicalOr( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -binaryOr( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionBinaryOr( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -logicalAnd( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionLogicalAnd( a ); -} - -template< int Size, typename Real > -__cuda_callable__ -auto -binaryAnd( const Containers::StaticVector< Size, Real >& a ) -{ - return Containers::Expressions::StaticExpressionBinaryAnd( a ); -} - -} // namespace TNL -#endif // DOXYGEN_ONLY diff --git a/src/TNL/Containers/Vector.h b/src/TNL/Containers/Vector.h index 6bec6932115b03a47696de90a7a560c31762c4a2..259081052c1d0c1241f190cdad4002f98b3bf2d0 100644 --- a/src/TNL/Containers/Vector.h +++ b/src/TNL/Containers/Vector.h @@ -174,7 +174,7 @@ public: */ template< typename VectorExpression, typename..., - typename = std::enable_if_t< Expressions::IsExpressionTemplate< VectorExpression >::value > > + typename = std::enable_if_t< Expressions::HasEnabledExpressionTemplates< VectorExpression >::value && ! IsArrayType< VectorExpression >::value > > Vector& operator=( const VectorExpression& expression ); /** @@ -326,8 +326,15 @@ public: void segmentedScan( const VectorExpression& expression, FlagsArray& flags, IndexType begin = 0, IndexType end = 0 ); }; +// Enable expression templates for Vector +namespace Expressions { + template< typename Real, typename Device, typename Index, typename Allocator > + struct HasEnabledExpressionTemplates< Vector< Real, Device, Index, Allocator > > + : std::true_type + {}; +} // namespace Expressions + } // namespace Containers } // namespace TNL #include <TNL/Containers/Vector.hpp> -#include <TNL/Containers/VectorExpressions.h> diff --git a/src/TNL/Containers/VectorExpressions.h b/src/TNL/Containers/VectorExpressions.h deleted file mode 100644 index 83d682e8bd50d38a7d16bf1b8895cb624aa021a2..0000000000000000000000000000000000000000 --- a/src/TNL/Containers/VectorExpressions.h +++ /dev/null @@ -1,1098 +0,0 @@ -/*************************************************************************** - VectorExpressions.h - description - ------------------- - begin : Jun 27, 2019 - copyright : (C) 2019 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once - -#include <TNL/Containers/Expressions/ExpressionTemplates.h> - -#include "Vector.h" - -namespace TNL { -namespace Containers { - -/** - * \brief Addition of vector and vector expression. - * @param a - * @param b - * @return - */ -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator+( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Addition >( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator+( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Addition >( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator+( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator+( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator+( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Addition >( a.getConstView(), b.getConstView() ); -} - -//// -// Subtraction -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator-( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Subtraction >( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator-( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Subtraction >( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator-( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator-( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator-( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Subtraction >( a.getConstView(), b.getConstView() ); -} - -//// -// Multiplication -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator*( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Multiplication >( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator*( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Multiplication >( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator*( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator*( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator*( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Multiplication >( a.getConstView(), b.getConstView() ); -} - -//// -// Division -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator/( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView, ET, Expressions::Division >( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator/( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ET, ConstView, Expressions::Division >( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator/( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator/( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator/( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Expressions::Division >( a.getConstView(), b.getConstView() ); -} - -//// -// Comparison operations - operator == -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator==( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView, ET >::EQ( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator==( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ET, ConstView >::EQ( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator > -bool -operator==( const Vector< Real1, Device1, Index, Allocator >& a, const Vector< Real2, Device2, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device1, Index, Allocator >::ConstViewType; - using ConstView2 = typename Vector< Real2, Device2, Index, Allocator >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator > -bool -operator==( const VectorView< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index, Allocator >& b ) -{ - using ConstView1 = VectorView< Real1, Device1, Index >; - using ConstView2 = typename Vector< Real2, Device2, Index, Allocator >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator > -bool -operator==( const Vector< Real1, Device1, Index, Allocator >& a, const VectorView< Real2, Device2, Index >& b ) -{ - using ConstView1 = typename Vector< Real1, Device1, Index, Allocator >::ConstViewType; - using ConstView2 = VectorView< Real2, Device2, Index >; - return Expressions::Comparison< ConstView1, ConstView2 >::EQ( a.getConstView(), b ); -} - -//// -// Comparison operations - operator != -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator!=( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView, ET >::NE( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator!=( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ET, ConstView >::NE( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator > -bool -operator!=( const Vector< Real1, Device1, Index, Allocator >& a, const Vector< Real2, Device2, Index, Allocator >& b ) -{ - return ! (a == b); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator > -bool -operator!=( const VectorView< Real1, Device1, Index >& a, const Vector< Real2, Device2, Index, Allocator >& b ) -{ - return ! (a == b); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index, typename Allocator > -bool -operator!=( const Vector< Real1, Device1, Index, Allocator >& a, const VectorView< Real2, Device2, Index >& b ) -{ - return ! (a == b); -} - -//// -// Comparison operations - operator < -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView, ET >::LT( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ET, ConstView >::LT( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator<( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator<( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator<( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::LT( a.getConstView(), b.getConstView() ); -} - -//// -// Comparison operations - operator <= -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<=( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView, ET >::LE( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<=( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ET, ConstView >::LE( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator<=( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator<=( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator<=( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::LE( a.getConstView(), b.getConstView() ); -} - -//// -// Comparison operations - operator > -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView, ET >::GT( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ET, ConstView >::GT( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator>( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator>( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator>( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::GT( a.getConstView(), b.getConstView() ); -} - -//// -// Comparison operations - operator >= -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>=( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView, ET >::GE( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>=( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename VectorView< Real, Device, Index >::ConstViewType; - return Expressions::Comparison< ET, ConstView >::GE( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator>=( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator>=( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -bool -operator>=( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename VectorView< Real2, Device, Index >::ConstViewType; - return Expressions::Comparison< ConstView1, ConstView2 >::GE( a.getConstView(), b.getConstView() ); -} - -//// -// Minus -template< typename Real, typename Device, typename Index, typename Allocator > -auto -operator-( const Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Vector< Real, Device, Index, Allocator >::ConstViewType; - return Expressions::UnaryExpressionTemplate< ConstView, Expressions::Minus >( a.getConstView() ); -} - -//// -// Scalar product -#ifdef DOXYGEN_ONLY -/** - * \brief Computes scalar product of two vectors or vector expressions. Equivalent to \ref TNL::dot. - * - * @param a input vector or vector expression - * @param b input vector or vector expression - * @return scalar product of \e a and \e b. - */ -template< typename ET1, typename ET2 > -Real -operator,( const ET1& a, const ET2& b ) {} -#else - -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -Real -operator,( const Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - return Expressions::ExpressionSum( a.getConstView() * b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -Real -operator,( const ET& a, const Vector< Real, Device, Index, Allocator >& b ) -{ - return Expressions::ExpressionSum( a * b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator,( const Vector< Real1, Device, Index, Allocator >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - return Expressions::ExpressionSum( a.getConstView() * b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator,( const VectorView< Real1, Device, Index >& a, const Vector< Real2, Device, Index, Allocator >& b ) -{ - return Expressions::ExpressionSum( a.getConstView() * b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -operator,( const Vector< Real1, Device, Index, Allocator >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::ExpressionSum( a.getConstView() * b.getConstView() ); -} -#endif // DOXYGEN_ONLY - -} //namespace Containers - -//// -// All functions are supposed to be in namespace TNL - -//// -// Min -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -min( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Min >( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -min( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Min >( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -min( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -min( const Containers::VectorView< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -min( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Min >( a.getConstView(), b.getConstView() ); -} - -//// -// Max -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -max( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ConstView, ET, Containers::Expressions::Max >( a.getConstView(), b ); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -max( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ET, ConstView, Containers::Expressions::Max >( a, b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -max( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -max( const Containers::VectorView< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b ) -{ - using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getConstView(), b.getConstView() ); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -max( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::VectorView< Real2, Device, Index >& b ) -{ - using ConstView1 = typename Containers::Vector< Real1, Device, Index, Allocator >::ConstViewType; - using ConstView2 = typename Containers::Vector< Real2, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ConstView1, ConstView2, Containers::Expressions::Max >( a.getConstView(), b.getConstView() ); -} - -//// -// Dot product - the same as scalar product, just for convenience -#ifdef DOXYGEN_ONLY -/** - * \brief Computes scalar product of vector and vector expression. Equivalent to \ref TNL::Containers::operator,. - * - * @param a input vector - * @param b input vector expression - * @return scalar product of vector and vector expression - */ -template< typename ET1, typename ET2 > -auto -dot( const ET1& a, const ET2& b ) {} -#else - -template< typename Real, typename Device, typename Index, typename Allocator, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -dot( const Containers::Vector< Real, Device, Index, Allocator >& a, const ET& b ) -{ - return (a, b); -} - -template< typename ET, typename Real, typename Device, typename Index, typename Allocator, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -dot( const ET& a, const Containers::Vector< Real, Device, Index, Allocator >& b ) -{ - return (a, b); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -dot( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b ) -{ - return (a, b); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -dot( const Containers::VectorView< Real1, Device, Index >& a, const Containers::Vector< Real2, Device, Index, Allocator >& b ) -{ - return (a, b); -} - -template< typename Real1, typename Real2, typename Device, typename Index, typename Allocator > -auto -dot( const Containers::Vector< Real1, Device, Index, Allocator >& a, const Containers::VectorView< Real2, Device, Index >& b ) -{ - return (a, b); -} -#endif // DOXYGEN_ONLY - - -//// -// Abs -template< typename Real, typename Device, typename Index, typename Allocator > -auto -abs( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Abs >( a.getConstView() ); -} - -//// -// Power -template< typename Real, typename Device, typename Index, typename Allocator, typename ExpType > -auto -pow( const Containers::Vector< Real, Device, Index, Allocator >& a, const ExpType& exp ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::BinaryExpressionTemplate< ConstView, ExpType, Containers::Expressions::Pow >( a.getConstView(), exp ); -} - -//// -// Exp -template< typename Real, typename Device, typename Index, typename Allocator > -auto -exp( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Exp >( a.getConstView() ); -} - -//// -// Sqrt -template< typename Real, typename Device, typename Index, typename Allocator > -auto -sqrt( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sqrt >( a.getConstView() ); -} - -//// -// Cbrt -template< typename Real, typename Device, typename Index, typename Allocator > -auto -cbrt( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cbrt >( a.getConstView() ); -} - -//// -// Log -template< typename Real, typename Device, typename Index, typename Allocator > -auto -log( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log >( a.getConstView() ); -} - -//// -// Log10 -template< typename Real, typename Device, typename Index, typename Allocator > -auto -log10( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log10 >( a.getConstView() ); -} - -//// -// Log2 -template< typename Real, typename Device, typename Index, typename Allocator > -auto -log2( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Log2 >( a.getConstView() ); -} - -//// -// Sine -template< typename Real, typename Device, typename Index, typename Allocator > -auto -sin( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sin >( a.getConstView() ); -} - -//// -// Cosine -template< typename Real, typename Device, typename Index, typename Allocator > -auto -cos( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cos >( a.getConstView() ); -} - -//// -// Tangent -template< typename Real, typename Device, typename Index, typename Allocator > -auto -tan( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tan >( a.getConstView() ); -} - -//// -// Asin -template< typename Real, typename Device, typename Index, typename Allocator > -auto -asin( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Asin >( a.getConstView() ); -} - -//// -// Acos -template< typename Real, typename Device, typename Index, typename Allocator > -auto -acos( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Acos >( a.getConstView() ); -} - -//// -// Atan -template< typename Real, typename Device, typename Index, typename Allocator > -auto -atan( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Atan >( a.getConstView() ); -} - -//// -// Sinh -template< typename Real, typename Device, typename Index, typename Allocator > -auto -sinh( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sinh >( a.getConstView() ); -} - -//// -// Cosh -template< typename Real, typename Device, typename Index, typename Allocator > -auto -cosh( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Cosh >( a.getConstView() ); -} - -//// -// Tanh -template< typename Real, typename Device, typename Index, typename Allocator > -auto -tanh( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Tanh >( a.getConstView() ); -} - -//// -// Asinh -template< typename Real, typename Device, typename Index, typename Allocator > -auto -asinh( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Asinh >( a.getConstView() ); -} - -//// -// Acosh -template< typename Real, typename Device, typename Index, typename Allocator > -auto -acosh( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Acosh >( a.getConstView() ); -} - -//// -// Atanh -template< typename Real, typename Device, typename Index, typename Allocator > -auto -atanh( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Atanh >( a.getConstView() ); -} - -//// -// Floor -template< typename Real, typename Device, typename Index, typename Allocator > -auto -floor( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Floor >( a.getConstView() ); -} - -//// -// Ceil -template< typename Real, typename Device, typename Index, typename Allocator > -auto -ceil( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Ceil >( a.getConstView() ); -} - -//// -// Sign -template< typename Real, typename Device, typename Index, typename Allocator > -auto -sign( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - using ConstView = typename Containers::Vector< Real, Device, Index, Allocator >::ConstViewType; - return Containers::Expressions::UnaryExpressionTemplate< ConstView, Containers::Expressions::Sign >( a.getConstView() ); -} - -//// -// Cast -template< typename ResultType, typename Real, typename Device, typename Index, typename Allocator, - // workaround: templated type alias cannot be declared at block level - template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation > -auto -cast( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< decltype(a.getConstView()), Operation >( a.getConstView() ); -} - -//// -// Vertical operations - min -template< typename Real, - typename Device, - typename Index, typename Allocator > -Real -min( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionMin( a.getConstView() ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator > -std::pair< Index, std::decay_t< Real > > -argMin( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionArgMin( a.getConstView() ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator > -Real -max( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionMax( a.getConstView() ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator > -std::pair< Index, std::decay_t< Real > > -argMax( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionArgMax( a.getConstView() ); -} - -/** - * \brief Computes sum of all vector elements. - * - * @param a input vector - * @return sum of all vector elements - */ -template< typename Real, - typename Device, - typename Index, typename Allocator > -auto -sum( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionSum( a.getConstView() ); -} - -/** - * \brief Computes maximum norm of a vector. - * \anchor TNL__maxNorm - * - * @param a input vector - * @return maximum norm - */ -template< typename Real, - typename Device, - typename Index, typename Allocator > -auto -maxNorm( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return max( abs( a ) ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator > -auto -l1Norm( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionL1Norm( a.getConstView() ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator > -auto -l2Norm( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return TNL::sqrt( Containers::Expressions::ExpressionL2Norm( a.getConstView() ) ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator, - typename Real2 > -auto -lpNorm( const Containers::Vector< Real, Device, Index, Allocator >& a, const Real2& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( Containers::Expressions::ExpressionLpNorm( a.getConstView(), p ), 1.0 / p ); -} - -/** - * \brief Computes product of all vector elements. - * @param a - * @return - */ -template< typename Real, - typename Device, - typename Index, typename Allocator > -auto -product( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionProduct( a.getConstView() ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator > -auto -logicalOr( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionLogicalOr( a.getConstView() ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator > -auto -binaryOr( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionBinaryOr( a.getConstView() ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator > -auto -logicalAnd( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionLogicalAnd( a.getConstView() ); -} - -template< typename Real, - typename Device, - typename Index, typename Allocator > -auto -binaryAnd( const Containers::Vector< Real, Device, Index, Allocator >& a ) -{ - return Containers::Expressions::ExpressionBinaryAnd( a.getConstView() ); -} - -} // namespace TNL diff --git a/src/TNL/Containers/VectorView.h b/src/TNL/Containers/VectorView.h index 1a144ea5cde79951ee059f386859322eba18cf57..4c5262d30f4ec904d176da1a33313ad94d64cd0f 100644 --- a/src/TNL/Containers/VectorView.h +++ b/src/TNL/Containers/VectorView.h @@ -138,7 +138,7 @@ public: */ template< typename VectorExpression, typename..., - typename = std::enable_if_t< Expressions::IsExpressionTemplate< VectorExpression >::value > > + typename = std::enable_if_t< Expressions::HasEnabledExpressionTemplates< VectorExpression >::value && ! IsArrayType< VectorExpression >::value > > VectorView& operator=( const VectorExpression& expression ); /** @@ -294,8 +294,15 @@ public: void segmentedScan( const VectorExpression& expression, FlagsArray& flags, IndexType begin = 0, IndexType end = 0 ); }; +// Enable expression templates for VectorView +namespace Expressions { + template< typename Real, typename Device, typename Index > + struct HasEnabledExpressionTemplates< VectorView< Real, Device, Index > > + : std::true_type + {}; +} // namespace Expressions + } // namespace Containers } // namespace TNL #include <TNL/Containers/VectorView.hpp> -#include <TNL/Containers/VectorViewExpressions.h> diff --git a/src/TNL/Containers/VectorViewExpressions.h b/src/TNL/Containers/VectorViewExpressions.h deleted file mode 100644 index 6168b54066d74ac5151e40ed1100116353759556..0000000000000000000000000000000000000000 --- a/src/TNL/Containers/VectorViewExpressions.h +++ /dev/null @@ -1,740 +0,0 @@ -/*************************************************************************** - VectorViewExpressions.h - description - ------------------- - begin : Apr 27, 2019 - copyright : (C) 2019 by Tomas Oberhuber et al. - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#pragma once -#ifndef DOXYGEN_ONLY - -#include <TNL/Containers/Expressions/ExpressionTemplates.h> - -#include "VectorView.h" - -namespace TNL { -namespace Containers { - -//// -// Addition -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator+( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Addition >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator+( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Addition >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -auto -operator+( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Addition >( a, b ); -} - -//// -// Subtraction -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator-( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Subtraction >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator-( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Subtraction >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -auto -operator-( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Subtraction >( a, b ); -} - -//// -// Multiplication -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator*( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Multiplication >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator*( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Multiplication >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -auto -operator*( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Multiplication >( a, b ); -} - -//// -// Division -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator/( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::BinaryExpressionTemplate< VectorView< Real, Device, Index >, ET, Expressions::Division >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator/( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::BinaryExpressionTemplate< ET, VectorView< Real, Device, Index >, Expressions::Division >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -auto -operator/( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::BinaryExpressionTemplate< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index >, Expressions::Division >( a, b ); -} - -//// -// Comparison operations - operator == -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator==( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::EQ( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator==( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::EQ( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index > -bool -operator==( const VectorView< Real1, Device1, Index >& a, const VectorView< Real2, Device2, Index >& b ) -{ - return Expressions::Comparison< VectorView< Real1, Device1, Index >, VectorView< Real2, Device2, Index > >::EQ( a, b ); -} - -//// -// Comparison operations - operator != -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator!=( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::NE( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator!=( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::NE( a, b ); -} - -template< typename Real1, typename Real2, typename Device1, typename Device2, typename Index > -bool -operator!=( const VectorView< Real1, Device1, Index >& a, const VectorView< Real2, Device2, Index >& b ) -{ - return ! (a == b); -} - -//// -// Comparison operations - operator < -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::LT( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::LT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -bool -operator<( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::LT( a, b ); -} - -//// -// Comparison operations - operator <= -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<=( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::LE( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator<=( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::LE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -bool -operator<=( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::LE( a, b ); -} - -//// -// Comparison operations - operator > -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::GT( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::GT( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -bool -operator>( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::GT( a, b ); -} - -//// -// Comparison operations - operator >= -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>=( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::Comparison< VectorView< Real, Device, Index >, ET >::GE( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -bool -operator>=( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::Comparison< ET, VectorView< Real, Device, Index > >::GE( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -bool -operator>=( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::Comparison< VectorView< Real1, Device, Index >, VectorView< Real2, Device, Index > >::GE( a, b ); -} - -//// -// Minus -template< typename Real, typename Device, typename Index > -auto -operator-( const VectorView< Real, Device, Index >& a ) -{ - return Expressions::UnaryExpressionTemplate< VectorView< Real, Device, Index >, Expressions::Minus >( a ); -} - -//// -// Scalar product -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator,( const VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Expressions::ExpressionSum( a * b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Expressions::IsNumericExpression<ET>::value > > -auto -operator,( const ET& a, const VectorView< Real, Device, Index >& b ) -{ - return Expressions::ExpressionSum( a * b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -auto -operator,( const VectorView< Real1, Device, Index >& a, const VectorView< Real2, Device, Index >& b ) -{ - return Expressions::ExpressionSum( a * b ); -} - -} // namespace Containers - -//// -// All functions are supposed to be in namespace TNL - -//// -// Min -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -min( const Containers::VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Min >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -min( const ET& a, const Containers::VectorView< Real, Device, Index >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Min >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -auto -min( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Min >( a, b ); -} - -//// -// Max -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -max( const Containers::VectorView< Real, Device, Index >& a, const ET& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ET, Containers::Expressions::Max >( a, b ); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -max( const ET& a, const Containers::VectorView< Real, Device, Index >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< ET, Containers::VectorView< Real, Device, Index >, Containers::Expressions::Max >( a, b ); -} - -template< typename Real1, typename Real2, typename Device, typename Index > -auto -max( const Containers::VectorView< Real1, Device, Index >& a, const Containers::VectorView< Real2, Device, Index >& b ) -{ - return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real1, Device, Index >, Containers::VectorView< Real2, Device, Index >, Containers::Expressions::Max >( a, b ); -} - -//// -// Dot product - the same as scalar product, just for convenience -template< typename Real, typename Device, typename Index, typename ET, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -dot( const Containers::VectorView< Real, Device, Index >& a, const ET& b ) -{ - return (a, b); -} - -template< typename ET, typename Real, typename Device, typename Index, - typename..., typename = std::enable_if_t< Containers::Expressions::IsNumericExpression<ET>::value > > -auto -dot( const ET& a, const Containers::VectorView< Real, Device, Index >& b ) -{ - return (a, b); -} - -template< typename Real1, typename Real2, typename Device, typename Index1, typename Index2 > -auto -dot( const Containers::VectorView< Real1, Device, Index1 >& a, const Containers::VectorView< Real2, Device, Index2 >& b ) -{ - return (a, b); -} - - -//// -// Abs -template< typename Real, typename Device, typename Index > -auto -abs( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Abs >( a ); -} - -//// -// Power -template< typename Real, typename Device, typename Index, typename ExpType > -auto -pow( const Containers::VectorView< Real, Device, Index >& a, const ExpType& exp ) -{ - return Containers::Expressions::BinaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, ExpType, Containers::Expressions::Pow >( a, exp ); -} - -//// -// Exp -template< typename Real, typename Device, typename Index > -auto -exp( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Exp >( a ); -} - -//// -// Sqrt -template< typename Real, typename Device, typename Index > -auto -sqrt( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sqrt >( a ); -} - -//// -// Cbrt -template< typename Real, typename Device, typename Index > -auto -cbrt( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cbrt >( a ); -} - -//// -// Log -template< typename Real, typename Device, typename Index > -auto -log( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log >( a ); -} - -//// -// Log10 -template< typename Real, typename Device, typename Index > -auto -log10( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log10 >( a ); -} - -//// -// Log2 -template< typename Real, typename Device, typename Index > -auto -log2( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Log2 >( a ); -} - -//// -// Sine -template< typename Real, typename Device, typename Index > -auto -sin( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sin >( a ); -} - -//// -// Cosine -template< typename Real, typename Device, typename Index > -auto -cos( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cos >( a ); -} - -//// -// Tangent -template< typename Real, typename Device, typename Index > -auto -tan( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tan >( a ); -} - -//// -// Asin -template< typename Real, typename Device, typename Index > -auto -asin( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Asin >( a ); -} - -//// -// Acos -template< typename Real, typename Device, typename Index > -auto -acos( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Acos >( a ); -} - -//// -// Atan -template< typename Real, typename Device, typename Index > -auto -atan( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Atan >( a ); -} - -//// -// Sinh -template< typename Real, typename Device, typename Index > -auto -sinh( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sinh >( a ); -} - -//// -// Cosh -template< typename Real, typename Device, typename Index > -auto -cosh( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Cosh >( a ); -} - -//// -// Tanh -template< typename Real, typename Device, typename Index > -auto -tanh( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Tanh >( a ); -} - -//// -// Asinh -template< typename Real, typename Device, typename Index > -auto -asinh( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Asinh >( a ); -} - -//// -// Acosh -template< typename Real, typename Device, typename Index > -auto -acosh( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Acosh >( a ); -} - -//// -// Atanh -template< typename Real, typename Device, typename Index > -auto -atanh( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Atanh >( a ); -} - -//// -// Floor -template< typename Real, typename Device, typename Index > -auto -floor( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Floor >( a ); -} - -//// -// Ceil -template< typename Real, typename Device, typename Index > -auto -ceil( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Ceil >( a ); -} - -//// -// Sign -template< typename Real, typename Device, typename Index > -auto -sign( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< Containers::VectorView< Real, Device, Index >, Containers::Expressions::Sign >( a ); -} - -//// -// Cast -template< typename ResultType, typename Real, typename Device, typename Index, - // workaround: templated type alias cannot be declared at block level - template<typename> class Operation = Containers::Expressions::Cast< ResultType >::template Operation > -auto -cast( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::UnaryExpressionTemplate< std::decay_t<decltype(a)>, Operation >( a ); -} - -//// -// Vertical operations - min -template< typename Real, - typename Device, - typename Index > -Real -min( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionMin( a ); -} - -template< typename Real, - typename Device, - typename Index > -std::pair< Index, std::decay_t< Real > > -argMin( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionArgMin( a ); -} - -template< typename Real, - typename Device, - typename Index > -Real -max( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionMax( a ); -} - -template< typename Real, - typename Device, - typename Index > -std::pair< Index, std::decay_t< Real > > -argMax( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionArgMax( a ); -} - -template< typename Real, - typename Device, - typename Index > -auto -sum( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionSum( a ); -} - -template< typename Real, - typename Device, - typename Index > -auto -maxNorm( const Containers::VectorView< Real, Device, Index >& a ) -{ - return max( abs( a ) ); -} - -template< typename Real, - typename Device, - typename Index > -auto -l1Norm( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionL1Norm( a ); -} - -template< typename Real, - typename Device, - typename Index > -auto -l2Norm( const Containers::VectorView< Real, Device, Index >& a ) -{ - return TNL::sqrt( Containers::Expressions::ExpressionL2Norm( a ) ); -} - -template< typename Real, - typename Device, - typename Index, - typename Real2 > -auto -lpNorm( const Containers::VectorView< Real, Device, Index >& a, const Real2& p ) -// since (1.0 / p) has type double, TNL::pow returns double --> double -{ - if( p == 1.0 ) - return l1Norm( a ); - if( p == 2.0 ) - return l2Norm( a ); - return TNL::pow( Containers::Expressions::ExpressionLpNorm( a, p ), 1.0 / p ); -} - -template< typename Real, - typename Device, - typename Index > -auto -product( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionProduct( a ); -} - -template< typename Real, - typename Device, - typename Index > -auto -logicalOr( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionLogicalOr( a ); -} - -template< typename Real, - typename Device, - typename Index > -auto -binaryOr( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionBinaryOr( a ); -} - -template< typename Real, - typename Device, - typename Index > -auto -logicalAnd( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionLogicalAnd( a ); -} - -template< typename Real, - typename Device, - typename Index > -auto -binaryAnd( const Containers::VectorView< Real, Device, Index >& a ) -{ - return Containers::Expressions::ExpressionBinaryAnd( a ); -} - -} // namespace TNL -#endif // DOXYGEN_ONLY diff --git a/src/TNL/TypeTraits.h b/src/TNL/TypeTraits.h index d617f2b42454bce2fad7a5d2ff69b685574723c9..3183460fef20a663705c02b641f8c866e2cde1c7 100644 --- a/src/TNL/TypeTraits.h +++ b/src/TNL/TypeTraits.h @@ -103,6 +103,33 @@ public: static constexpr bool value = type::value; }; +/** + * \brief Type trait for checking if T has operator+= taking one argument of type T. + */ +template< typename T > +class HasAddAssignmentOperator +{ +private: + template< typename U > + static constexpr auto check(U*) + -> typename + std::enable_if_t< + ! std::is_same< + decltype( std::declval<U>() += std::declval<U>() ), + void + >::value, + std::true_type + >; + + template< typename > + static constexpr std::false_type check(...); + + using type = decltype(check<T>(0)); + +public: + static constexpr bool value = type::value; +}; + /** * \brief Type trait for checking if T is an array type, e.g. * \ref Containers::Array or \ref Containers::Vector. @@ -118,6 +145,17 @@ struct IsArrayType HasSubscriptOperator< T >::value > {}; +/** + * \brief Type trait for checking if T is a vector type, e.g. + * \ref Containers::Vector or \ref Containers::VectorView. + */ +template< typename T > +struct IsVectorType +: public std::integral_constant< bool, + IsArrayType< T >::value && + HasAddAssignmentOperator< T >::value > +{}; + /** * \brief Type trait for checking if T has a \e constexpr \e getSize method. */