Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:03

0001 //
0002 //  Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
0003 //
0004 //  Distributed under the Boost Software License, Version 1.0. (See
0005 //  accompanying file LICENSE_1_0.txt or copy at
0006 //  http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 //  The authors gratefully acknowledge the support of
0009 //  Fraunhofer IOSB, Ettlingen, Germany
0010 //
0011 
0012 #ifndef BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_HPP
0013 #define BOOST_UBLAS_TENSOR_OPERATORS_ARITHMETIC_HPP
0014 
0015 #include "expression.hpp"
0016 #include "expression_evaluation.hpp"
0017 #include "multi_index_utility.hpp"
0018 #include "functions.hpp"
0019 
0020 #include <type_traits>
0021 #include <functional>
0022 #include <algorithm>
0023 
0024 namespace boost{
0025 namespace numeric{
0026 namespace ublas {
0027 
0028 
0029 template<class element_type, class storage_format, class storage_type>
0030 class tensor;
0031 
0032 template<class E>
0033 class matrix_expression;
0034 
0035 
0036 template<class E>
0037 class vector_expression;
0038 
0039 }
0040 }
0041 }
0042 
0043 #define FIRST_ORDER_OPERATOR_RIGHT(OP, EXPR_TYPE_L, EXPR_TYPE_R) \
0044 template<class T, class L, class R> \
0045 auto operator OP ( boost::numeric::ublas:: EXPR_TYPE_L <T,L> const& lhs, boost::numeric::ublas:: EXPR_TYPE_R <R> const& rhs) { \
0046     return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), \
0047       [](auto const& l, auto const& r){ return l OP r; }); \
0048 } \
0049 
0050 FIRST_ORDER_OPERATOR_RIGHT (*, detail:: tensor_expression , vector_expression)
0051 FIRST_ORDER_OPERATOR_RIGHT (+, detail:: tensor_expression , vector_expression)
0052 FIRST_ORDER_OPERATOR_RIGHT (-, detail:: tensor_expression , vector_expression)
0053 FIRST_ORDER_OPERATOR_RIGHT (/, detail:: tensor_expression , vector_expression)
0054 
0055 FIRST_ORDER_OPERATOR_RIGHT (*, detail:: tensor_expression , matrix_expression)
0056 FIRST_ORDER_OPERATOR_RIGHT (+, detail:: tensor_expression , matrix_expression)
0057 FIRST_ORDER_OPERATOR_RIGHT (-, detail:: tensor_expression , matrix_expression)
0058 FIRST_ORDER_OPERATOR_RIGHT (/, detail:: tensor_expression , matrix_expression)
0059 
0060 
0061 #define FIRST_ORDER_OPERATOR_LEFT(OP, EXPR_TYPE_L, EXPR_TYPE_R) \
0062 template<class T, class L, class R> \
0063 auto operator OP ( boost::numeric::ublas:: EXPR_TYPE_L <L> const& lhs, boost::numeric::ublas:: EXPR_TYPE_R <T,R> const& rhs) { \
0064     return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), \
0065       [](auto const& l, auto const& r){ return l OP r; }); \
0066 } \
0067 
0068 FIRST_ORDER_OPERATOR_LEFT (*, vector_expression, detail:: tensor_expression)
0069 FIRST_ORDER_OPERATOR_LEFT (+, vector_expression, detail:: tensor_expression)
0070 FIRST_ORDER_OPERATOR_LEFT (-, vector_expression, detail:: tensor_expression)
0071 FIRST_ORDER_OPERATOR_LEFT (/, vector_expression, detail:: tensor_expression)
0072 
0073 FIRST_ORDER_OPERATOR_LEFT (*, matrix_expression, detail:: tensor_expression)
0074 FIRST_ORDER_OPERATOR_LEFT (+, matrix_expression, detail:: tensor_expression)
0075 FIRST_ORDER_OPERATOR_LEFT (-, matrix_expression, detail:: tensor_expression)
0076 FIRST_ORDER_OPERATOR_LEFT (/, matrix_expression, detail:: tensor_expression)
0077 
0078 
0079 
0080 
0081 template<class T, class L, class R>
0082 auto operator+( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0083     return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l + r; });
0084 }
0085 template<class T, class L, class R>
0086 auto operator-( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0087     return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l - r; });
0088 //  return boost::numeric::ublas::detail::make_lambda<T>([&lhs,&rhs](std::size_t i){ return lhs(i) - rhs(i);});
0089 }
0090 template<class T, class L, class R>
0091 auto operator*( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0092     return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l * r; });
0093 }
0094 template<class T, class L, class R>
0095 auto operator/( boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0096     return boost::numeric::ublas::detail::make_binary_tensor_expression<T> (lhs(), rhs(), [](auto const& l, auto const& r){ return l / r; });
0097 }
0098 
0099 
0100 // Overloaded Arithmetic Operators with Scalars
0101 template<class T, class R>
0102 auto operator+(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0103     return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs + r; });
0104     //return boost::numeric::ublas::detail::make_lambda<T>( [&lhs,&rhs](std::size_t i) {return lhs + rhs(i); } );
0105 }
0106 template<class T, class R>
0107 auto operator-(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0108     return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs - r; });
0109 }
0110 template<class T, class R>
0111 auto operator*(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0112     return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs * r; });
0113 }
0114 template<class T, class R>
0115 auto operator/(typename T::const_reference lhs, boost::numeric::ublas::detail::tensor_expression<T,R> const& rhs) {
0116     return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (rhs(), [lhs](auto const& r){ return lhs / r; });
0117 }
0118 
0119 
0120 template<class T, class L>
0121 auto operator+(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) {
0122     return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l + rhs; } );
0123 }
0124 template<class T, class L>
0125 auto operator-(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) {
0126     return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l - rhs; } );
0127 }
0128 template<class T, class L>
0129 auto operator*(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) {
0130     return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l * rhs; } );
0131 }
0132 template<class T, class L>
0133 auto operator/(boost::numeric::ublas::detail::tensor_expression<T,L> const& lhs, typename T::const_reference rhs) {
0134     return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [rhs] (auto const& l) { return l / rhs; } );
0135 }
0136 
0137 
0138 
0139 template<class T, class D>
0140 auto& operator += (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) {
0141     boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l+=r; } );
0142     return lhs;
0143 }
0144 
0145 template<class T, class D>
0146 auto& operator -= (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) {
0147     boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l-=r; } );
0148     return lhs;
0149 }
0150 
0151 template<class T, class D>
0152 auto& operator *= (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) {
0153     boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l*=r; } );
0154     return lhs;
0155 }
0156 
0157 template<class T, class D>
0158 auto& operator /= (T& lhs, const boost::numeric::ublas::detail::tensor_expression<T,D> &expr) {
0159     boost::numeric::ublas::detail::eval(lhs, expr(), [](auto& l, auto const& r) { l/=r; } );
0160     return lhs;
0161 }
0162 
0163 
0164 
0165 
0166 template<class E, class F, class A>
0167 auto& operator += (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) {
0168     boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l+=r; } );
0169     return lhs;
0170 }
0171 
0172 template<class E, class F, class A>
0173 auto& operator -= (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) {
0174     boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l-=r; } );
0175     return lhs;
0176 }
0177 
0178 template<class E, class F, class A>
0179 auto& operator *= (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) {
0180     boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l*=r; } );
0181     return lhs;
0182 }
0183 
0184 template<class E, class F, class A>
0185 auto& operator /= (boost::numeric::ublas::tensor<E,F,A>& lhs, typename boost::numeric::ublas::tensor<E,F,A>::const_reference r) {
0186     boost::numeric::ublas::detail::eval(lhs, [r](auto& l) { l/=r; } );
0187     return lhs;
0188 }
0189 
0190 
0191 
0192 
0193 
0194 
0195 template<class T, class D>
0196 auto const& operator +(const boost::numeric::ublas::detail::tensor_expression<T,D>& lhs) {
0197     return lhs;
0198 }
0199 
0200 template<class T, class D>
0201 auto operator -(boost::numeric::ublas::detail::tensor_expression<T,D> const& lhs) {
0202     return boost::numeric::ublas::detail::make_unary_tensor_expression<T> (lhs(), [] (auto const& l) { return -l; } );
0203 }
0204 
0205 
0206 
0207 
0208 
0209 /** @brief Performs a tensor contraction, not an elementwise multiplication
0210     *
0211 */
0212 
0213 template<class tensor_type_left, class tuple_type_left, class tensor_type_right, class tuple_type_right>
0214 auto operator*(
0215         std::pair< tensor_type_left  const&, tuple_type_left  > lhs,
0216         std::pair< tensor_type_right const&, tuple_type_right > rhs)
0217 {
0218 
0219     using namespace boost::numeric::ublas;
0220 
0221     auto const& tensor_left  = lhs.first;
0222     auto const& tensor_right = rhs.first;
0223 
0224     auto multi_index_left = lhs.second;
0225     auto multi_index_right = rhs.second;
0226 
0227     static constexpr auto num_equal_ind = number_equal_indexes<tuple_type_left, tuple_type_right>::value;
0228 
0229     if constexpr ( num_equal_ind == 0  ){
0230         return tensor_left * tensor_right;
0231     }
0232     else if constexpr ( num_equal_ind==std::tuple_size<tuple_type_left>::value && std::is_same<tuple_type_left, tuple_type_right>::value ){
0233 
0234         return boost::numeric::ublas::inner_prod( tensor_left, tensor_right );
0235     }
0236     else {
0237         auto array_index_pairs = index_position_pairs(multi_index_left,multi_index_right);
0238         auto index_pairs = array_to_vector(  array_index_pairs  );
0239         return boost::numeric::ublas::prod( tensor_left, tensor_right, index_pairs.first, index_pairs.second );
0240     }
0241 
0242 }
0243 
0244 #endif