Stratax 0.4.0rc1
Loading...
Searching...
No Matches
Shape.hpp
Go to the documentation of this file.
1
4#pragma once
5
6#include <algorithm>
7#include <cstddef>
8#include <initializer_list>
9#include <ostream>
10#include <vector>
11#include <limits>
12
16
17namespace stratax::core {
18
35class Shape
36{
37private:
39
40public:
42 using value_type = std::size_t;
44 using size_type = std::size_t;
46 using difference_type = std::ptrdiff_t;
53
58 Shape() noexcept = default;
59
67 Shape(std::initializer_list<value_type> dims)
68 : dims_(dims)
69 {}
70
78 Shape(const std::vector<value_type>& dims)
79 : dims_(dims.size())
80 {
81 std::copy(dims.begin(), dims.end(), dims_.begin());
82 }
83
94 [[nodiscard]] size_type elements() const
95 {
96 if (empty() || std::find(dims_.begin(), dims_.end(), 0) != dims_.end())
97 {
98 return 0;
99 }
100 size_type prod = 1;
101 for (value_type dim : dims_)
102 {
103 if (dim == 0)
104 {
105 return 0;
106 }
107
108 if (prod > std::numeric_limits<size_type>::max() / dim)
109 {
110 throw Exceptions::DimensionError("Shape element count overflow.");
111 }
112
113 prod *= dim;
114 }
115
116 return prod;
117 }
118
124 [[nodiscard]] size_type rank() const noexcept
125 {
126 return dims_.size();
127 }
128
142 [[nodiscard]] Shape strides() const
143 {
144 if (empty())
145 {
146 return {};
147 }
148
149 std::vector<value_type> stride_values(rank());
150 stride_values[rank() - 1] = 1;
151
152 for (size_type i = rank() - 1; i > 0; --i)
153 {
154 if (dims_[i] != 0 &&
155 stride_values[i] > std::numeric_limits<value_type>::max() / dims_[i])
156 {
157 throw Exceptions::DimensionError("Shape stride overflow.");
158 }
159
160 stride_values[i - 1] = stride_values[i] * dims_[i];
161 }
162
163 return Shape(stride_values);
164 }
165
173 [[nodiscard]] const_reference operator[](size_type index) const noexcept
174 {
175 return dims_[index];
176 }
177
189 [[nodiscard]] const_reference at(difference_type index) const
190 {
191 return dims_[stratax::indexing::normalize_index(index, rank())];
192 }
193
199 [[nodiscard]] bool empty() const noexcept
200 {
201 return dims_.empty();
202 }
203
210 [[nodiscard]] bool operator==(const Shape& other) const noexcept
211 {
212 if (rank() != other.rank())
213 {
214 return false;
215 }
216 for (size_type i = 0; i < rank(); ++i)
217 {
218 if (dims_[i] != other.dims_[i])
219 {
220 return false;
221 }
222 }
223 return true;
224 }
225
227 const_iterator begin() const noexcept
228 {
229 return dims_.begin();
230 }
232 const_iterator end() const noexcept
233 {
234 return dims_.end();
235 }
237 const_iterator cbegin() const noexcept
238 {
239 return dims_.cbegin();
240 }
242 const_iterator cend() const noexcept
243 {
244 return dims_.cend();
245 }
248 {
249 return dims_.rbegin();
250 }
253 {
254 return dims_.crbegin();
255 }
258 {
259 return dims_.rend();
260 }
263 {
264 return dims_.crend();
265 }
266
272 void swap(Shape& other) noexcept
273 {
274 dims_.swap(other.dims_);
275 }
276
277};
278
290inline std::ostream& operator<<(std::ostream& os, const Shape& shape)
291{
292 os << "(";
293
294 bool first = true;
295 for (Shape::value_type dim : shape)
296 {
297 if (!first)
298 os << ", ";
299
300 os << dim;
301 first = false;
302 }
303
304 if (shape.rank() == 1)
305 {
306 os << ",";
307 }
308
309 os << ")";
310
311 return os;
312}
313
314}
Fixed-size aligned storage with element lifetime management.
Stratax exception types derived from std::runtime_error.
Checked signed index normalization.
std::ostream & operator<<(std::ostream &os, const Shape &shape)
Writes a shape using tuple notation.
Definition Shape.hpp:290
Invalid dimension or overflow in dimension, element-count, or stride arithmetic.
Fixed-size owner of aligned, contiguous element storage.
Definition Buffer.hpp:54
const_pointer const_iterator
Read-only contiguous random-access iterator type.
Definition Buffer.hpp:77
reverse_iterator rend() noexcept
Returns the past-the-end iterator for mutable reverse traversal.
Definition Buffer.hpp:474
void swap(Buffer &other) noexcept
Swaps storage and size with another buffer.
Definition Buffer.hpp:534
size_type size() const noexcept
Returns the number of stored elements.
Definition Buffer.hpp:497
const_reverse_iterator crend() const noexcept
Returns the past-the-end iterator for const reverse traversal.
Definition Buffer.hpp:486
const_iterator cend() const noexcept
Returns a const iterator one past the final element.
Definition Buffer.hpp:450
bool empty() const noexcept
Returns whether the buffer has no elements.
Definition Buffer.hpp:505
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the final element.
Definition Buffer.hpp:468
reverse_iterator rbegin() noexcept
Returns a mutable reverse iterator to the final element.
Definition Buffer.hpp:456
iterator begin() noexcept
Returns a mutable iterator to the first element.
Definition Buffer.hpp:420
const_iterator cbegin() const noexcept
Returns a const iterator to the first element.
Definition Buffer.hpp:432
std::reverse_iterator< const_iterator > const_reverse_iterator
Read-only iterator that traverses elements in reverse order.
Definition Buffer.hpp:81
iterator end() noexcept
Returns a mutable iterator one past the final element.
Definition Buffer.hpp:438
Stores the dimensions of a multidimensional array.
Definition Shape.hpp:36
Shape(const std::vector< value_type > &dims)
Constructs a shape by copying a vector of dimensions.
Definition Shape.hpp:78
size_type elements() const
Computes the total number of elements described by the shape.
Definition Shape.hpp:94
std::size_t size_type
Unsigned type used for ranks and dimension indices.
Definition Shape.hpp:44
size_type rank() const noexcept
Returns the number of dimensions.
Definition Shape.hpp:124
const_reference at(difference_type index) const
Returns a dimension using checked, Python-style indexing.
Definition Shape.hpp:189
const_iterator cend() const noexcept
Returns a const iterator past the final dimension.
Definition Shape.hpp:242
bool empty() const noexcept
Reports whether the shape has rank zero.
Definition Shape.hpp:199
const value_type & const_reference
Read-only reference to a dimension.
Definition Shape.hpp:48
bool operator==(const Shape &other) const noexcept
Compares two shapes dimension by dimension.
Definition Shape.hpp:210
void swap(Shape &other) noexcept
Exchanges dimension storage with another shape.
Definition Shape.hpp:272
const_reverse_iterator crbegin() const noexcept
Returns a const reverse iterator to the final dimension.
Definition Shape.hpp:252
const_iterator begin() const noexcept
Returns a const iterator to the first dimension.
Definition Shape.hpp:227
Shape strides() const
Computes canonical row-major strides for this shape.
Definition Shape.hpp:142
const_iterator end() const noexcept
Returns a const iterator past the final dimension.
Definition Shape.hpp:232
Shape() noexcept=default
Constructs an empty, rank-zero shape.
const_reference operator[](size_type index) const noexcept
Returns a dimension without bounds checking.
Definition Shape.hpp:173
Buffer< value_type >::const_reverse_iterator const_reverse_iterator
Read-only iterator over dimensions in reverse order.
Definition Shape.hpp:52
const_reverse_iterator crend() const noexcept
Returns the past-the-end const reverse iterator.
Definition Shape.hpp:262
std::size_t value_type
Type used to represent each dimension.
Definition Shape.hpp:42
const_iterator cbegin() const noexcept
Returns a const iterator to the first dimension.
Definition Shape.hpp:237
const_reverse_iterator rbegin() const noexcept
Returns a const reverse iterator to the final dimension.
Definition Shape.hpp:247
Buffer< value_type >::const_iterator const_iterator
Read-only contiguous iterator over dimensions.
Definition Shape.hpp:50
const_reverse_iterator rend() const noexcept
Returns the past-the-end reverse iterator.
Definition Shape.hpp:257
std::ptrdiff_t difference_type
Signed type used for checked indices and iterator distances.
Definition Shape.hpp:46