/* * 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; } }; public: NDRange& operator=(const NDRange& rhs)=default; NDRange(const NDRange& rhs) =default; template NDRange(T... ts) : m_sizes{ts...} { unsigned int t=1; for (unsigned int i=0; i& n) : m_sizes(n) { unsigned int t=1; for (unsigned int i=0; i 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 < m_positions.size()); return m_positions[d]; } void set_position(int_t d, int_t v) { assert(d < size(m_positions)); assert(v < ndrange_t::get_size(d)); m_positions[d] = v; } int_t get_position_end(int_t d) const { return get_position(d) + NDRange::get_size(d); } }; //class NDCoordinate /** @returns the number of dimensions in the NDRange which have none-1 values * IE there is actual work in these dimensions that can be broken up */ template std::size_t ndrange_popcount(const NDRange& ndr) { std::size_t count = 0; for(unsigned int d = 0; d != N; ++d) { if(ndr.get_size(d) != 1) ++count; } return count; } } // namespace arm_gemm