/******************************************************************************* * * 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,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