Stratax
Scientific computing containers and operations
Loading...
Searching...
No Matches
Strides.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Buffer.hpp"
4#include "Shape.hpp"
5#include "Exceptions.hpp"
6#include "Validation.hpp"
7
8#include <cstddef>
9#include <stdexcept>
10#include <utility>
11#include <ostream>
12
13namespace stratax::core {
14
23{
24private:
25 Buffer<std::size_t> buffer_;
26
27public:
31 Strides() noexcept = default;
32
43 explicit Strides(const Shape& shape)
44 : buffer_(shape.rank())
45 {
46 if (shape.empty()) {
47 return;
48 }
49
50 buffer_[shape.rank() - 1] = 1;
51
52 for (std::size_t i = shape.rank() - 1; i > 0; --i) {
53 buffer_[i - 1] = validation::checked_multiply(
54 buffer_[i],
55 shape(i),
56 "Strides overflow for shape");
57 }
58 }
59
60 Strides(const Strides&) = default;
61 Strides(Strides&&) noexcept = default;
62
63 Strides& operator=(const Strides&) = default;
64 Strides& operator=(Strides&&) noexcept = default;
65
69 ~Strides() = default;
70
76 [[nodiscard]] std::size_t size() const noexcept
77 {
78 return buffer_.size();
79 }
80
86 [[nodiscard]] bool empty() const noexcept
87 {
88 return buffer_.empty();
89 }
90
96 [[nodiscard]] std::size_t rank() const noexcept
97 {
98 return buffer_.size();
99 }
100
109 const std::size_t& operator()(std::size_t index) const
110 {
111 return buffer_[index];
112 }
113
123 const std::size_t& at(std::size_t index) const
124 {
125 validation::require_index(index, rank(), "Strides index out of bounds");
126 return buffer_[index];
127 }
128
134 const std::size_t& front() const
135 {
136 return buffer_.front();
137 }
138
144 const std::size_t& back() const
145 {
146 return buffer_.back();
147 }
148
154 [[nodiscard]] const std::size_t* data() const noexcept
155 {
156 return buffer_.data();
157 }
158
164 [[nodiscard]] const std::size_t* begin() noexcept
165 {
166 return buffer_.begin();
167 }
168
174 [[nodiscard]] const std::size_t* begin() const noexcept
175 {
176 return buffer_.begin();
177 }
178
184 [[nodiscard]] const std::size_t* cbegin() const noexcept
185 {
186 return buffer_.cbegin();
187 }
188
194 [[nodiscard]] const std::size_t* end() noexcept
195 {
196 return buffer_.end();
197 }
198
204 [[nodiscard]] const std::size_t* end() const noexcept
205 {
206 return buffer_.end();
207 }
208
214 [[nodiscard]] const std::size_t* cend() const noexcept
215 {
216 return buffer_.cend();
217 }
218
224 [[nodiscard]] std::reverse_iterator<const std::size_t*> rbegin() noexcept
225 {
226 return buffer_.rbegin();
227 }
228
234 [[nodiscard]] std::reverse_iterator<const std::size_t*> rbegin() const noexcept
235 {
236 return buffer_.rbegin();
237 }
238
244 [[nodiscard]] std::reverse_iterator<const std::size_t*> crbegin() const noexcept
245 {
246 return buffer_.crbegin();
247 }
248
254 [[nodiscard]] std::reverse_iterator<const std::size_t*> rend() noexcept
255 {
256 return buffer_.rend();
257 }
258
264 [[nodiscard]] std::reverse_iterator<const std::size_t*> rend() const noexcept
265 {
266 return buffer_.rend();
267 }
268
274 [[nodiscard]] std::reverse_iterator<const std::size_t*> crend() const noexcept
275 {
276 return buffer_.crend();
277 }
278
284 void swap(Strides& other) noexcept
285 {
286 buffer_.swap(other.buffer_);
287 }
288
296 [[nodiscard]] bool operator==(const Strides& other) const noexcept
297 {
298 if (rank() != other.rank()) {
299 return false;
300 }
301
302 for (std::size_t i = 0; i < rank(); ++i) {
303 if (buffer_[i] != other.buffer_[i]) {
304 return false;
305 }
306 }
307
308 return true;
309 }
310
318 [[nodiscard]] bool operator!=(const Strides& other) const noexcept
319 {
320 return !(*this == other);
321 }
322};
323
332inline std::ostream& operator<<(std::ostream& os, const Strides& stride)
333{
334 os << "(";
335
336 bool first = true;
337 for (std::size_t dim : stride)
338 {
339 if (!first)
340 os << ", ";
341
342 os << dim;
343 first = false;
344 }
345
346 if (stride.rank() == 1)
347 {
348 os << ",";
349 }
350
351 os << ")";
352
353 return os;
354}
355
356}
Shared runtime validation helpers.
Owns contiguous dynamically allocated storage.
Definition Buffer.hpp:38
Stores a list of dimension lengths for an array shape.
Definition Shape.hpp:20
Stores strides for a shape in contiguous memory.
Definition Strides.hpp:23
bool operator!=(const Strides &other) const noexcept
Returns whether two stride vectors differ.
Definition Strides.hpp:318
std::reverse_iterator< const std::size_t * > rbegin() const noexcept
Returns a const reverse iterator to the last stride value.
Definition Strides.hpp:234
bool operator==(const Strides &other) const noexcept
Compares two stride vectors for equality.
Definition Strides.hpp:296
const std::size_t & at(std::size_t index) const
Returns a stride value with bounds checking.
Definition Strides.hpp:123
Strides(const Strides &)=default
bool empty() const noexcept
Returns whether the stride vector is empty.
Definition Strides.hpp:86
std::reverse_iterator< const std::size_t * > rend() const noexcept
Returns a const reverse iterator before the first stride value.
Definition Strides.hpp:264
const std::size_t & operator()(std::size_t index) const
Returns a stride value without bounds checking.
Definition Strides.hpp:109
std::size_t rank() const noexcept
Returns the number of dimensions represented by the strides.
Definition Strides.hpp:96
std::reverse_iterator< const std::size_t * > rend() noexcept
Returns a reverse iterator before the first stride value.
Definition Strides.hpp:254
std::reverse_iterator< const std::size_t * > crend() const noexcept
Returns a const reverse iterator before the first stride value.
Definition Strides.hpp:274
const std::size_t * data() const noexcept
Returns the raw stride data pointer.
Definition Strides.hpp:154
std::reverse_iterator< const std::size_t * > rbegin() noexcept
Returns a reverse iterator to the last stride value.
Definition Strides.hpp:224
const std::size_t & back() const
Returns the last stride value.
Definition Strides.hpp:144
const std::size_t * end() noexcept
Returns an iterator one past the last stride value.
Definition Strides.hpp:194
const std::size_t * cend() const noexcept
Returns a const iterator one past the last stride value.
Definition Strides.hpp:214
const std::size_t * end() const noexcept
Returns a const iterator one past the last stride value.
Definition Strides.hpp:204
const std::size_t * cbegin() const noexcept
Returns a const iterator to the first stride value.
Definition Strides.hpp:184
const std::size_t * begin() noexcept
Returns an iterator to the first stride value.
Definition Strides.hpp:164
std::reverse_iterator< const std::size_t * > crbegin() const noexcept
Returns a const reverse iterator to the last stride value.
Definition Strides.hpp:244
std::size_t size() const noexcept
Returns the number of stored stride values.
Definition Strides.hpp:76
const std::size_t & front() const
Returns the first stride value.
Definition Strides.hpp:134
Strides(Strides &&) noexcept=default
void swap(Strides &other) noexcept
Swaps the stored strides with another instance.
Definition Strides.hpp:284
Strides() noexcept=default
Creates an empty stride vector.
const std::size_t * begin() const noexcept
Returns a const iterator to the first stride value.
Definition Strides.hpp:174
void require_index(std::size_t index, std::size_t size, const char *message)
Requires an index to be less than a size.
std::ostream & operator<<(std::ostream &os, const Shape &shape)
Writes a shape to a stream in tuple-like form.
Definition Shape.hpp:282