19namespace uni20::detail
22template <std::
integral Extent> [[nodiscard]]
constexpr bool tensor_extent_is_valid(Extent extent)
noexcept
24 if constexpr (std::signed_integral<Extent>)
25 if (extent < 0)
return false;
26 return std::in_range<index_type>(extent);
29template <std::integral... Extents> [[nodiscard]]
auto make_tensor_extents(Extents... extents)
31 ERROR_IF(!(tensor_extent_is_valid(extents) && ...),
32 "tensor extents must be nonnegative and representable by uni20::index_type");
33 using extents_type = stdex::dextents<
index_type,
sizeof...(Extents)>;
34 return extents_type{
static_cast<index_type>(extents)...};
37template <
class Extents> [[nodiscard]] std::size_t checked_element_count(Extents
const& extents)
39 bool has_zero_extent =
false;
40 for (std::size_t axis = 0; axis < Extents::rank(); ++axis)
42 auto const extent = extents.extent(axis);
43 ERROR_IF(!tensor_extent_is_valid(extent),
"tensor extents must be nonnegative and representable");
44 has_zero_extent = has_zero_extent || extent == 0;
46 if (has_zero_extent)
return 0;
48 std::size_t result = 1;
49 for (std::size_t axis = 0; axis < Extents::rank(); ++axis)
51 auto const value =
static_cast<std::size_t
>(extents.extent(axis));
52 ERROR_IF(result > std::numeric_limits<std::size_t>::max() /
value,
"tensor element count overflows size_t");
58template <std::
integral Extent> [[nodiscard]]
constexpr bool is_inferred_extent(Extent extent)
noexcept
60 if constexpr (std::signed_integral<Extent>)
return extent ==
static_cast<Extent
>(-1);
64template <std::integral... Extents>
65[[nodiscard]]
auto make_reshape_extents(std::size_t source_size, Extents... requested_extents)
67 constexpr std::size_t rank =
sizeof...(Extents);
68 std::array<index_type, rank>
values{};
69 std::array<bool, rank> inferred{};
71 auto record_extent = [&](
auto requested) {
72 bool const infer = is_inferred_extent(requested);
73 ERROR_IF(!infer && !tensor_extent_is_valid(requested),
74 "reshape extents must be nonnegative, except for one inferred -1 extent");
75 inferred[axis] = infer;
79 (record_extent(requested_extents), ...);
81 std::size_t inferred_axis = rank;
82 std::size_t known_size = 1;
83 for (axis = 0; axis < rank; ++axis)
87 ERROR_IF(inferred_axis != rank,
"reshape accepts at most one inferred extent");
91 auto const extent =
static_cast<std::size_t
>(
values[axis]);
97 ERROR_IF(known_size > std::numeric_limits<std::size_t>::max() / extent,
"reshape element count overflows size_t");
101 if (inferred_axis != rank)
103 ERROR_IF(known_size == 0,
"cannot infer a reshape extent when the specified extents have zero product");
104 ERROR_IF(source_size % known_size != 0,
"inferred reshape extent does not divide the source element count");
105 auto const inferred_value = source_size / known_size;
106 ERROR_IF(!std::in_range<index_type>(inferred_value),
"inferred reshape extent is not representable");
111 ERROR_IF(known_size != source_size,
"reshape source and destination element counts differ");
114 using extents_type = stdex::dextents<index_type, rank>;
115 return [&]<std::size_t... Axis>(std::index_sequence<Axis...>) {
116 return extents_type{
values[Axis]...};
117 }(std::make_index_sequence<rank>{});
120template <
class TargetExtents,
class SourceExtents>
121[[nodiscard]]
auto convert_reshape_extents(SourceExtents
const& source) -> TargetExtents
123 static_assert(TargetExtents::rank() == SourceExtents::rank());
124 for (std::size_t axis = 0; axis < TargetExtents::rank(); ++axis)
126 auto const fixed_extent = TargetExtents::static_extent(axis);
127 ERROR_IF(fixed_extent != stdex::dynamic_extent &&
static_cast<std::size_t
>(source.extent(axis)) != fixed_extent,
128 "reshape extent does not match the tensor's static extent");
131 using target_index =
typename TargetExtents::index_type;
132 return [&]<std::size_t... Axis>(std::index_sequence<Axis...>) {
133 return TargetExtents{
static_cast<target_index
>(source.extent(Axis))...};
134 }(std::make_index_sequence<TargetExtents::rank()>{});
locale_t value
Definition data_table.cpp:49
Configured gateway to Uni20's mdspan implementation.
auto values(Tensor &tensor)
Definition packed_matrix.hpp:29
std::ptrdiff_t index_type
Definition types.hpp:19
#define ERROR_IF(cond,...)
Definition trace.hpp:389