/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-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_DOMAIN_H
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_DOMAIN_H
#include "../common.hpp"
#include "../range.hpp"
#include "./mem_layout.hpp"
#include
#include "../../impl/exceptions.hpp"
#include
#include
#include
#include
#include
#include
namespace triqs { namespace arrays { namespace indexmaps { namespace cuboid {
using namespace triqs::arrays::permutations;
/// Standard hyper_rectangular domain for arrays
template
class domain_t {
typedef mini_vector n_uple;
n_uple lengths_;
friend class boost::serialization::access;
template void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::make_nvp("dimensions",lengths_);}
public :
//static const unsigned int rank = Rank;
static constexpr unsigned int rank = Rank;
typedef n_uple index_value_type;
domain_t ():lengths_(){}
domain_t (n_uple const & lengths):lengths_(lengths) {}
domain_t (n_uple && lengths):lengths_(std::move(lengths)) {}
domain_t (mini_vector const & lengths):lengths_(lengths) {}
domain_t (std::vector const & l):lengths_() {
if (!(l.size()==rank)) TRIQS_RUNTIME_ERROR << "cuboid domain_t construction : vector size incorrect : got "<lengths_ == X.lengths_;}
bool operator!=(domain_t const & X) const { return !(this->lengths_ == X.lengths_);}
n_uple const & lengths() const { return lengths_;}
/** Generates the value of the indices of a cuboid_domain. */
static constexpr ull_t iteration_order_default = permutations::identity(Rank);
template
class gal_generator {
typedef index_value_type indices_type;
const domain_t * dom;
indices_type indices_tuple;
bool atend;
public:
gal_generator (const domain_t & P, bool atEnd=false): dom(&P), atend(atEnd) {}
bool operator==(const gal_generator & IT2) const { assert((IT2.dom == dom)); return ((IT2.atend==atend) );}
bool operator!=(const gal_generator & IT2) const { return (!operator==(IT2));}
indices_type const & operator *() const { return indices_tuple;}
operator bool () const { return !atend;}
gal_generator & operator++(){ assert(!atend); atend = advance_impl(std::integral_constant()); return *this;}
private:
template bool advance_impl(std::integral_constant) {
constexpr int p = permutations::apply(IterationOrder, r);
if (indices_tuple[p] < dom->lengths()[p]-1) { ++(indices_tuple[p]); return false;}
indices_tuple[p] = 0;
return advance_impl(std::integral_constant());
}
bool advance_impl(std::integral_constant) { return true;}
};
typedef gal_generator<> generator;
generator begin() const { return generator(*this,false);}
generator end() const { return generator(*this,true);}
/* End of generator */
// Check that key in in the domain
template void assert_key_in_domain(KeyType const & key) const {
std::stringstream fs;
bool res = key_check_impl(std::integral_constant(), key,this->lengths_,fs);
if (!res) TRIQS_ARRAYS_KEY_ERROR << " key out of domain \n" <
bool key_check_impl (std::integral_constant, KeyType const & key, n_uple const & L, std::stringstream & fs ) const {
//bool cond = ( ( size_t(key[r]) < L[r]));
bool cond = ( ( size_t(std::get(key)) < L[r]));
//if (!cond) fs << "key ["<(key) <<" is not within [0,"<(), key,L,fs) && cond;
}
template bool key_check_impl (std::integral_constant, KeyType const &, n_uple const &, std::stringstream &) const { return true;}
// Check that key in in the domain : variadic form. No need for speed optimisation here, it is just for debug
template void assert_key_in_domain_v (Args const & ... args) const { assert_key_in_domain( std::make_tuple(args...));}
friend std::ostream & operator<<(std::ostream & out, domain_t const & x){return out<<"Cuboid of rank "< struct foreach_impl;
/// Call the function F for each element of the domain, traversed in the TraversalOrder
template
void foreach(domain_t const & d, FntType F) { foreach_impl::invoke (d,F); }
// ------------------------- implementation of foreach -----------------------------------------------------
typedef std::ptrdiff_t foreach_int_type;
// better to be signed here : 1) on some machine/compiler, it is a lot faster !
// When used with clef auto assign, e.g. A(i_,j_) = i -2*j, one needs signed arithmetics
// The clef adapters would convert, but this requires a conversion at each call....
//typedef size_t foreach_int_type;
#define AUX0(z,P,NNN) constexpr int p##P = mem_layout::memory_rank_to_index(TraversalOrder,NNN-P);
#define AUX1(z,P,unused) for (t[p##P]=0; t[p##P]< l[p##P]; ++t[p##P])
//#define AUX1(z,P,unused) for (foreach_int_type x##P=0; x##P< dom.lengths()[p##P]; ++x##P)
#define AUX3(z,p,unused) BOOST_PP_COMMA_IF(p) t[p]
#define IMPL(z, RR, unused) \
template struct foreach_impl {\
static void invoke ( domain_t const & dom, FntType F) { \
BOOST_PP_REPEAT(RR,AUX0,BOOST_PP_DEC(RR))\
mini_vector t;\
const mini_vector l(dom.lengths());\
BOOST_PP_REPEAT(RR,AUX1,nil){\
F(BOOST_PP_REPEAT(RR,AUX3,nil));\
} }};
BOOST_PP_REPEAT_FROM_TO(1,ARRAY_NRANK_MAX , IMPL, nil);
#undef IMPL
#undef AUX0
#undef AUX1
#undef AUX3
}
/// ------------ Pretty Printing : specializing the default behaviour for d=1,2 -------------------------
namespace PrettyPrint_details {
template
struct print_impl {
std::ostream & out; A const & a;
print_impl( std::ostream & out_, A const & a_) : out(out_), a(a_){}
template void operator()(A0 const & a0, Args const & ... args) const { out << a(a0,args...)<< " ";}
void print() const { out<<"[";
indexmaps::cuboid::foreach (a.domain(), std::cref(*this)); //foreach(a, std::cref(*this));
out<<"]"; }
};
template
struct print_impl <1,A> {
std::ostream & out; A const & a;
print_impl( std::ostream & out_, A const & a_) : out(out_), a(a_){}
void print() const {
auto d = a.indexmap().domain();
out<<"["; for (size_t i=0; i< d.lengths()[0]; ++i) out<<(i>0 ? ",": "")<
struct print_impl <2,A> {
std::ostream & out; A const & a;
print_impl( std::ostream & out_, A const & a_) : out(out_), a(a_){}
void print() const {
auto d = a.indexmap().domain();
out<<"\n[";
for (size_t i=0; i< d.lengths()[0]; ++i) {
out<<(i==0 ? "[" : " [");
for (size_t j=0; j< d.lengths()[1]; ++j) out<<(j>0 ? ",": "")<
void pretty_print (std::ostream & out, A const & a ) { PrettyPrint_details::print_impl(out,a).print();}
}}}
#endif