4#ifndef TETL_MDSPAN_EXTENTS_HPP
5#define TETL_MDSPAN_EXTENTS_HPP
7#include <etl/_algorithm/transform.hpp>
8#include <etl/_array/array.hpp>
9#include <etl/_cstddef/size_t.hpp>
10#include <etl/_limits/numeric_limits.hpp>
11#include <etl/_mdspan/is_extents.hpp>
12#include <etl/_span/dynamic_extent.hpp>
13#include <etl/_span/span.hpp>
14#include <etl/_type_traits/is_convertible.hpp>
15#include <etl/_type_traits/is_nothrow_convertible.hpp>
16#include <etl/_type_traits/make_unsigned.hpp>
17#include <etl/_utility/cmp_not_equal.hpp>
18#include <etl/_utility/index_sequence.hpp>
22template <
typename IndexType,
etl::size_t... Extents>
24 using index_type = IndexType;
25 using size_type = make_unsigned_t<IndexType>;
26 using rank_type =
etl::size_t;
29 static constexpr auto _rank =
sizeof...(Extents);
30 static constexpr auto _rank_dynamic = ((rank_type(Extents == dynamic_extent)) + ... + 0);
31 static constexpr auto _static_extents =
array<
etl::size_t,
sizeof...(Extents)>{Extents...};
33 [[
nodiscard]]
static constexpr auto _dynamic_index(rank_type i)
noexcept -> rank_type
35 return []<etl::size_t... Idxs>(
etl::size_t idx,
etl::index_sequence<Idxs...> ) {
37 return static_cast<rank_type>((((Idxs < idx) ? (Extents == dynamic_extent ? 1 : 0) : 0) + ... + 0));
41 [[
nodiscard]]
static constexpr auto _dynamic_index_inv(rank_type i)
noexcept -> rank_type
44 auto result = rank_type{};
45 for (rank_type r{0}; r <
rank(); ++r) {
46 if (_dynamic_index(r) == i) {
56 return sizeof...(Extents);
66 return _static_extents[i];
74 return _extents[
static_cast<
etl::size_t>(i)];
77 return static_cast<index_type>(ext);
79 return _extents[
static_cast<
etl::size_t>(_dynamic_index(i))];
86 template <
typename OtherIndexType,
etl::size_t... OtherExtents>
88 sizeof...(OtherExtents) ==
rank()
94 )
constexpr extents(
extents<OtherIndexType, OtherExtents...>
const& e)
noexcept
97 for (rank_type i{0}; i <
rank(); ++i) {
99 _extents[_dynamic_index(i)] =
static_cast<IndexType>(e.extent(i));
105 template <
typename... OtherIndexTypes>
107 (is_convertible_v<OtherIndexTypes, IndexType>
and ...)
108 and (is_nothrow_constructible_v<IndexType, OtherIndexTypes>
and ...)
111 explicit constexpr extents(OtherIndexTypes... es)
noexcept
112 :
extents{
array<IndexType,
sizeof...(OtherIndexTypes)>{
static_cast<IndexType>(es)...}}
116 template <
typename OtherIndexType,
etl::size_t N>
118 is_convertible_v<OtherIndexType
const&, IndexType>
119 and is_nothrow_constructible_v<IndexType, OtherIndexType
const&>
122 explicit(N != rank_dynamic())
constexpr extents(span<OtherIndexType, N> ext)
noexcept
125 transform(ext.begin(), ext.end(), _extents.begin(), [](
auto e) {
return static_cast<IndexType>(e); });
129 template <
typename OtherIndexType,
etl::size_t N>
131 is_convertible_v<OtherIndexType
const&, IndexType>
132 and is_nothrow_constructible_v<IndexType, OtherIndexType
const&>
135 explicit(N != rank_dynamic())
constexpr extents(
array<OtherIndexType, N>
const& e)
noexcept
140 template <
typename OtherIndexType,
etl::size_t... OtherExtents>
141 friend constexpr auto operator==(
extents const& lhs,
extents<OtherIndexType, OtherExtents...>
const& rhs)
noexcept
144 if constexpr (
rank() !=
extents<OtherIndexType, OtherExtents...>::rank()) {
147 for (
auto i = rank_type(0); i <
rank(); ++i) {
148 if (cmp_not_equal(lhs.extent(i), rhs.extent(i))) {
156 template <
typename OtherIndexType>
157 [[nodiscard]]
static constexpr auto index_cast(OtherIndexType&& i)
noexcept -> IndexType
159 return static_cast<IndexType>(i);
162 [[
nodiscard]]
constexpr auto fwd_prod_of_extents(rank_type i)
const noexcept -> size_t
164 if constexpr (
rank() == 0) {
167 auto result = size_t(1);
168 for (
auto e = rank_type(0); e < i; ++e) {
169 result *=
static_cast<size_t>(
extent(e
));
175 [[
nodiscard]]
constexpr auto rev_prod_of_extents(rank_type i)
const noexcept -> size_t
177 auto result = size_t(1);
178 for (
auto e = i + 1; e <
rank(); ++e) {
179 result *=
static_cast<size_t>(
extent(e
));
190template <
typename IndexType,
typename Integrals>
193template <
typename IndexType,
etl::size_t... Integrals>
194struct dextents_impl<IndexType,
etl::index_sequence<Integrals...>> {
200template <
typename... Integrals>
201 requires(
etl::is_convertible_v<Integrals,
etl::size_t>
and ...)
204template <
typename IndexType,
etl::size_t Rank>
205using dextents =
typename detail::dextents_impl<IndexType,
etl::make_index_sequence<Rank>>::type;
constexpr auto dynamic_extent
etl::dynamic_extent is a constant of type etl::size_t that is used to differentiate etl::span of stat...
Definition dynamic_extent.hpp:15
Definition adjacent_find.hpp:9
extents(Integrals...) -> extents< etl::size_t, etl::size_t((Integrals(), etl::dynamic_extent))... >
A container that encapsulates fixed size arrays.
Definition array.hpp:49
Definition extents.hpp:23
static constexpr auto rank() noexcept -> rank_type
Definition extents.hpp:54
static constexpr auto static_extent(rank_type i) noexcept -> etl::size_t
Definition extents.hpp:64
static constexpr auto rank_dynamic() noexcept -> rank_type
Definition extents.hpp:59
OtherExtents const &e noexcept
Definition extents.hpp:95
constexpr extents() noexcept=default
constexpr auto extent(rank_type i) const noexcept -> index_type
Definition extents.hpp:69