/*******************************************************************************
*
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
*
* Copyright (C) 2011 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_SLICE_H
#define TRIQS_ARRAYS_INDEXMAP_CUBOID_SLICE_H
#include
#include "./slice_traversal_order.hpp"
namespace triqs { namespace arrays { namespace indexmaps {
namespace cuboid_details {
#define LISILOSO l_type const * li, s_type const * si, l_type * lo, s_type * so
typedef size_t l_type;
typedef std::ptrdiff_t s_type;
template inline void _check_BC ( int N, int ind, size_t B, int ind_min =0) { }
template <> inline void _check_BC (int N, int ind, size_t B, int ind_min) {
if (!((ind >= ind_min) && (ind < int(B)))) TRIQS_ARRAYS_KEY_ERROR << " index "<
static void one_step(LISILOSO, std::ptrdiff_t& offset, size_t R){
_check_BC (N, R, li[N]);
offset += R*si[N];
}
template
static void one_step(LISILOSO, std::ptrdiff_t& offset, range R){
_check_BC (N, R.first(),li[N]);
lo[P] = ((R.last()==-1 ? li[N] : R.last()) - R.first() + R.step()-1 )/R.step(); // python behaviour
_check_BC (N, R.first() + (lo[P]!=0 ? (lo[P]-1) : 0)*R.step() ,li[N], -1);
so[P] = si[N] * R.step();
offset += R.first() * si[N];
}
template
static typename std::enable_if<((EllipsisLength==1) || (!std::is_base_of::type::value)), void>::type
invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) {
constexpr bool dP = (std::is_base_of::type::value ? 1 : 0); // Arg0 is range or ellipsis
one_step(li,si,lo,so,offset, arg0);
invoke(li,si,lo,so, offset, args...);
}
template
static typename std::enable_if<((EllipsisLength==0) && std::is_base_of::type::value), void>::type
invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) {
invoke(li,si,lo,so, offset, args...);
}
template
static typename std::enable_if<((EllipsisLength>1) && std::is_base_of::type::value), void>::type
invoke(LISILOSO, s_type & offset, Arg0 const & arg0, Args const & ... args ) {
//constexpr int dP = 1;//(std::is_base_of::type::value ? 1 : 0); // Arg0 is range or ellipsis
one_step(li,si,lo,so,offset, arg0);
invoke(li,si,lo,so, offset, arg0, args...);
}
template static void invoke(LISILOSO, s_type & offset ) {}
};
#undef LISILOSO
}//namespace cuboid_details
// special case of no argument :
template struct slicer < cuboid::map > { typedef cuboid::map < R, Opt,To > r_type; };
// general case
template struct slicer < cuboid::map, Args...> {
static const unsigned int len = sizeof...(Args);
static constexpr bool has_ellipsis = (count_type_occurrence::value>0);
static_assert((count_type_occurrence::value < 2), "Only one ellipsis is permitted");
static_assert((len>=R || has_ellipsis), "Too few arguments in slice");
static_assert((len<=R+(has_ellipsis ?1:0)), "Too many arguments in slice"); // + one to allow an empty ellipsis
typedef cuboid::map im_t;
static constexpr int Rf = R - count_type_occurrence_not::value;
static constexpr ull_t To_i = im_t::traversal_order;
// compute a new traversal order, only if there is no ellipsis
// the computation with ellipsis is not yet implemented...
static constexpr ull_t Tof = (has_ellipsis ? 0 : cuboid::slicing_TO_order::sliced_memory_order::value);
typedef cuboid::map < Rf , Opt, Tof> r_type;
#ifndef TRIQS_WORKAROUND_INTEL_COMPILER_BUGS
static_assert(( (has_ellipsis) || (permutations::size(Tof) == Rf)), "Mismatch between Rank and the TraversalOrder");
#endif
static r_type invoke (im_t const & X, Args ... args) {
typename r_type::lengths_type newlengths;
typename r_type::strides_type newstrides;
std::ptrdiff_t newstart= X.start_shift();
constexpr int EllipsisLength = R -len+1;
cuboid_details::slice_calc::invoke<0,0,flags::bound_check_trait::value,EllipsisLength>(&X.lengths()[0],&X.strides()[0],&newlengths[0],&newstrides[0],newstart, args...);
return r_type(std::move(newlengths),std::move(newstrides),newstart);// use move construction ?
};
};
}}}//namespaces triqs::arrays::indexmaps
#endif