Stratax
Scientific computing containers and operations
Loading...
Searching...
No Matches
Tensor.hpp
Go to the documentation of this file.
1#pragma once
2
10
11#include <array>
12#include <cstddef>
13#include <initializer_list>
14#include <stdexcept>
15#include <utility>
16
17namespace stratax::container {
18
19template<typename T>
20requires Numeric<T>
29class Tensor
30{
31private:
32 core::Shape shape_;
33 core::Strides strides_;
34 core::Buffer<T> buffer_;
35
36public:
37 using value_type = T;
38
39 template<typename U>
41
48 Tensor() noexcept = default;
49
58 explicit Tensor(const core::Shape& shape)
59 : shape_(shape),
60 strides_(shape_),
61 buffer_(shape_.elements())
62 {
63 }
64
72 Tensor(const core::Shape& shape, const T& value)
73 : shape_(shape),
74 strides_(shape_),
75 buffer_(shape_.elements(), value)
76 {
77 }
78
83 Tensor(const Tensor&) = default;
84
89 Tensor(Tensor&&) noexcept = default;
90
95 Tensor& operator=(const Tensor&) = default;
96
101 Tensor& operator=(Tensor&&) noexcept = default;
102
107 ~Tensor() = default;
108
114 [[nodiscard]] std::size_t size() const noexcept
115 {
116 return buffer_.size();
117 }
118
124 [[nodiscard]] bool empty() const noexcept
125 {
126 return buffer_.empty();
127 }
128
134 [[nodiscard]] std::size_t rank() const noexcept
135 {
136 return shape_.rank();
137 }
138
144 const core::Shape& shape() const noexcept
145 {
146 return shape_;
147 }
148
154 const core::Strides& strides() const noexcept
155 {
156 return strides_;
157 }
158
167 T& operator()(std::size_t index) noexcept
168 {
169 return buffer_[index];
170 }
171
180 const T& operator()(std::size_t index) const noexcept
181 {
182 return buffer_[index];
183 }
184
193 T& operator[](std::size_t index) noexcept
194 {
195 return buffer_[index];
196 }
197
206 const T& operator[](std::size_t index) const noexcept
207 {
208 return buffer_[index];
209 }
210
225 template<typename... Rest>
226 T& operator()(std::size_t first, std::size_t second, Rest... rest)
227 {
228 std::array<std::size_t, sizeof...(Rest) + 2> indices{
229 first,
230 second,
231 static_cast<std::size_t>(rest)...
232 };
233
234 return buffer_[offset(shape_, strides_, indices)];
235 }
236
248 template<typename... Rest>
249 const T& operator()(std::size_t first, std::size_t second, Rest... rest) const
250 {
251 std::array<std::size_t, sizeof...(Rest) + 2> indices{
252 first,
253 second,
254 static_cast<std::size_t>(rest)...
255 };
256
257 return buffer_[offset(shape_, strides_, indices)];
258 }
259
268 T& at(std::size_t index)
269 {
270 core::validation::require_index(index, size(), "Tensor flat index out of bounds.");
271 return buffer_[index];
272 }
273
282 const T& at(std::size_t index) const
283 {
284 core::validation::require_index(index, size(), "Tensor flat index out of bounds.");
285 return buffer_[index];
286 }
287
299 template<typename... Rest>
300 T& at(std::size_t first, std::size_t second, Rest... rest)
301 {
302 std::array<std::size_t, sizeof...(Rest) + 2> indices{
303 first,
304 second,
305 static_cast<std::size_t>(rest)...
306 };
307
308 try
309 {
310 return buffer_[offset(shape_, strides_, indices)];
311 }
312 catch (const Exceptions::DimensionError&)
313 {
314 throw Exceptions::IndexError("Tensor multi-index rank mismatch.");
315 }
316 catch (const Exceptions::IndexError&)
317 {
318 throw Exceptions::IndexError("Tensor multi-index out of bounds.");
319 }
320 }
321
333 template<typename... Rest>
334 const T& at(std::size_t first, std::size_t second, Rest... rest) const
335 {
336 std::array<std::size_t, sizeof...(Rest) + 2> indices{
337 first,
338 second,
339 static_cast<std::size_t>(rest)...
340 };
341
342 try
343 {
344 return buffer_[offset(shape_, strides_, indices)];
345 }
346 catch (const Exceptions::DimensionError&)
347 {
348 throw Exceptions::IndexError("Tensor multi-index rank mismatch.");
349 }
350 catch (const Exceptions::IndexError&)
351 {
352 throw Exceptions::IndexError("Tensor multi-index out of bounds.");
353 }
354 }
355
362 T& front()
363 {
364 return buffer_.front();
365 }
366
373 const T& front() const
374 {
375 return buffer_.front();
376 }
377
384 T& back()
385 {
386 return buffer_.back();
387 }
388
395 const T& back() const
396 {
397 return buffer_.back();
398 }
399
405 [[nodiscard]] T* data() noexcept
406 {
407 return buffer_.data();
408 }
409
415 [[nodiscard]] const T* data() const noexcept
416 {
417 return buffer_.data();
418 }
419
425 [[nodiscard]] auto begin() noexcept
426 {
427 return buffer_.begin();
428 }
429
435 [[nodiscard]] auto begin() const noexcept
436 {
437 return buffer_.begin();
438 }
439
445 [[nodiscard]] auto cbegin() const noexcept
446 {
447 return buffer_.cbegin();
448 }
449
455 [[nodiscard]] auto end() noexcept
456 {
457 return buffer_.end();
458 }
459
465 [[nodiscard]] auto end() const noexcept
466 {
467 return buffer_.end();
468 }
469
475 [[nodiscard]] auto cend() const noexcept
476 {
477 return buffer_.cend();
478 }
479
485 [[nodiscard]] auto rbegin() noexcept
486 {
487 return buffer_.rbegin();
488 }
489
495 [[nodiscard]] auto rbegin() const noexcept
496 {
497 return buffer_.rbegin();
498 }
499
505 [[nodiscard]] auto crbegin() const noexcept
506 {
507 return buffer_.crbegin();
508 }
509
515 [[nodiscard]] auto rend() noexcept
516 {
517 return buffer_.rend();
518 }
519
525 [[nodiscard]] auto rend() const noexcept
526 {
527 return buffer_.rend();
528 }
529
535 [[nodiscard]] auto crend() const noexcept
536 {
537 return buffer_.crend();
538 }
539
545 void fill(const T& value)
546 {
547 buffer_.fill(value);
548 }
549
555 void swap(Tensor& other) noexcept
556 {
557 shape_.swap(other.shape_);
558 strides_.swap(other.strides_);
559 buffer_.swap(other.buffer_);
560 }
561};
562
563}
std::size_t offset(const stratax::core::Shape &shape, const stratax::core::Strides &strides, const IndexContainer &index)
Computes a flat storage offset from a shape, strides, and index container.
Definition Indexing.hpp:23
Shared runtime validation helpers.
Signals an invalid dimension count or dimension arithmetic failure.
Signals an invalid index access.
void fill(const T &value)
Fills every element with the same value.
Definition Tensor.hpp:545
void swap(Tensor &other) noexcept
Swaps the contents of two tensors.
Definition Tensor.hpp:555
T & operator()(std::size_t first, std::size_t second, Rest... rest)
Returns an element by multidimensional index with bounds checking.
Definition Tensor.hpp:226
auto end() const noexcept
Returns a const iterator one past the last element.
Definition Tensor.hpp:465
auto begin() noexcept
Returns an iterator to the first element.
Definition Tensor.hpp:425
Tensor(const Tensor &)=default
Creates a copy of another tensor.
const core::Shape & shape() const noexcept
Definition Tensor.hpp:144
T * data() noexcept
Returns the raw data pointer.
Definition Tensor.hpp:405
const T & front() const
Returns the first element as a const reference.
Definition Tensor.hpp:373
const T & operator[](std::size_t index) const noexcept
Returns a flat element without bounds checking.
Definition Tensor.hpp:206
Tensor(const core::Shape &shape, const T &value)
Creates a tensor from a shape and fills it with a value.
Definition Tensor.hpp:72
std::size_t rank() const noexcept
Returns the tensor rank.
Definition Tensor.hpp:134
bool empty() const noexcept
Returns whether the tensor contains no elements.
Definition Tensor.hpp:124
const T & at(std::size_t first, std::size_t second, Rest... rest) const
Returns an element by multi-index with bounds checking.
Definition Tensor.hpp:334
std::size_t size() const noexcept
Definition Tensor.hpp:114
auto end() noexcept
Returns an iterator one past the last element.
Definition Tensor.hpp:455
auto rend() const noexcept
Returns a const reverse iterator before the first element.
Definition Tensor.hpp:525
T & front()
Returns the first element.
Definition Tensor.hpp:362
auto rend() noexcept
Returns a reverse iterator before the first element.
Definition Tensor.hpp:515
const core::Strides & strides() const noexcept
Returns the tensor strides.
Definition Tensor.hpp:154
auto cbegin() const noexcept
Returns a const iterator to the first element.
Definition Tensor.hpp:445
auto rbegin() noexcept
Returns a reverse iterator to the last element.
Definition Tensor.hpp:485
auto crbegin() const noexcept
Returns a const reverse iterator to the last element.
Definition Tensor.hpp:505
Tensor() noexcept=default
Creates an empty tensor with rank 0.
auto rbegin() const noexcept
Returns a const reverse iterator to the last element.
Definition Tensor.hpp:495
const T & at(std::size_t index) const
Returns an element by rank-1 flat index with bounds checking.
Definition Tensor.hpp:282
T & at(std::size_t index)
Returns an element by rank-1 flat index with bounds checking.
Definition Tensor.hpp:268
T & operator[](std::size_t index) noexcept
Returns a flat element without bounds checking.
Definition Tensor.hpp:193
const T * data() const noexcept
Returns the raw data pointer as a const pointer.
Definition Tensor.hpp:415
auto cend() const noexcept
Returns a const iterator one past the last element.
Definition Tensor.hpp:475
T & operator()(std::size_t index) noexcept
Returns a flat element without bounds checking.
Definition Tensor.hpp:167
T & back()
Returns the last element.
Definition Tensor.hpp:384
auto crend() const noexcept
Returns a const reverse iterator before the first element.
Definition Tensor.hpp:535
const T & operator()(std::size_t index) const noexcept
Returns a flat element without bounds checking.
Definition Tensor.hpp:180
T & at(std::size_t first, std::size_t second, Rest... rest)
Returns an element by multi-index with bounds checking.
Definition Tensor.hpp:300
Tensor(Tensor &&) noexcept=default
Transfers ownership from another tensor.
const T & operator()(std::size_t first, std::size_t second, Rest... rest) const
Returns an element by multidimensional index with bounds checking.
Definition Tensor.hpp:249
auto begin() const noexcept
Returns a const iterator to the first element.
Definition Tensor.hpp:435
const T & back() const
Returns the last element as a const reference.
Definition Tensor.hpp:395
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
void require_index(std::size_t index, std::size_t size, const char *message)
Requires an index to be less than a size.