3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-27 06:43:40 +01:00
dft_tools/triqs/arrays/indexmaps/cuboid/mem_layout.hpp
Olivier Parcollet f2c7d449cc First commit : triqs libs version 1.0 alpha1
for earlier commits, see TRIQS0.x repository.
2013-07-17 19:24:07 +02:00

131 lines
6.2 KiB
C++

/*******************************************************************************
*
* 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 <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#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)
*/
#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS
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<int n> struct fortran_order_tr { static constexpr ull_t value = permutations::identity(n);};
template<int n> 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); };
#else
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);}
template<ull_t p, int r> struct index_to_memory_rank_tr { static constexpr ull_t value = 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<int n> struct fortran_order_tr { static constexpr ull_t value = permutations::identity(n);};
template<int n> struct c_order_tr { static constexpr ull_t value = permutations::ridentity(n);};
template< int rank, ull_t fl, ull_t to> struct get_traversal_order {
static constexpr ull_t value = (flags::traversal_order_c<fl>::value ? c_order_tr<rank>::value :
(flags::traversal_order_fortran<fl>::value ? fortran_order_tr<rank>::value : (to==0 ? c_order_tr<rank>::value : to )));
};
#endif
}}
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<int Rank>
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<typename ... INT>
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) { *this = std::move(C);}
friend void swap( memory_layout & a, memory_layout & b){ std::swap(a.value,b.value);}
memory_layout & operator =( memory_layout const &) = default;
memory_layout & operator =( memory_layout && x) { swap(*this,x); return *this;}
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<int Rank> void swap( memory_layout<Rank> & a, memory_layout<Rank> & b) { std::swap(a.value,b.value);}
}}//namespace triqs::arrays
#endif