/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 2012 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_MEMORY_LAYOUT_H #define TRIQS_ARRAYS_INDEXMAP_MEMORY_LAYOUT_H #include "../permutation.hpp" #include "../../impl/flags.hpp" namespace triqs { namespace arrays { namespace indexmaps { namespace mem_layout { /* The storage order is given by a permutation P stored in a ull_t (unsigned long long) as in permutations::.. * P[0] : the fastest index, * P[RANK-1] : the slowest index * Example : * 012 : Fortran, the first index is the fastest * 210: C the last index is the fastest * 120 : storage (i,j,k) is : index j is fastest, then k, then i * * index_to_memory_rank : i ---> r : to the index (0,1, ... etc), associates the rank in memory * e.g. r=0 : fastest index, r = RANK-1 : the slowest * memory_rank_to_index : the inverse mapping : r---> i : * 0-> the fastest index, etc.. * * All these computations can be done *at compile time* (constexpr) */ constexpr int memory_rank_to_index(ull_t p, int r) { return permutations::apply(p, r);} constexpr int index_to_memory_rank(ull_t p, int r) { return permutations::apply(permutations::inverse(p), r);} constexpr bool is_fortran (ull_t p){ return p == permutations::identity(permutations::size(p));} constexpr bool is_c (ull_t p){ return p == permutations::ridentity(permutations::size(p));} constexpr ull_t fortran_order (int n){ return permutations::identity(n);} constexpr ull_t c_order (int n){ return permutations::ridentity(n);} template struct fortran_order_tr { static constexpr ull_t value = permutations::identity(n);}; template struct c_order_tr { static constexpr ull_t value = permutations::ridentity(n);}; // From the flag in the template definition to the real traversal_order // 0 -> C order // 1 -> Fortran Order // Any other number interpreted as a permutation ? constexpr ull_t _get_traversal_order (int rank, ull_t fl, ull_t to) { return (flags::traversal_order_c(fl) ? c_order(rank) : (flags::traversal_order_fortran(fl) ? fortran_order(rank) : (to==0 ? c_order(rank) : to )));} template< int rank, ull_t fl, ull_t to> struct get_traversal_order { static constexpr ull_t value = _get_traversal_order (rank,fl,to); }; }} struct memory_layout_fortran {}; struct memory_layout_c {}; #define FORTRAN_LAYOUT (triqs::arrays::memory_layout_fortran()) #define C_LAYOUT (triqs::arrays::memory_layout_fortran()) // stores the layout == order of the indices in memory // wrapped into a little type to make constructor unambigous. template struct memory_layout { ull_t value; explicit memory_layout (ull_t v) : value(v) {assert((permutations::size(v)==Rank));} explicit memory_layout (char ml='C') { assert( (ml=='C') || (ml == 'F')); value = (ml=='F' ? indexmaps::mem_layout::fortran_order(Rank) : indexmaps::mem_layout::c_order(Rank)); } memory_layout (memory_layout_fortran) { value = indexmaps::mem_layout::fortran_order(Rank); } memory_layout (memory_layout_c) { value = indexmaps::mem_layout::c_order(Rank); } template explicit memory_layout(int i0, int i1, INT ... in) : value (permutations::permutation(i0,i1,in...)){ static_assert( sizeof...(in)==Rank-2, "Error"); } memory_layout (const memory_layout & C) = default; memory_layout (memory_layout && C) = default; memory_layout & operator =( memory_layout const &) = default; memory_layout & operator =( memory_layout && x) = default; bool operator ==( memory_layout const & ml) const { return value == ml.value;} bool operator !=( memory_layout const & ml) const { return value != ml.value;} friend std::ostream &operator<<(std::ostream &out, memory_layout const &s) { permutations::print(out, s.value); return out; } }; template memory_layout transpose(memory_layout ml, INT... is) { static_assert(sizeof...(INT)==R, "!"); return memory_layout{permutations::compose(ml.value, permutations::inverse(permutations::permutation(is...)))}; } }}//namespace triqs::arrays #endif