Loading Documentation/Tutorials/ReductionAndScan/ReductionWithArgumentWithFunctional.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ maximumNorm( const Vector< double, Device >& v ) auto view = v.getConstView(); auto fetch = [=] __cuda_callable__ ( int i ) { return abs( view[ i ] ); }; return reduceWithArgument< Device >( 0, view.getSize(), fetch, TNL::MaxWithArg<>{} ); return reduceWithArgument< Device >( 0, view.getSize(), fetch, TNL::MaxWithArg{} ); } int main( int argc, char* argv[] ) Loading Documentation/Tutorials/ReductionAndScan/ScalarProductWithFunctionalExample.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ double scalarProduct( const Vector< double, Device >& u, const Vector< double, D return reduce< Device >( 0, v_view.getSize(), [=] __cuda_callable__ ( int i ) { return u_view[ i ] * v_view[ i ]; }, TNL::Plus<>{} ); TNL::Plus{} ); } int main( int argc, char* argv[] ) Loading Documentation/Tutorials/ReductionAndScan/SumExampleWithFunctional.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ double sum( const Vector< double, Device >& v ) * Finally we call the templated function Reduction and pass number of elements to reduce, * lambda defined above and functional representing the reduction operation. */ return reduce< Device >( 0, view.getSize(), fetch, TNL::Plus<>{} ); return reduce< Device >( 0, view.getSize(), fetch, TNL::Plus{} ); } int main( int argc, char* argv[] ) Loading Documentation/Tutorials/ReductionAndScan/tutorial_ReductionAndScan.md +12 −12 Original line number Diff line number Diff line Loading @@ -170,17 +170,17 @@ This example also shows more compact how to evoke the function `reduce` (lines 1 In \ref TNL/Functionals.h you may find probably all operations that can be reasonably used for reduction: | Functional | Reduction operation | |-----------------------------------|--------------------------| | \ref TNL::Plus<> | Sum | | \ref TNL::Multiplies<> | Product | | \ref TNL::Min<> | Minimum | | \ref TNL::Max<> | Maximum | | \ref TNL::MinWithArg<> | Minimum with argument | | \ref TNL::MaxWithArg<> | Maximum with argument | | \ref TNL::LogicalAnd<> | Logical AND | | \ref TNL::LogicalOr<> | Logical OR | | \ref TNL::BitAnd<> | Bit AND | | \ref TNL::BitOr<> | Bit OR | |---------------------------------|--------------------------| | \ref TNL::Plus | Sum | | \ref TNL::Multiplies | Product | | \ref TNL::Min | Minimum | | \ref TNL::Max | Maximum | | \ref TNL::MinWithArg | Minimum with argument | | \ref TNL::MaxWithArg | Maximum with argument | | \ref TNL::LogicalAnd | Logical AND | | \ref TNL::LogicalOr | Logical OR | | \ref TNL::BitAnd | Bit AND | | \ref TNL::BitOr | Bit OR | ## Flexible scan Loading src/TNL/Functional.h +26 −226 Original line number Diff line number Diff line Loading @@ -10,164 +10,68 @@ #pragma once #include <functional> #include <algorithm> #include <limits> namespace TNL { /** * \brief Replacement of std::plus optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct Plus { using ValueType = Value; static constexpr Value getIdempotent() { return ( Value ) 0; }; constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs + rhs; } }; /** * \brief Replacement of std::plus optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::plus for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct Plus< void > struct Plus : public std::plus< void > { template< typename T > static constexpr T getIdempotent() { return ( T ) 0; }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs + rhs; } }; /** * \brief Replacement of std::multiplies optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct Multiplies { using ValueType = Value; static constexpr ValueType idempotent = 1; constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs * rhs; } }; /** * \brief Replacement of std::multiplies optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::multiplies for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct Multiplies< void > struct Multiplies : public std::multiplies< void > { template< typename T > static constexpr T getIdempotent() { return ( T ) 1; }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs * rhs; } }; /** * \brief Replacement of std::min optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct Min { using ValueType = Value; static constexpr ValueType idempotent = std::numeric_limits< Value >::max(); constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs < rhs ? lhs : rhs; } }; /** * \brief Replacement of std::min optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::min for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct Min< void > struct Min { template< typename T > static constexpr T getIdempotent() { return std::numeric_limits< T >::max(); }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs < rhs ? lhs : rhs; } }; /** * \brief Replacement of std::max optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct Max { using ValueType = Value; static constexpr ValueType idempotent = std::numeric_limits< Value >::min(); constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs > rhs ? lhs : rhs; } template< typename Value > constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs < rhs ? lhs : rhs; } }; /** * \brief Replacement of std::max optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::max for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct Max< void > struct Max { template< typename T > static constexpr T getIdempotent() { return std::numeric_limits< T >::min(); }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs > rhs ? lhs : rhs; } }; /** * \brief Replacement of std::min optimized for use with \ref TNL::Algorithms::reduceWithArgument. * * \tparam Value is data type. */ template< typename Value = void, typename Index = void > struct MinWithArg { using ValueType = Value; static constexpr ValueType idempotent = std::numeric_limits< Value >::max(); constexpr void operator()( Value& lhs, const Value& rhs, Index& lhsIdx, const Index& rhsIdx ) const { if( lhs > rhs ) { lhs = rhs; lhsIdx = rhsIdx; } else if( lhs == rhs && rhsIdx < lhsIdx ) { lhsIdx = rhsIdx; } } template< typename Value > constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs > rhs ? lhs : rhs; } }; /** * \brief Replacement of std::min optimized for use with \ref TNL::Algorithms::reduceWithArgument. * \brief Extension of std::min for use with \ref TNL::Algorithms::reduceWithArgument. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct MinWithArg< void, void > struct MinWithArg { template< typename T > static constexpr T getIdempotent() { return std::numeric_limits< T >::max(); }; Loading @@ -188,38 +92,11 @@ struct MinWithArg< void, void > }; /** * \brief Replacement of std::max optimized for use with \ref TNL::Algorithms::reduceWithArgument. * * \tparam Value is data type. */ template< typename Value = void, typename Index = void > struct MaxWithArg { using ValueType = Value; static constexpr ValueType idempotent = std::numeric_limits< Value >::min(); constexpr void operator()( Value& lhs, const Value& rhs, Index& lhsIdx, const Index& rhsIdx ) const { if( lhs < rhs ) { lhs = rhs; lhsIdx = rhsIdx; } else if( lhs == rhs && rhsIdx < lhsIdx ) { lhsIdx = rhsIdx; } } }; /** * \brief Replacement of std::max optimized for use with \ref TNL::Algorithms::reduceWithArgument. * \brief Extension of std::max for use with \ref TNL::Algorithms::reduceWithArgument. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct MaxWithArg< void, void > struct MaxWithArg { template< typename T > static constexpr T getIdempotent() { return std::numeric_limits< T >::min(); }; Loading @@ -240,124 +117,47 @@ struct MaxWithArg< void, void > }; /** * \brief Replacement of std::logical_and optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct LogicalAnd { using ValueType = Value; static constexpr ValueType idempotent = ( Value ) true; constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs && rhs; } }; /** * \brief Replacement of std::logical_and optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::logical_and for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct LogicalAnd< void > struct LogicalAnd : public std::logical_and< void > { template< typename T > static constexpr T getIdempotent() { return ( T ) true; }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs && rhs; } }; /** * \brief Replacement of std::logical_or optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct LogicalOr { using ValueType = Value; static constexpr ValueType idempotent = ( Value ) false; constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs || rhs; } }; /** * \brief Replacement of std::logical_or optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::logical_or for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct LogicalOr< void > struct LogicalOr : public std::logical_or< void > { template< typename T > static constexpr T getIdempotent() { return ( T ) false; }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs || rhs; } }; /** * \brief Replacement of std::bit_and optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct BitAnd { using ValueType = Value; static constexpr ValueType idempotent = ~static_cast< ValueType >( 0 ); constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs & rhs; } }; /** * \brief Replacement of std::bit_and optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::bit_and for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct BitAnd< void > struct BitAnd : public std::bit_and< void > { template< typename T > static constexpr T getIdempotent() { return ~static_cast< T >( 0 ); }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs & rhs; } }; /** * \brief Replacement of std::bit_or optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct BitOr { using ValueType = Value; static constexpr ValueType idempotent = static_cast< ValueType >( 0 ); constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs | rhs; } }; /** * \brief Replacement of std::bit_or optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::bit_or for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct BitOr< void > struct BitOr : public std::bit_or< void > { template< typename T > static constexpr T getIdempotent() { return static_cast< T >( 0 ); }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs | rhs; } }; } // namespace TNL Loading
Documentation/Tutorials/ReductionAndScan/ReductionWithArgumentWithFunctional.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ maximumNorm( const Vector< double, Device >& v ) auto view = v.getConstView(); auto fetch = [=] __cuda_callable__ ( int i ) { return abs( view[ i ] ); }; return reduceWithArgument< Device >( 0, view.getSize(), fetch, TNL::MaxWithArg<>{} ); return reduceWithArgument< Device >( 0, view.getSize(), fetch, TNL::MaxWithArg{} ); } int main( int argc, char* argv[] ) Loading
Documentation/Tutorials/ReductionAndScan/ScalarProductWithFunctionalExample.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ double scalarProduct( const Vector< double, Device >& u, const Vector< double, D return reduce< Device >( 0, v_view.getSize(), [=] __cuda_callable__ ( int i ) { return u_view[ i ] * v_view[ i ]; }, TNL::Plus<>{} ); TNL::Plus{} ); } int main( int argc, char* argv[] ) Loading
Documentation/Tutorials/ReductionAndScan/SumExampleWithFunctional.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -24,7 +24,7 @@ double sum( const Vector< double, Device >& v ) * Finally we call the templated function Reduction and pass number of elements to reduce, * lambda defined above and functional representing the reduction operation. */ return reduce< Device >( 0, view.getSize(), fetch, TNL::Plus<>{} ); return reduce< Device >( 0, view.getSize(), fetch, TNL::Plus{} ); } int main( int argc, char* argv[] ) Loading
Documentation/Tutorials/ReductionAndScan/tutorial_ReductionAndScan.md +12 −12 Original line number Diff line number Diff line Loading @@ -170,17 +170,17 @@ This example also shows more compact how to evoke the function `reduce` (lines 1 In \ref TNL/Functionals.h you may find probably all operations that can be reasonably used for reduction: | Functional | Reduction operation | |-----------------------------------|--------------------------| | \ref TNL::Plus<> | Sum | | \ref TNL::Multiplies<> | Product | | \ref TNL::Min<> | Minimum | | \ref TNL::Max<> | Maximum | | \ref TNL::MinWithArg<> | Minimum with argument | | \ref TNL::MaxWithArg<> | Maximum with argument | | \ref TNL::LogicalAnd<> | Logical AND | | \ref TNL::LogicalOr<> | Logical OR | | \ref TNL::BitAnd<> | Bit AND | | \ref TNL::BitOr<> | Bit OR | |---------------------------------|--------------------------| | \ref TNL::Plus | Sum | | \ref TNL::Multiplies | Product | | \ref TNL::Min | Minimum | | \ref TNL::Max | Maximum | | \ref TNL::MinWithArg | Minimum with argument | | \ref TNL::MaxWithArg | Maximum with argument | | \ref TNL::LogicalAnd | Logical AND | | \ref TNL::LogicalOr | Logical OR | | \ref TNL::BitAnd | Bit AND | | \ref TNL::BitOr | Bit OR | ## Flexible scan Loading
src/TNL/Functional.h +26 −226 Original line number Diff line number Diff line Loading @@ -10,164 +10,68 @@ #pragma once #include <functional> #include <algorithm> #include <limits> namespace TNL { /** * \brief Replacement of std::plus optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct Plus { using ValueType = Value; static constexpr Value getIdempotent() { return ( Value ) 0; }; constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs + rhs; } }; /** * \brief Replacement of std::plus optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::plus for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct Plus< void > struct Plus : public std::plus< void > { template< typename T > static constexpr T getIdempotent() { return ( T ) 0; }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs + rhs; } }; /** * \brief Replacement of std::multiplies optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct Multiplies { using ValueType = Value; static constexpr ValueType idempotent = 1; constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs * rhs; } }; /** * \brief Replacement of std::multiplies optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::multiplies for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct Multiplies< void > struct Multiplies : public std::multiplies< void > { template< typename T > static constexpr T getIdempotent() { return ( T ) 1; }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs * rhs; } }; /** * \brief Replacement of std::min optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct Min { using ValueType = Value; static constexpr ValueType idempotent = std::numeric_limits< Value >::max(); constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs < rhs ? lhs : rhs; } }; /** * \brief Replacement of std::min optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::min for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct Min< void > struct Min { template< typename T > static constexpr T getIdempotent() { return std::numeric_limits< T >::max(); }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs < rhs ? lhs : rhs; } }; /** * \brief Replacement of std::max optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct Max { using ValueType = Value; static constexpr ValueType idempotent = std::numeric_limits< Value >::min(); constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs > rhs ? lhs : rhs; } template< typename Value > constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs < rhs ? lhs : rhs; } }; /** * \brief Replacement of std::max optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::max for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct Max< void > struct Max { template< typename T > static constexpr T getIdempotent() { return std::numeric_limits< T >::min(); }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs > rhs ? lhs : rhs; } }; /** * \brief Replacement of std::min optimized for use with \ref TNL::Algorithms::reduceWithArgument. * * \tparam Value is data type. */ template< typename Value = void, typename Index = void > struct MinWithArg { using ValueType = Value; static constexpr ValueType idempotent = std::numeric_limits< Value >::max(); constexpr void operator()( Value& lhs, const Value& rhs, Index& lhsIdx, const Index& rhsIdx ) const { if( lhs > rhs ) { lhs = rhs; lhsIdx = rhsIdx; } else if( lhs == rhs && rhsIdx < lhsIdx ) { lhsIdx = rhsIdx; } } template< typename Value > constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs > rhs ? lhs : rhs; } }; /** * \brief Replacement of std::min optimized for use with \ref TNL::Algorithms::reduceWithArgument. * \brief Extension of std::min for use with \ref TNL::Algorithms::reduceWithArgument. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct MinWithArg< void, void > struct MinWithArg { template< typename T > static constexpr T getIdempotent() { return std::numeric_limits< T >::max(); }; Loading @@ -188,38 +92,11 @@ struct MinWithArg< void, void > }; /** * \brief Replacement of std::max optimized for use with \ref TNL::Algorithms::reduceWithArgument. * * \tparam Value is data type. */ template< typename Value = void, typename Index = void > struct MaxWithArg { using ValueType = Value; static constexpr ValueType idempotent = std::numeric_limits< Value >::min(); constexpr void operator()( Value& lhs, const Value& rhs, Index& lhsIdx, const Index& rhsIdx ) const { if( lhs < rhs ) { lhs = rhs; lhsIdx = rhsIdx; } else if( lhs == rhs && rhsIdx < lhsIdx ) { lhsIdx = rhsIdx; } } }; /** * \brief Replacement of std::max optimized for use with \ref TNL::Algorithms::reduceWithArgument. * \brief Extension of std::max for use with \ref TNL::Algorithms::reduceWithArgument. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct MaxWithArg< void, void > struct MaxWithArg { template< typename T > static constexpr T getIdempotent() { return std::numeric_limits< T >::min(); }; Loading @@ -240,124 +117,47 @@ struct MaxWithArg< void, void > }; /** * \brief Replacement of std::logical_and optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct LogicalAnd { using ValueType = Value; static constexpr ValueType idempotent = ( Value ) true; constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs && rhs; } }; /** * \brief Replacement of std::logical_and optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::logical_and for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct LogicalAnd< void > struct LogicalAnd : public std::logical_and< void > { template< typename T > static constexpr T getIdempotent() { return ( T ) true; }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs && rhs; } }; /** * \brief Replacement of std::logical_or optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct LogicalOr { using ValueType = Value; static constexpr ValueType idempotent = ( Value ) false; constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs || rhs; } }; /** * \brief Replacement of std::logical_or optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::logical_or for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct LogicalOr< void > struct LogicalOr : public std::logical_or< void > { template< typename T > static constexpr T getIdempotent() { return ( T ) false; }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs || rhs; } }; /** * \brief Replacement of std::bit_and optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct BitAnd { using ValueType = Value; static constexpr ValueType idempotent = ~static_cast< ValueType >( 0 ); constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs & rhs; } }; /** * \brief Replacement of std::bit_and optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::bit_and for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct BitAnd< void > struct BitAnd : public std::bit_and< void > { template< typename T > static constexpr T getIdempotent() { return ~static_cast< T >( 0 ); }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs & rhs; } }; /** * \brief Replacement of std::bit_or optimized for use with \ref TNL::Algorithms::reduce. * * \tparam Value is data type. */ template< typename Value = void > struct BitOr { using ValueType = Value; static constexpr ValueType idempotent = static_cast< ValueType >( 0 ); constexpr Value operator()( const Value& lhs, const Value& rhs ) const { return lhs | rhs; } }; /** * \brief Replacement of std::bit_or optimized for use with \ref TNL::Algorithms::reduce. * \brief Extension of std::bit_or for use with \ref TNL::Algorithms::reduce. * * This is specialization for void type. The real type is deduced just when operator() is evoked. */ template<> struct BitOr< void > struct BitOr : public std::bit_or< void > { template< typename T > static constexpr T getIdempotent() { return static_cast< T >( 0 ); }; template< typename T > constexpr T operator()( const T& lhs, const T& rhs ) const { return lhs | rhs; } }; } // namespace TNL