/*******************************************************************************
*
* 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 constexpr unsigned int rank = Rank;
typedef n_uple index_value_type;
domain_t () =default;
domain_t (const domain_t & C) = default;
domain_t (domain_t && C) { *this = std::move(C);}
friend void swap( domain_t & a, domain_t & b) { swap(a.lengths_,b.lengths_);}
domain_t & operator =( domain_t const &) = default;
domain_t & operator =( domain_t && x) { swap(*this,x); return *this;}
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 "< domain_t(size_t i0, T... t): lengths_(i0, t...){}
size_t number_of_elements() const { return lengths_.product_of_elements();}
bool operator==(domain_t const & X) const { return this->lengths_ == X.lengths_;}
bool operator!=(domain_t const & X) const { return !(*this==X);}
#ifdef TRIQS_COMPILER_IS_C11_COMPLIANT
n_uple const & lengths() const & { return lengths_;}
n_uple lengths() && { return lengths_;}
#else
n_uple lengths() const { return lengths_;}
#endif
/** 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;}
explicit 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 "< void foreach(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();}
}
template
indexmaps::cuboid::domain_t make_cuboid_domain(U ... u) { return {u...};}
//cuboid_array_domain make_cuboid_domain(U ... u) { return {u...};}
typedef indexmaps::cuboid::domain_t<2> matrix_shape_t;
typedef indexmaps::cuboid::domain_t<1> vector_shape_t;
}}
#endif