/* * Copyright (c) 2019-2020 Arm Limited. * * SPDX-License-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #pragma once #include #include #include #include namespace arm_gemm { template class NDRange { private: std::array m_sizes{}; std::array m_totalsizes{}; class NDRangeIterator { private: const NDRange &m_parent; unsigned int m_pos = 0; unsigned int m_end = 0; public: NDRangeIterator(const NDRange &p, unsigned int s, unsigned int e) : m_parent(p), m_pos(s), m_end(e) { } bool done() const { return (m_pos >= m_end); } unsigned int dim(unsigned int d) const { unsigned int r = m_pos; if(d < (D - 1)) { r %= m_parent.m_totalsizes[d]; } if(d > 0) { r /= m_parent.m_totalsizes[d - 1]; } return r; } bool next_dim0() { m_pos++; return !done(); } bool next_dim1() { m_pos += m_parent.m_sizes[0] - dim(0); return !done(); } unsigned int dim0_max() const { unsigned int offset = std::min(m_end - m_pos, m_parent.m_sizes[0] - dim(0)); return dim(0) + offset; } }; void set_totalsizes() { unsigned int t = 1; for(unsigned int i = 0; i < D; i++) { if(m_sizes[i] == 0) { m_sizes[i] = 1; } t *= m_sizes[i]; m_totalsizes[i] = t; } } public: NDRange &operator=(const NDRange &rhs) = default; NDRange(const NDRange &rhs) = default; template NDRange(T... ts) : m_sizes{ ts... } { set_totalsizes(); } NDRange(const std::array &n) : m_sizes(n) { set_totalsizes(); } NDRangeIterator iterator(unsigned int start, unsigned int end) const { return NDRangeIterator(*this, start, end); } unsigned int total_size() const { return m_totalsizes[D - 1]; } unsigned int get_size(unsigned int v) const { return m_sizes[v]; } }; /** NDCoordinate builds upon a range, but specifies a starting position * in addition to a size which it inherits from NDRange */ template class NDCoordinate : public NDRange { using int_t = unsigned int; using ndrange_t = NDRange; std::array m_positions{}; public: NDCoordinate &operator=(const NDCoordinate &rhs) = default; NDCoordinate(const NDCoordinate &rhs) = default; NDCoordinate(const std::initializer_list> &list) { std::array sizes{}; std::size_t i = 0; for(auto &p : list) { m_positions[i] = p.first; sizes[i++] = p.second; } //update the parents sizes static_cast(*this) = ndrange_t(sizes); } int_t get_position(int_t d) const { assert(d < N); return m_positions[d]; } void set_position(int_t d, int_t v) { assert(d < N); m_positions[d] = v; } int_t get_position_end(int_t d) const { return get_position(d) + ndrange_t::get_size(d); } }; //class NDCoordinate using ndrange_t = NDRange<6>; using ndcoord_t = NDCoordinate<6>; } // namespace arm_gemm