Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:03

0001 //
0002 //  Copyright (c) 2018-2019, Cem Bassoy, cem.bassoy@gmail.com
0003 //
0004 //  Distributed under the Boost Software License, Version 1.0. (See
0005 //  accompanying file LICENSE_1_0.txt or copy at
0006 //  http://www.boost.org/LICENSE_1_0.txt)
0007 //
0008 //  The authors gratefully acknowledge the support of
0009 //  Fraunhofer IOSB, Ettlingen, Germany
0010 //
0011 /// \file strides.hpp Definition for the basic_strides template class
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 /** @brief Template class for storing tensor strides for iteration with runtime variable size.
0039  *
0040  * Proxy template class of std::vector<int_type>.
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     /** @brief Default constructs basic_strides
0068      *
0069      * @code auto ex = basic_strides<unsigned>{};
0070      */
0071     constexpr explicit basic_strides()
0072         : _base{}
0073     {
0074     }
0075 
0076     /** @brief Constructs basic_strides from basic_extents for the first- and last-order storage formats
0077      *
0078      * @code auto strides = basic_strides<unsigned>( basic_extents<std::size_t>{2,3,4} );
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 /** @brief Returns relative memory index with respect to a multi-index
0207  *
0208  * @code auto j = access(std::vector{3,4,5}, strides{shape{4,2,3},first_order}); @endcode
0209  *
0210  * @param[in] i multi-index of length p
0211  * @param[in] w stride vector of length p
0212  * @returns relative memory location depending on \c i and \c w
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 /** @brief Returns relative memory index with respect to a multi-index
0226  *
0227  * @code auto j = access(0, strides{shape{4,2,3},first_order}, 2,3,4); @endcode
0228  *
0229  * @param[in] i   first element of the partial multi-index
0230  * @param[in] is  the following elements of the partial multi-index
0231  * @param[in] sum the current relative memory index
0232  * @returns relative memory location depending on \c i and \c w
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