/*************************************************************************** * 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 #include "xchunked_array.hpp" #include "xnoalias.hpp" #include "xstorage.hpp" #include "xstrided_view.hpp" namespace xt { template struct is_chunked_t : detail::chunk_helper::is_chunked { }; /***************** * xchunked_view * *****************/ template class xchunk_iterator; template class xchunked_view { public: using self_type = xchunked_view; using expression_type = std::decay_t; 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; using chunk_iterator = xchunk_iterator; using const_chunk_iterator = xchunk_iterator; template xchunked_view(OE&& e, S&& chunk_shape); template xchunked_view(OE&& e); void init(); template typename std::enable_if_t::value, xchunked_view&> operator=(const OE& e); template typename std::enable_if_t::value, xchunked_view&> 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 xchunked_view as_chunked(E&& e, S&& chunk_shape); /******************************** * xchunked_view implementation * ********************************/ template template inline xchunked_view::xchunked_view(OE&& e, S&& chunk_shape) : m_expression(std::forward(e)) , m_chunk_shape(xtl::forward_sequence(chunk_shape)) { m_shape.resize(e.dimension()); const auto& s = e.shape(); std::copy(s.cbegin(), s.cend(), m_shape.begin()); init(); } template template inline xchunked_view::xchunked_view(OE&& e) : m_expression(std::forward(e)) { m_shape.resize(e.dimension()); const auto& s = e.shape(); std::copy(s.cbegin(), s.cend(), m_shape.begin()); } template void xchunked_view::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 template typename std::enable_if_t::value, xchunked_view&> xchunked_view::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 template typename std::enable_if_t::value, xchunked_view&> xchunked_view::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 inline auto xchunked_view::dimension() const noexcept -> size_type { return m_shape.size(); } template inline auto xchunked_view::shape() const noexcept -> const shape_type& { return m_shape; } template inline auto xchunked_view::chunk_shape() const noexcept -> const shape_type& { return m_chunk_shape; } template inline auto xchunked_view::grid_size() const noexcept -> size_type { return m_chunk_nb; } template inline auto xchunked_view::grid_shape() const noexcept -> const shape_type& { return m_grid_shape; } template inline auto xchunked_view::expression() noexcept -> expression_type& { return m_expression; } template inline auto xchunked_view::expression() const noexcept -> const expression_type& { return m_expression; } template inline auto xchunked_view::chunk_begin() -> chunk_iterator { shape_type chunk_index(m_shape.size(), size_type(0)); return chunk_iterator(*this, std::move(chunk_index), 0u); } template inline auto xchunked_view::chunk_end() -> chunk_iterator { return chunk_iterator(*this, shape_type(grid_shape()), grid_size()); } template inline auto xchunked_view::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 inline auto xchunked_view::chunk_end() const -> const_chunk_iterator { return const_chunk_iterator(*this, shape_type(grid_shape()), grid_size()); } template inline auto xchunked_view::chunk_cbegin() const -> const_chunk_iterator { return chunk_begin(); } template inline auto xchunked_view::chunk_cend() const -> const_chunk_iterator { return chunk_end(); } template inline xchunked_view as_chunked(E&& e, S&& chunk_shape) { return xchunked_view(std::forward(e), std::forward(chunk_shape)); } template inline xchunked_view as_chunked(E&& e) { return xchunked_view(std::forward(e)); } } #endif