SuperDex Physics C++ API
Loading...
Searching...
No Matches
span.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
22
23#if MOCHI_USE_EXTERN_TEMPLATE
24#include <mochi_core/utils/nd_array.h> // For extern template declarations
25#endif // MOCHI_USE_EXTERN_TEMPLATE
26
27#include <cstddef>
28#include <iterator>
29#include <string>
30#include <type_traits>
31#include <vector>
32
33namespace superdex {
34
35/**************************************************************************************************
36 Span<T>
37
38 Wraps a pointer and length. If type T is a const type, then span provides a read-only view into
39 the range of elements. The span does not own the memory nor guarantee its lifespan. To help
40 reduce register pressure, the type used to encode the span length is also templatized.
41*/
42template <typename T, typename SizeT = size_t>
43class Span {
44 public:
45 using value_type = T;
46 using size_type = SizeT;
47 static_assert(std::is_integral_v<SizeT>, "SizeT should be a signed or unsigned integral type");
48
49 MOCHI_ANY MOCHI_FORCE_INLINE constexpr Span() = default;
50
51 // Construct from pointer + size
52 MOCHI_ANY MOCHI_FORCE_INLINE constexpr Span(T* ptr, SizeT len) : _ptr(ptr), _len(len) {}
53
54 // Unfortunately, overload resolution would be ambiguous if someone wrote "Span{ptr, 0}" because 0
55 // could convert to SizeT or to T* (sigh). This template wrapper avoids that ambiguity.
56 template <typename U>
57 struct NotIntegral {
58 NotIntegral(SizeT) = delete;
59 NotIntegral(U u) : value(u) {}
61 };
62
63 // Construct from the half open range [begin, end)
65 : _ptr(begin), _len(static_cast<SizeT>(end.value - begin)) {}
66
67 // Construct from any container whose data pointer is implicitly convertible to T* (e.g.,
68 // std::vector<int> -> Span<int const>, Span<int> -> Span<int const>). The SFINAE constraint
69 // excludes Span with the same template arguments to avoid hijacking the implicit copy/move
70 // constructors.
71 template <class ContainerT, MOCHI_CONCEPT((!std::is_same_v<std::decay_t<ContainerT>, Span>))>
72 MOCHI_ANY MOCHI_FORCE_INLINE constexpr Span(ContainerT&& container)
73 : _ptr(std::data(container)), _len(static_cast<SizeT>(std::size(container))) {}
74
75 // Index operator. May return a const reference if type T is const.
76 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr T& operator[](SizeT index) const {
77 MOCHI_ASSERT_VERBOSE(index >= 0 && index < _len, "Index out-of-range");
78 return _ptr[index];
79 }
80
81 // Bool operator to mimic non-null pointer semantics. Same empty() == false.
82 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE explicit constexpr operator bool() const noexcept {
83 return !empty();
84 }
85
86 // Spans are equal if all elements are equal
87 template <typename T2, typename S2>
88 [[nodiscard]] MOCHI_ANY bool operator==(Span<T2, S2> const& rhs) const {
89 if (static_cast<size_type>(rhs.size()) != _len) {
90 return false;
91 }
92 for (size_type i = 0; i < _len; ++i) {
93 if (rhs[i] != _ptr[i]) {
94 return false;
95 }
96 }
97 return true;
98 }
99
100 template <typename T2, typename S2>
101 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE bool operator!=(Span<T2, S2> const& rhs) const {
102 return !(*this == rhs);
103 }
104
105 // These member names are lower case in keeping with the std library conventions.
106 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr SizeT size() const {
107 return _len;
108 }
109 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr bool empty() const {
110 return _len == 0;
111 }
112 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr T* begin() const {
113 return _ptr;
114 }
115 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr T* end() const {
116 return _ptr + _len;
117 }
118 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr T* data() const {
119 return _ptr;
120 }
121 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr Span subspan(SizeT start, SizeT len) const {
122 MOCHI_ASSERT_VERBOSE(start + len <= _len, "Subspan out-of-range");
123 return Span(_ptr + start, len);
124 }
125 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr Span subspan(SizeT start) const {
126 MOCHI_ASSERT_VERBOSE(start <= _len, "Start index out-of-range");
127 return Span(_ptr + start, _len - start);
128 }
129 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr T& front() const {
130 return (*this)[0];
131 }
132 [[nodiscard]] MOCHI_ANY MOCHI_FORCE_INLINE constexpr T& back() const {
133 return (*this)[_len - 1];
134 }
135
136 protected:
137 T* _ptr = nullptr;
138 SizeT _len = 0;
139};
140
141// Convert a std::vectors or c-style array to a Spans. The template argument can be deduced
142template <typename ContainerT>
143[[nodiscard]] MOCHI_FORCE_INLINE auto MakeSpan(ContainerT& container);
144
145/**************************************************************************************************
146 Span Inlines
147*/
148
149template <typename ContainerT>
150[[nodiscard]] MOCHI_FORCE_INLINE auto MakeSpan(ContainerT& container) {
151 auto* ptr = std::data(container);
152 size_t len = std::size(container);
153 return Span<std::remove_reference_t<decltype(*ptr)>>{ptr, len};
154}
155
156template <typename T, size_t N>
157[[nodiscard]] MOCHI_FORCE_INLINE auto MakeSpan(T (&arr)[N]) {
158 return Span<T>{arr, N};
159}
160
161template <typename T, typename S>
162[[nodiscard]] MOCHI_FORCE_INLINE Span<T, S> const& MakeSpan(Span<T, S> const& alreadyASpan) {
163 return alreadyASpan;
164}
165
166template <typename ContainerT>
167[[nodiscard]] MOCHI_FORCE_INLINE auto MakeConstSpan(ContainerT const& container) {
168 auto* ptr = std::data(container);
169 size_t len = std::size(container);
170 return Span<std::add_const_t<std::remove_reference_t<decltype(*ptr)>>>{ptr, len};
171}
172
173template <typename T, size_t N>
174[[nodiscard]] MOCHI_FORCE_INLINE auto MakeConstSpan(T (&arr)[N]) {
175 return Span<T const>{arr, N};
176}
177
178template <typename T, typename S>
180 return alreadyASpan;
181}
182
183template <typename T>
185 return {&obj, 1};
186}
187
188template <typename T>
190 return {&obj, 1};
191}
192
193#if MOCHI_USE_EXTERN_TEMPLATE
194extern template class Span<int>;
195extern template class Span<NdArray<int, 2>>;
196extern template class Span<NdArray<int, 3>>;
197extern template class Span<NdArray<int, 4>>;
198extern template class Span<real>;
199extern template class Span<NdArray<real, 3>>;
200extern template class Span<int, int>;
201extern template class Span<NdArray<int, 2>, int>;
202extern template class Span<NdArray<int, 3>, int>;
203extern template class Span<NdArray<int, 4>, int>;
204extern template class Span<real, int>;
205extern template class Span<NdArray<real, 3>, int>;
206#endif // MOCHI_USE_EXTERN_TEMPLATE
207
208// ScalarType specialization: recursively unwrap value type.
209namespace details {
210template <class T, class SizeT>
211struct ScalarTypeDef<Span<T, SizeT>, void> {
212 using type = ScalarType<T>;
213};
214} // namespace details
215
216} // namespace superdex
constexpr Span(ContainerT &&container)
Definition span.h:72
bool operator==(Span< T2, S2 > const &rhs) const
Definition span.h:88
SizeT size_type
Definition span.h:46
constexpr T * end() const
Definition span.h:115
bool operator!=(Span< T2, S2 > const &rhs) const
Definition span.h:101
constexpr Span()=default
constexpr Span(T *begin, NotIntegral< T * > end)
Definition span.h:64
constexpr T & front() const
Definition span.h:129
constexpr Span subspan(SizeT start, SizeT len) const
Definition span.h:121
constexpr SizeT size() const
Definition span.h:106
constexpr T & back() const
Definition span.h:132
constexpr bool empty() const
Definition span.h:109
constexpr Span subspan(SizeT start) const
Definition span.h:125
SizeT _len
Definition span.h:138
constexpr Span(T *ptr, SizeT len)
Definition span.h:52
constexpr T * begin() const
Definition span.h:112
constexpr T & operator[](SizeT index) const
Definition span.h:76
constexpr T * data() const
Definition span.h:118
#define MOCHI_ASSERT_VERBOSE(condition_without_side_effects,...)
Definition debug.h:102
#define MOCHI_FORCE_INLINE
#define MOCHI_ANY
auto MakeConstSpan(ContainerT const &container)
Definition span.h:167
Span< T const, size_t > MakeSingletonConstSpan(T const &obj)
Definition span.h:189
Span< T, size_t > MakeSingletonSpan(T &obj)
Definition span.h:184
auto MakeSpan(ContainerT &container)
Definition span.h:150