File indexing completed on 2025-01-18 09:43:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_UBLAS_TENSOR_STRIDES_HPP
0015 #define BOOST_UBLAS_TENSOR_STRIDES_HPP
0016
0017 #include <vector>
0018 #include <limits>
0019 #include <numeric>
0020 #include <stdexcept>
0021 #include <initializer_list>
0022 #include <algorithm>
0023 #include <cassert>
0024
0025 #include <boost/numeric/ublas/functional.hpp>
0026
0027 namespace boost {
0028 namespace numeric {
0029 namespace ublas {
0030
0031 using first_order = column_major;
0032 using last_order = row_major;
0033
0034 template<class T>
0035 class basic_extents;
0036
0037
0038
0039
0040
0041
0042
0043 template<class __int_type, class __layout>
0044 class basic_strides
0045 {
0046 public:
0047
0048 using base_type = std::vector<__int_type>;
0049
0050 static_assert( std::numeric_limits<typename base_type::value_type>::is_integer,
0051 "Static error in boost::numeric::ublas::basic_strides: type must be of type integer.");
0052 static_assert(!std::numeric_limits<typename base_type::value_type>::is_signed,
0053 "Static error in boost::numeric::ublas::basic_strides: type must be of type unsigned integer.");
0054 static_assert(std::is_same<__layout,first_order>::value || std::is_same<__layout,last_order>::value,
0055 "Static error in boost::numeric::ublas::basic_strides: layout type must either first or last order");
0056
0057
0058 using layout_type = __layout;
0059 using value_type = typename base_type::value_type;
0060 using reference = typename base_type::reference;
0061 using const_reference = typename base_type::const_reference;
0062 using size_type = typename base_type::size_type;
0063 using const_pointer = typename base_type::const_pointer;
0064 using const_iterator = typename base_type::const_iterator;
0065
0066
0067
0068
0069
0070
0071 constexpr explicit basic_strides()
0072 : _base{}
0073 {
0074 }
0075
0076
0077
0078
0079
0080
0081 template <class T>
0082 basic_strides(basic_extents<T> const& s)
0083 : _base(s.size(),1)
0084 {
0085 if(s.empty())
0086 return;
0087
0088 if(!s.valid())
0089 throw std::runtime_error("Error in boost::numeric::ublas::basic_strides() : shape is not valid.");
0090
0091 if(s.is_vector() || s.is_scalar())
0092 return;
0093
0094 if(this->size() < 2)
0095 throw std::runtime_error("Error in boost::numeric::ublas::basic_strides() : size of strides must be greater or equal 2.");
0096
0097
0098 if constexpr (std::is_same<layout_type,first_order>::value){
0099 size_type k = 1ul, kend = this->size();
0100 for(; k < kend; ++k)
0101 _base[k] = _base[k-1] * s[k-1];
0102 }
0103 else {
0104 size_type k = this->size()-2, kend = 0ul;
0105 for(; k > kend; --k)
0106 _base[k] = _base[k+1] * s[k+1];
0107 _base[0] = _base[1] * s[1];
0108 }
0109 }
0110
0111 basic_strides(basic_strides const& l)
0112 : _base(l._base)
0113 {}
0114
0115 basic_strides(basic_strides && l )
0116 : _base(std::move(l._base))
0117 {}
0118
0119 basic_strides(base_type const& l )
0120 : _base(l)
0121 {}
0122
0123 basic_strides(base_type && l )
0124 : _base(std::move(l))
0125 {}
0126
0127 ~basic_strides() = default;
0128
0129
0130 basic_strides& operator=(basic_strides other)
0131 {
0132 swap (*this, other);
0133 return *this;
0134 }
0135
0136 friend void swap(basic_strides& lhs, basic_strides& rhs) {
0137 std::swap(lhs._base , rhs._base);
0138 }
0139
0140 const_reference operator[] (size_type p) const{
0141 return _base[p];
0142 }
0143
0144 const_pointer data() const{
0145 return _base.data();
0146 }
0147
0148 const_reference at (size_type p) const{
0149 return _base.at(p);
0150 }
0151
0152
0153 bool empty() const{
0154 return _base.empty();
0155 }
0156
0157 size_type size() const{
0158 return _base.size();
0159 }
0160
0161 template<class other_layout>
0162 bool operator == (basic_strides<value_type, other_layout> const& b) const{
0163 return b.base() == this->base();
0164 }
0165
0166 template<class other_layout>
0167 bool operator != (basic_strides<value_type, other_layout> const& b) const{
0168 return b.base() != this->base();
0169 }
0170
0171 bool operator == (basic_strides const& b) const{
0172 return b._base == _base;
0173 }
0174
0175 bool operator != (basic_strides const& b) const{
0176 return b._base != _base;
0177 }
0178
0179 const_iterator begin() const{
0180 return _base.begin();
0181 }
0182
0183 const_iterator end() const{
0184 return _base.end();
0185 }
0186
0187 void clear() {
0188 this->_base.clear();
0189 }
0190
0191 base_type const& base() const{
0192 return this->_base;
0193 }
0194
0195
0196 protected:
0197 base_type _base;
0198 };
0199
0200 template<class layout_type>
0201 using strides = basic_strides<std::size_t, layout_type>;
0202
0203 namespace detail {
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214 BOOST_UBLAS_INLINE
0215 template<class size_type, class layout_type>
0216 auto access(std::vector<size_type> const& i, basic_strides<size_type,layout_type> const& w)
0217 {
0218 const auto p = i.size();
0219 size_type sum = 0u;
0220 for(auto r = 0u; r < p; ++r)
0221 sum += i[r]*w[r];
0222 return sum;
0223 }
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 BOOST_UBLAS_INLINE
0235 template<std::size_t r, class layout_type, class ... size_types>
0236 auto access(std::size_t sum, basic_strides<std::size_t, layout_type> const& w, std::size_t i, size_types ... is)
0237 {
0238 sum+=i*w[r];
0239 if constexpr (sizeof...(is) == 0)
0240 return sum;
0241 else
0242 return detail::access<r+1>(sum,w,std::forward<size_types>(is)...);
0243 }
0244
0245 }
0246
0247 }
0248 }
0249 }
0250
0251 #endif