/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2013 by O. Parcollet * * TRIQS is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * TRIQS. If not, see . * ******************************************************************************/ #ifndef TRIQS_ARRAYS_INDEXMAP_CUBOID_GROUP_INDICES_H #define TRIQS_ARRAYS_INDEXMAP_CUBOID_GROUP_INDICES_H #include namespace triqs { namespace arrays { // a variadic push_back into a vector. template void vector_push_back_v(V & v){} template void vector_push_back_v(V & v, T0 && t0, T && ... t){ v.push_back(std::forward(t0)); vector_push_back_v(v,t...);} // a list of compile time int... template struct m_index{}; template struct m_index {static constexpr int head = I0; }; template std::vector m_index_to_vector( m_index) { std::vector v; vector_push_back_v(v,Is...); return v;} // a trait to get the min, max of a m_index template struct get_min_max; template struct get_min_max> { typedef get_min_max> r; static constexpr int min = (I0 < r::min ? I0 : r::min); static constexpr int max = (I0 > r::max ? I0 : r::max); }; template struct get_min_max> { static constexpr int min = I0; static constexpr int max = I0; }; // given a m_index of indices, a metafunction to map to their position into memory template struct index_group_to_mem_pos_list; template struct index_group_to_mem_pos_list> { typedef m_index < indexmaps::mem_layout::index_to_memory_rank(ML,Is)...> type; static_assert( get_min_max::max - get_min_max::min + 1 == sizeof...(Is), "Indices not contiguous in memory"); }; #ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS // count the number of Is strictly smaller than C constexpr int count_pos(int C){ return 0;} template constexpr int count_pos(int C, int i, T... t){ return (i struct count_pos_list { typedef m_index< count_pos(Is, Is...)...> type; }; #else template struct count_pos; template struct count_pos> : std::integral_constant>::value + (I0 {}; template struct count_pos> : std::integral_constant{}; template struct count_pos_list { typedef m_index tmp; typedef m_index< count_pos::value...> type; }; #endif // a simple foreach template void for_each (Callee & C, T0 const & t0, T const & ... t ) { C(t0); for_each(C, t...);} template void for_each (Callee & C){} // make a permutation out of a m_index template struct to_permu; template struct to_permu> { static constexpr ull_t value = permutations::permutation(Is...);}; // the main class template struct group_indices_impl { static constexpr int new_dim = sizeof...(MIndex); typedef typename count_pos_list< index_group_to_mem_pos_list::type::head ...>::type new_memory_pos; static constexpr ull_t traversal_layout = to_permu::value; typedef array_view type; static type invoke(A const & a) { if (a.indexmap().memory_indices_layout_ull() != a.indexmap().traversal_order) TRIQS_RUNTIME_ERROR << "Grouping indices is only possible for arrays when the memory_layout is the same as the traversal order \n" << "But here your memory_layout is "<< a.indexmap().memory_indices_layout() << " while the traversal order is "<< a.indexmap().traversal_order_indices_layout(); std::vector< std::vector > Indices; vector_push_back_v(Indices, m_index_to_vector(MIndex())...); mini_vector l; mini_vector s; for (size_t u=0; u typename group_indices_impl::type group_indices(A const & a, MIndex... ) { return group_indices_impl::invoke(a);} }}//namespace triqs::arrays #endif