mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-10-30 16:30:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			296 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			296 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /***************************************************************************
 | |
|  * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht          *
 | |
|  * Copyright (c) QuantStack                                                 *
 | |
|  *                                                                          *
 | |
|  * Distributed under the terms of the BSD 3-Clause License.                 *
 | |
|  *                                                                          *
 | |
|  * The full license is in the file LICENSE, distributed with this software. *
 | |
|  ****************************************************************************/
 | |
| 
 | |
| #ifndef XTENSOR_CHUNKED_VIEW_HPP
 | |
| #define XTENSOR_CHUNKED_VIEW_HPP
 | |
| 
 | |
| #include <xtl/xsequence.hpp>
 | |
| 
 | |
| #include "xchunked_array.hpp"
 | |
| #include "xnoalias.hpp"
 | |
| #include "xstorage.hpp"
 | |
| #include "xstrided_view.hpp"
 | |
| 
 | |
| namespace xt
 | |
| {
 | |
| 
 | |
|     template <class E>
 | |
|     struct is_chunked_t : detail::chunk_helper<E>::is_chunked
 | |
|     {
 | |
|     };
 | |
| 
 | |
|     /*****************
 | |
|      * xchunked_view *
 | |
|      *****************/
 | |
| 
 | |
|     template <class E>
 | |
|     class xchunk_iterator;
 | |
| 
 | |
|     template <class E>
 | |
|     class xchunked_view
 | |
|     {
 | |
|     public:
 | |
| 
 | |
|         using self_type = xchunked_view<E>;
 | |
|         using expression_type = std::decay_t<E>;
 | |
|         using value_type = typename expression_type::value_type;
 | |
|         using reference = typename expression_type::reference;
 | |
|         using const_reference = typename expression_type::const_reference;
 | |
|         using pointer = typename expression_type::pointer;
 | |
|         using const_pointer = typename expression_type::const_pointer;
 | |
|         using size_type = typename expression_type::size_type;
 | |
|         using difference_type = typename expression_type::difference_type;
 | |
|         using shape_type = svector<size_type>;
 | |
|         using chunk_iterator = xchunk_iterator<self_type>;
 | |
|         using const_chunk_iterator = xchunk_iterator<const self_type>;
 | |
| 
 | |
|         template <class OE, class S>
 | |
|         xchunked_view(OE&& e, S&& chunk_shape);
 | |
| 
 | |
|         template <class OE>
 | |
|         xchunked_view(OE&& e);
 | |
| 
 | |
|         void init();
 | |
| 
 | |
|         template <class OE>
 | |
|         typename std::enable_if_t<!is_chunked_t<OE>::value, xchunked_view<E>&> operator=(const OE& e);
 | |
| 
 | |
|         template <class OE>
 | |
|         typename std::enable_if_t<is_chunked_t<OE>::value, xchunked_view<E>&> operator=(const OE& e);
 | |
| 
 | |
|         size_type dimension() const noexcept;
 | |
|         const shape_type& shape() const noexcept;
 | |
|         const shape_type& chunk_shape() const noexcept;
 | |
|         size_type grid_size() const noexcept;
 | |
|         const shape_type& grid_shape() const noexcept;
 | |
| 
 | |
|         expression_type& expression() noexcept;
 | |
|         const expression_type& expression() const noexcept;
 | |
| 
 | |
|         chunk_iterator chunk_begin();
 | |
|         chunk_iterator chunk_end();
 | |
| 
 | |
|         const_chunk_iterator chunk_begin() const;
 | |
|         const_chunk_iterator chunk_end() const;
 | |
|         const_chunk_iterator chunk_cbegin() const;
 | |
|         const_chunk_iterator chunk_cend() const;
 | |
| 
 | |
|     private:
 | |
| 
 | |
|         E m_expression;
 | |
|         shape_type m_shape;
 | |
|         shape_type m_chunk_shape;
 | |
|         shape_type m_grid_shape;
 | |
|         size_type m_chunk_nb;
 | |
|     };
 | |
| 
 | |
|     template <class E, class S>
 | |
|     xchunked_view<E> as_chunked(E&& e, S&& chunk_shape);
 | |
| 
 | |
|     /********************************
 | |
|      * xchunked_view implementation *
 | |
|      ********************************/
 | |
| 
 | |
|     template <class E>
 | |
|     template <class OE, class S>
 | |
|     inline xchunked_view<E>::xchunked_view(OE&& e, S&& chunk_shape)
 | |
|         : m_expression(std::forward<OE>(e))
 | |
|         , m_chunk_shape(xtl::forward_sequence<shape_type, S>(chunk_shape))
 | |
|     {
 | |
|         m_shape.resize(e.dimension());
 | |
|         const auto& s = e.shape();
 | |
|         std::copy(s.cbegin(), s.cend(), m_shape.begin());
 | |
|         init();
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     template <class OE>
 | |
|     inline xchunked_view<E>::xchunked_view(OE&& e)
 | |
|         : m_expression(std::forward<OE>(e))
 | |
|     {
 | |
|         m_shape.resize(e.dimension());
 | |
|         const auto& s = e.shape();
 | |
|         std::copy(s.cbegin(), s.cend(), m_shape.begin());
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     void xchunked_view<E>::init()
 | |
|     {
 | |
|         // compute chunk number in each dimension
 | |
|         m_grid_shape.resize(m_shape.size());
 | |
|         std::transform(
 | |
|             m_shape.cbegin(),
 | |
|             m_shape.cend(),
 | |
|             m_chunk_shape.cbegin(),
 | |
|             m_grid_shape.begin(),
 | |
|             [](auto s, auto cs)
 | |
|             {
 | |
|                 std::size_t cn = s / cs;
 | |
|                 if (s % cs > 0)
 | |
|                 {
 | |
|                     cn++;  // edge_chunk
 | |
|                 }
 | |
|                 return cn;
 | |
|             }
 | |
|         );
 | |
|         m_chunk_nb = std::accumulate(
 | |
|             std::begin(m_grid_shape),
 | |
|             std::end(m_grid_shape),
 | |
|             std::size_t(1),
 | |
|             std::multiplies<>()
 | |
|         );
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     template <class OE>
 | |
|     typename std::enable_if_t<!is_chunked_t<OE>::value, xchunked_view<E>&>
 | |
|     xchunked_view<E>::operator=(const OE& e)
 | |
|     {
 | |
|         auto end = chunk_end();
 | |
|         for (auto it = chunk_begin(); it != end; ++it)
 | |
|         {
 | |
|             auto el = *it;
 | |
|             noalias(el) = strided_view(e, it.get_slice_vector());
 | |
|         }
 | |
|         return *this;
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     template <class OE>
 | |
|     typename std::enable_if_t<is_chunked_t<OE>::value, xchunked_view<E>&>
 | |
|     xchunked_view<E>::operator=(const OE& e)
 | |
|     {
 | |
|         m_chunk_shape.resize(e.dimension());
 | |
|         const auto& cs = e.chunk_shape();
 | |
|         std::copy(cs.cbegin(), cs.cend(), m_chunk_shape.begin());
 | |
|         init();
 | |
|         auto it2 = e.chunks().begin();
 | |
|         auto end1 = chunk_end();
 | |
|         for (auto it1 = chunk_begin(); it1 != end1; ++it1, ++it2)
 | |
|         {
 | |
|             auto el1 = *it1;
 | |
|             auto el2 = *it2;
 | |
|             auto lhs_shape = el1.shape();
 | |
|             if (lhs_shape != el2.shape())
 | |
|             {
 | |
|                 xstrided_slice_vector esv(el2.dimension());  // element slice in edge chunk
 | |
|                 std::transform(
 | |
|                     lhs_shape.begin(),
 | |
|                     lhs_shape.end(),
 | |
|                     esv.begin(),
 | |
|                     [](auto size)
 | |
|                     {
 | |
|                         return range(0, size);
 | |
|                     }
 | |
|                 );
 | |
|                 noalias(el1) = strided_view(el2, esv);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 noalias(el1) = el2;
 | |
|             }
 | |
|         }
 | |
|         return *this;
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::dimension() const noexcept -> size_type
 | |
|     {
 | |
|         return m_shape.size();
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::shape() const noexcept -> const shape_type&
 | |
|     {
 | |
|         return m_shape;
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::chunk_shape() const noexcept -> const shape_type&
 | |
|     {
 | |
|         return m_chunk_shape;
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::grid_size() const noexcept -> size_type
 | |
|     {
 | |
|         return m_chunk_nb;
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::grid_shape() const noexcept -> const shape_type&
 | |
|     {
 | |
|         return m_grid_shape;
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::expression() noexcept -> expression_type&
 | |
|     {
 | |
|         return m_expression;
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::expression() const noexcept -> const expression_type&
 | |
|     {
 | |
|         return m_expression;
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::chunk_begin() -> chunk_iterator
 | |
|     {
 | |
|         shape_type chunk_index(m_shape.size(), size_type(0));
 | |
|         return chunk_iterator(*this, std::move(chunk_index), 0u);
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::chunk_end() -> chunk_iterator
 | |
|     {
 | |
|         return chunk_iterator(*this, shape_type(grid_shape()), grid_size());
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::chunk_begin() const -> const_chunk_iterator
 | |
|     {
 | |
|         shape_type chunk_index(m_shape.size(), size_type(0));
 | |
|         return const_chunk_iterator(*this, std::move(chunk_index), 0u);
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::chunk_end() const -> const_chunk_iterator
 | |
|     {
 | |
|         return const_chunk_iterator(*this, shape_type(grid_shape()), grid_size());
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::chunk_cbegin() const -> const_chunk_iterator
 | |
|     {
 | |
|         return chunk_begin();
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline auto xchunked_view<E>::chunk_cend() const -> const_chunk_iterator
 | |
|     {
 | |
|         return chunk_end();
 | |
|     }
 | |
| 
 | |
|     template <class E, class S>
 | |
|     inline xchunked_view<E> as_chunked(E&& e, S&& chunk_shape)
 | |
|     {
 | |
|         return xchunked_view<E>(std::forward<E>(e), std::forward<S>(chunk_shape));
 | |
|     }
 | |
| 
 | |
|     template <class E>
 | |
|     inline xchunked_view<E> as_chunked(E&& e)
 | |
|     {
 | |
|         return xchunked_view<E>(std::forward<E>(e));
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif
 |