File indexing completed on 2025-01-18 09:43:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_HPP
0013 #define BOOST_UBLAS_TENSOR_OPERATORS_COMPARISON_HPP
0014
0015 #include <boost/numeric/ublas/tensor/expression.hpp>
0016 #include <boost/numeric/ublas/tensor/expression_evaluation.hpp>
0017 #include <type_traits>
0018 #include <functional>
0019
0020 namespace boost::numeric::ublas {
0021 template<class element_type, class storage_format, class storage_type>
0022 class tensor;
0023 }
0024
0025 namespace boost::numeric::ublas::detail {
0026
0027 template<class T, class F, class A, class BinaryPred>
0028 bool compare(tensor<T,F,A> const& lhs, tensor<T,F,A> const& rhs, BinaryPred pred)
0029 {
0030
0031 if(lhs.extents() != rhs.extents()){
0032 if constexpr(!std::is_same<BinaryPred,std::equal_to<>>::value && !std::is_same<BinaryPred,std::not_equal_to<>>::value)
0033 throw std::runtime_error("Error in boost::numeric::ublas::detail::compare: cannot compare tensors with different shapes.");
0034 else
0035 return false;
0036 }
0037
0038 if constexpr(std::is_same<BinaryPred,std::greater<>>::value || std::is_same<BinaryPred,std::less<>>::value)
0039 if(lhs.empty())
0040 return false;
0041
0042 for(auto i = 0u; i < lhs.size(); ++i)
0043 if(!pred(lhs(i), rhs(i)))
0044 return false;
0045 return true;
0046 }
0047
0048 template<class T, class F, class A, class UnaryPred>
0049 bool compare(tensor<T,F,A> const& rhs, UnaryPred pred)
0050 {
0051 for(auto i = 0u; i < rhs.size(); ++i)
0052 if(!pred(rhs(i)))
0053 return false;
0054 return true;
0055 }
0056
0057
0058 template<class T, class L, class R, class BinaryPred>
0059 bool compare(tensor_expression<T,L> const& lhs, tensor_expression<T,R> const& rhs, BinaryPred pred)
0060 {
0061 constexpr bool lhs_is_tensor = std::is_same<T,L>::value;
0062 constexpr bool rhs_is_tensor = std::is_same<T,R>::value;
0063
0064 if constexpr (lhs_is_tensor && rhs_is_tensor)
0065 return compare(static_cast<T const&>( lhs ), static_cast<T const&>( rhs ), pred);
0066 else if constexpr (lhs_is_tensor && !rhs_is_tensor)
0067 return compare(static_cast<T const&>( lhs ), T( rhs ), pred);
0068 else if constexpr (!lhs_is_tensor && rhs_is_tensor)
0069 return compare(T( lhs ), static_cast<T const&>( rhs ), pred);
0070 else
0071 return compare(T( lhs ), T( rhs ), pred);
0072
0073 }
0074
0075 template<class T, class D, class UnaryPred>
0076 bool compare(tensor_expression<T,D> const& expr, UnaryPred pred)
0077 {
0078 if constexpr (std::is_same<T,D>::value)
0079 return compare(static_cast<T const&>( expr ), pred);
0080 else
0081 return compare(T( expr ), pred);
0082 }
0083
0084 }
0085
0086
0087 template<class T, class L, class R>
0088 bool operator==( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
0089 boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0090 return boost::numeric::ublas::detail::compare( lhs, rhs, std::equal_to<>{} );
0091 }
0092 template<class T, class L, class R>
0093 auto operator!=(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
0094 boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0095 return boost::numeric::ublas::detail::compare( lhs, rhs, std::not_equal_to<>{} );
0096 }
0097 template<class T, class L, class R>
0098 auto operator< ( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
0099 boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0100 return boost::numeric::ublas::detail::compare( lhs, rhs, std::less<>{} );
0101 }
0102 template<class T, class L, class R>
0103 auto operator<=( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
0104 boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0105 return boost::numeric::ublas::detail::compare( lhs, rhs, std::less_equal<>{} );
0106 }
0107 template<class T, class L, class R>
0108 auto operator> ( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
0109 boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0110 return boost::numeric::ublas::detail::compare( lhs, rhs, std::greater<>{} );
0111 }
0112 template<class T, class L, class R>
0113 auto operator>=( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs,
0114 boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0115 return boost::numeric::ublas::detail::compare( lhs, rhs, std::greater_equal<>{} );
0116 }
0117
0118
0119
0120
0121
0122 template<class T, class D>
0123 bool operator==( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
0124 return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs == r; } );
0125 }
0126 template<class T, class D>
0127 auto operator!=( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
0128 return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs != r; } );
0129 }
0130 template<class T, class D>
0131 auto operator< ( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
0132 return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs < r; } );
0133 }
0134 template<class T, class D>
0135 auto operator<=( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
0136 return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs <= r; } );
0137 }
0138 template<class T, class D>
0139 auto operator> ( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
0140 return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs > r; } );
0141 }
0142 template<class T, class D>
0143 auto operator>=( typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,D> const& rhs) {
0144 return boost::numeric::ublas::detail::compare( rhs, [lhs](auto const& r){ return lhs >= r; } );
0145 }
0146
0147
0148
0149 template<class T, class D>
0150 bool operator==( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
0151 return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l == rhs; } );
0152 }
0153 template<class T, class D>
0154 auto operator!=( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
0155 return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l != rhs; } );
0156 }
0157 template<class T, class D>
0158 auto operator< ( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
0159 return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l < rhs; } );
0160 }
0161 template<class T, class D>
0162 auto operator<=( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
0163 return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l <= rhs; } );
0164 }
0165 template<class T, class D>
0166 auto operator> ( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
0167 return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l > rhs; } );
0168 }
0169 template<class T, class D>
0170 auto operator>=( boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs, typename T::const_reference rhs) {
0171 return boost::numeric::ublas::detail::compare( lhs, [rhs](auto const& l){ return l >= rhs; } );
0172 }
0173
0174
0175 #endif