| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- /***************************************************************************
- * 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
|