#ifndef CONTRACTION_SINGLE_H #define CONTRACTION_SINGLE_H #include "Fastor/tensor/Tensor.h" #include "Fastor/tensor_algebra/indicial.h" namespace Fastor { template struct extractor_contract_1 {}; template struct extractor_contract_1> { template static typename contraction_impl, Tensor, typename std_ext::make_index_sequence::type>::type FASTOR_INLINE contract_impl(const Tensor &a) { constexpr bool _is_reduction = is_single_reduction_v,Tensor>; using OutTensor = typename contraction_impl, Tensor, typename std_ext::make_index_sequence::type>::type; using OutIndices = typename contraction_impl, Tensor, typename std_ext::make_index_sequence::type>::indices; OutTensor out; out.zeros(); const T *a_data = a.data(); T *out_data = out.data(); constexpr int a_dim = sizeof...(Rest0); constexpr int out_dim = no_of_unique::value; constexpr auto& idx_a = IndexTensors< Index, Tensor, Index,Tensor, typename std_ext::make_index_sequence::type>::indices; constexpr auto& idx_out = IndexTensors< Index, Tensor, OutIndices,OutTensor, typename std_ext::make_index_sequence::type>::indices; using nloops = loop_setter< Index, Tensor, typename std_ext::make_index_sequence::type>; constexpr auto& maxes_out = nloops::dims; constexpr int total = nloops::value; constexpr std::array products_a = nprods,typename std_ext::make_index_sequence::type>::values; int as[out_dim] = {}; constexpr int stride = 1; FASTOR_IF_CONSTEXPR (!_is_reduction) { using Index_with_dims = typename put_dims_in_Index::type; constexpr std::array products_out = \ nprods::type>::values; int it, jt, counter = 0; while(counter < total) { int index_a = as[idx_a[a_dim-1]]; for(it = 0; it< a_dim; it++) { index_a += products_a[it]*as[idx_a[it]]; } int index_out = as[idx_out[OutTensor::Dimension-1]]; for(it = 0; it< static_cast(OutTensor::Dimension); it++) { index_out += products_out[it]*as[idx_out[it]]; } out_data[index_out] += a_data[index_a]; for(jt = out_dim-1 ; jt>=0 ; jt--) { if(++as[jt]=0 ; jt--) { if(++as[jt] auto contraction(const Tensor &a) -> decltype(extractor_contract_1::contract_impl(a)) { return extractor_contract_1::contract_impl(a); } } // end of namespace Fastor #endif // CONTRACTION_SINGLE_H