/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011-2014 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 .
*
******************************************************************************/
#pragma once
#include "../common.hpp"
#include "../range.hpp"
#include "./mem_layout.hpp"
#include "../permutation.hpp"
#include
#include "../../impl/exceptions.hpp"
#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 {
using n_uple = mini_vector;
n_uple lengths_;
friend class boost::serialization::access;
template void serialize(Archive &ar, const unsigned int version) {
ar &TRIQS_MAKE_NVP("dimensions", lengths_);
}
public:
static constexpr unsigned int rank = Rank;
using index_value_type = n_uple;
domain_t() = default;
domain_t(const domain_t &C) = default;
domain_t(domain_t &&C) = default;
domain_t &operator=(domain_t const &) = default;
domain_t &operator=(domain_t &&x) = default;
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 " << l.size() << " while expected "
<< Rank;
lengths_ = n_uple(l);
}
template 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); }
n_uple const &lengths() const &{ return lengths_; }
n_uple lengths() && { 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 {
using indices_type = index_value_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; }
};
using generator = gal_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" << fs.str();
}
template
bool key_check_impl(std::integral_constant, KeyType const &key, n_uple const &L, std::stringstream &fs) const {
bool cond = ((size_t(std::get(key)) < L[r]));
if (!cond) fs << "key [" << r << "] = " << std::get(key) << " is not within [0," << L[r] << "[\n";
return key_check_impl(std::integral_constant(), 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 " << x.rank << " and dimensions " << x.lengths();
}
};
}
}
template indexmaps::cuboid::domain_t make_cuboid_domain(U... u) {
return {size_t(u)...};
}
using matrix_shape_t = indexmaps::cuboid::domain_t<2>;
using vector_shape_t = indexmaps::cuboid::domain_t<1>;
}
}