#ifndef RANGES_H #define RANGES_H #include "Fastor/config/config.h" #include "Fastor/meta/meta.h" #include namespace Fastor { // range detector for fseq //----------------------------------------------------------------------------------------------------------// template struct range_detector { static constexpr int range = last - first; static constexpr int value = range % step==0 ? range/step : range/step+1; }; namespace internal { template struct fseq_range_detector; template class Seq, int first, int last, int step> struct fseq_range_detector> { static constexpr int range = last - first; static constexpr int value = range % step==0 ? range/step : range/step+1; }; } // internal //----------------------------------------------------------------------------------------------------------// // Immediate sequence //----------------------------------------------------------------------------------------------------------// template struct iseq { static constexpr size_t _first = F; static constexpr size_t _last= L; static constexpr size_t _step = S; }; //----------------------------------------------------------------------------------------------------------// // Fixed sequence //----------------------------------------------------------------------------------------------------------// template struct fseq { static constexpr int _first = F; static constexpr int _last= L; static constexpr int _step = S; static constexpr int Size = range_detector::value; constexpr FASTOR_INLINE int size() const {return range_detector::value;} }; static constexpr fseq<0,-1,1> fall; template static constexpr fseq fix{}; static constexpr fseq<0 ,1 ,1> ffirst; static constexpr fseq<-1,-1,1> flast; //----------------------------------------------------------------------------------------------------------// // Dynamic sequence //----------------------------------------------------------------------------------------------------------// struct seq { int _first; int _last; int _step = 1; constexpr FASTOR_INLINE seq(int _f, int _l, int _s=1) : _first(_f), _last(_l), _step(_s) {} constexpr FASTOR_INLINE seq(int num) : _first(num), _last(num+1), _step(1) {} template constexpr FASTOR_INLINE seq(fseq) : _first(F), _last(L), _step(S) {} // Do not allow construction of seq using std::initializer_list, as it happens // implicitly. Overloading operator() with std::initializer_list should imply // TensorRandomView, not TensorView template constexpr FASTOR_INLINE seq(std::initializer_list _s1) = delete; // Do not provide this overload as it is meaningless [iseq stands for immediate evaluation] // template // constexpr FASTOR_INLINE seq(iseq) : _first(F), _last(L), _step(S) {} FASTOR_INLINE int size() const { int range = _last - _first; return range % _step==0 ? range/_step : range/_step+1; } constexpr FASTOR_INLINE bool operator==(seq other) const { return (_first==other._first && _last==other._last && _step==other._step) ? true : false; } constexpr FASTOR_INLINE bool operator!=(seq other) const { return (_first!=other._first || _last!=other._last || _step!=other._step) ? true : false; } }; static constexpr int first = 0; static constexpr int last = -1; // static constexpr seq all = seq(0,-1,1); // why not this? static constexpr fseq<0,-1,1> all; //----------------------------------------------------------------------------------------------------------// // traits //----------------------------------------------------------------------------------------------------------// template struct is_fixed_sequence { static constexpr bool value = false; }; template struct is_fixed_sequence> { static constexpr bool value = true; }; template struct is_fixed_sequence> { static constexpr bool value = true; }; template static constexpr bool is_fixed_sequence_v = is_fixed_sequence::value; template struct is_fixed_sequence_pack; template struct is_fixed_sequence_pack { static constexpr bool value = is_fixed_sequence::value && is_fixed_sequence_pack::value; }; template struct is_fixed_sequence_pack { static constexpr bool value = is_fixed_sequence::value; }; template static constexpr bool is_fixed_sequence_pack_v = is_fixed_sequence_pack::value; //----------------------------------------------------------------------------------------------------------// // Transform sequence with negative indices to positive indices; //----------------------------------------------------------------------------------------------------------// template struct to_positive; template struct to_positive,N> { // Same logic as seq used in the constructor of dynamic tensor views static constexpr int _first = (L==0 && F==-1) ? N-1 : ( L < 0 && F < 0 ? F + N + 1 : F); static constexpr int _last = (L < 0 && F >=0) ? L + N + 1 : ( (L==0 && F==-1) ? N : ( L < 0 && F < 0 ? L + N + 1 : L) ); using type = fseq<_first,_last,S>; }; template struct to_positive,N> { // Same logic as seq used in the constructor of dynamic tensor views static constexpr int _first = (L==0 && F==-1) ? N-1 : ( L < 0 && F < 0 ? F + N + 1 : F); static constexpr int _last = (L < 0 && F >=0) ? L + N + 1 : ( (L==0 && F==-1) ? N : ( L < 0 && F < 0 ? L + N + 1 : L) ); using type = iseq<_first,_last,S>; }; template using to_positive_t = typename to_positive::type; //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// template struct get_fixed_sequence_pack_dimensions; template class Derived, typename T, size_t ...Rest, size_t... ss, typename ... Fseqs> struct get_fixed_sequence_pack_dimensions, std_ext::index_sequence, Fseqs...>{ static constexpr std::array dims = { internal::fseq_range_detector>::value... }; // using type = Derived::value...>; using type = Derived>::value...>; static constexpr size_t Size = pack_prod::value; }; template class Derived, typename T, size_t ...Rest, size_t... ss, typename ... Fseqs> constexpr std::array get_fixed_sequence_pack_dimensions, std_ext::index_sequence, Fseqs...>::dims; //----------------------------------------------------------------------------------------------------------// //----------------------------------------------------------------------------------------------------------// template struct ravel_2d_indices; template struct ravel_2d_indices> { static constexpr size_t size_1 = range_detector::value; static constexpr std::array idx = {(S0*(ss/size_1)*Ncol + S1*(ss%size_1) + F0*Ncol + F1)...}; }; template constexpr std::array ravel_2d_indices>::idx; //----------------------------------------------------------------------------------------------------------// } #endif // RANGES_H