Txeo v0.1
A Developer-Friendly TensorFlow C++ Wrapper
Loading...
Searching...
No Matches
Tensor.h
Go to the documentation of this file.
1#ifndef TENSOR_H
2#define TENSOR_H
3
4#pragma once
5
6#include "TensorShape.h"
8
9#include <cstddef>
10#include <exception>
11#include <initializer_list>
12#include <memory>
13#include <type_traits>
14#include <vector>
15
16namespace txeo {
17
18template <typename T>
19concept c_numeric = std::is_arithmetic_v<T> && !std::is_same_v<T, bool>;
20
21namespace detail {
22class TensorHelper;
23}
24
25template <typename T>
26class Predictor;
27
28template <typename T>
29class TensorAgg;
30
31template <typename T>
32class TensorPart;
33
34template <typename T>
35class TensorOp;
36
37template <typename T>
38class TensorFunc;
39
47template <typename T>
48class Tensor {
49 public:
53 Tensor(const Tensor &tensor);
54 Tensor(Tensor &&tensor) noexcept;
56
60 Tensor &operator=(const Tensor &tensor);
61 Tensor &operator=(Tensor &&tensor) noexcept;
62 bool operator==(const Tensor &tensor);
63 bool operator!=(const Tensor &tensor);
64
65 template <typename U>
66 friend std::ostream &operator<<(std::ostream &os, const Tensor<U> &tensor);
67
88 explicit Tensor(const txeo::TensorShape &shape);
89
111
131 explicit Tensor(const std::vector<size_t> &shape);
132
152 explicit Tensor(std::vector<size_t> &&shape);
153
172 explicit Tensor(const std::initializer_list<size_t> &shape)
173 : Tensor(std::vector<size_t>(shape)) {}
174
196 explicit Tensor(const txeo::TensorShape &shape, const T &fill_value);
197
218 explicit Tensor(txeo::TensorShape &&shape, const T &fill_value);
219
240 explicit Tensor(const std::vector<size_t> &shape, const T &fill_value);
241
261 explicit Tensor(std::vector<size_t> &&shape, const T &fill_value);
262
282 explicit Tensor(const std::initializer_list<size_t> &shape, const T &fill_value)
283 : Tensor(std::vector<size_t>(shape), fill_value) {}
284
309 explicit Tensor(const txeo::TensorShape &shape, const std::vector<T> &values);
310
334 explicit Tensor(const std::vector<size_t> &shape, const std::vector<T> &values);
335
359 explicit Tensor(const std::initializer_list<size_t> &shape, const std::vector<T> &values)
360 : Tensor(std::vector<size_t>(shape), values) {}
361
381 explicit Tensor(const std::initializer_list<std::initializer_list<T>> &values);
382
410 explicit Tensor(
411 const std::initializer_list<std::initializer_list<std::initializer_list<T>>> &values);
412
418 [[nodiscard]] const txeo::TensorShape &shape() const;
419
425 constexpr std::type_identity_t<T> type() const;
426
432 [[nodiscard]] int order() const;
433
439 [[nodiscard]] size_t dim() const;
440
447 [[nodiscard]] size_t number_of_elements() const { return this->dim(); };
448
454 [[nodiscard]] size_t memory_size() const;
455
480 Tensor<T> slice(size_t first_axis_begin, size_t first_axis_end) const;
481
489 void view_of(const Tensor<T> &tensor, const txeo::TensorShape &shape);
490
518 template <typename U>
519 [[nodiscard]] bool is_equal_shape(const Tensor<U> &other) const {
520 return this->shape() == other.shape();
521 };
522
532
556 template <typename... Args>
557 requires(std::convertible_to<Args, size_t> && ...)
558 T &operator()(Args... args);
559
570 T &at();
571
597 template <typename... Args>
598 requires(std::convertible_to<Args, size_t> && ...)
599 T &at(Args... args);
600
609 const T &operator()() const;
610
634 template <typename... Args>
635 requires(std::convertible_to<Args, size_t> && ...)
636 const T &operator()(Args... args) const;
637
646 const T &at() const;
647
673 template <typename... Args>
674 requires(std::convertible_to<Args, size_t> && ...)
675 const T &at(Args... args) const;
676
703
729 void reshape(const std::vector<size_t> &shape);
730
756 void reshape(const std::initializer_list<size_t> &shape) {
757 this->reshape(std::vector<size_t>(shape));
758 };
759
770
776 void fill(const T &value);
777
803 void fill_with_uniform_random(const T &min, const T &max);
804
834 void fill_with_uniform_random(const T &min, const T &max, const size_t &seed1,
835 const size_t &seed2);
836
841 void shuffle();
842
862 void squeeze();
863
870 Tensor<T> &operator=(const T &value);
871
877 T *data();
878
884 [[nodiscard]] const T *data() const;
885
894
913 template <typename U>
914 friend txeo::Tensor<U> operator+(const txeo::Tensor<U> &left, const txeo::Tensor<U> &right);
915
916 template <typename U>
917 friend txeo::Tensor<U> operator+(const txeo::Tensor<U> &left, const U &right);
918
936 template <typename U>
937 friend txeo::Tensor<U> operator-(const txeo::Tensor<U> &left, const txeo::Tensor<U> &right);
938
954 template <typename U>
955 friend txeo::Tensor<U> operator-(const txeo::Tensor<U> &left, const U &right);
956
972 template <typename U>
973 friend txeo::Tensor<U> operator-(const U &left, const txeo::Tensor<U> &right);
974
989 template <typename U>
990 friend txeo::Tensor<U> operator*(const txeo::Tensor<U> &tensor, const U &scalar);
991
1006 template <typename U>
1007 friend txeo::Tensor<U> operator/(const txeo::Tensor<U> &left, const U &right);
1008
1024 template <typename U>
1025 friend txeo::Tensor<U> operator/(const U &left, const txeo::Tensor<U> &right);
1026
1028 Tensor<T> &operator+=(const T &tensor);
1030 Tensor<T> &operator-=(const T &tensor);
1031 Tensor<T> &operator*=(const T &scalar);
1032 Tensor<T> &operator/=(const T &scalar);
1033
1038
1039 protected:
1040 struct Impl;
1041 std::unique_ptr<Impl> _impl{nullptr};
1042
1043 friend class txeo::Predictor<T>;
1044 friend class txeo::TensorAgg<T>;
1045 friend class txeo::TensorPart<T>;
1046 friend class txeo::TensorOp<T>;
1047 friend class txeo::TensorFunc<T>;
1049
1050 template <typename P>
1052
1053 void fill_data_shape(const std::initializer_list<std::initializer_list<T>> &list,
1054 std::vector<T> &flat_data, std::vector<size_t> &shape);
1055
1056 void fill_data_shape(
1057 const std::initializer_list<std::initializer_list<std::initializer_list<T>>> &list,
1058 std::vector<T> &flat_data, std::vector<size_t> &shape);
1059
1060 void check_indexes(const std::vector<size_t> &indexes);
1061
1062 explicit Tensor();
1063};
1064
1069class TensorError : public std::runtime_error {
1070 public:
1071 using std::runtime_error::runtime_error;
1072};
1073
1074template <typename T>
1075template <typename... Args>
1076 requires(std::convertible_to<Args, size_t> && ...)
1077inline T &Tensor<T>::operator()(Args... args) {
1078 size_t indexes[] = {static_cast<size_t>(args)...};
1079 size_t size = this->order();
1080 auto *stride = this->shape().stride().data();
1081 size_t flat_index{indexes[size - 1]};
1082
1083 for (size_t i = 0; i < size - 1; ++i)
1084 flat_index += indexes[i] * stride[i];
1085
1086 return this->data()[flat_index];
1087}
1088
1089template <typename T>
1090template <typename... Args>
1091 requires(std::convertible_to<Args, size_t> && ...)
1092inline const T &Tensor<T>::operator()(Args... args) const {
1093 size_t indexes[] = {static_cast<size_t>(args)...};
1094 size_t size = this->order();
1095 auto *stride = this->shape().stride().data();
1096 size_t flat_index{indexes[size - 1]};
1097
1098 for (size_t i = 0; i < size - 1; ++i)
1099 flat_index += indexes[i] * stride[i];
1100
1101 return this->data()[flat_index];
1102}
1103
1104template <typename T>
1105template <typename... Args>
1106 requires(std::convertible_to<Args, size_t> && ...)
1107inline T &Tensor<T>::at(Args... args) {
1108 if (this->order() != sizeof...(Args))
1109 throw TensorError("The number of axes specified and the order of this tensor do no match.");
1110 try {
1111 check_indexes({static_cast<size_t>(args)...});
1112 } catch (std::exception e) {
1113 throw txeo::TensorError(e.what());
1114 }
1115
1116 return (*this)(args...);
1117}
1118
1119template <typename T>
1120template <typename... Args>
1121 requires(std::convertible_to<Args, size_t> && ...)
1122inline const T &Tensor<T>::at(Args... args) const {
1123 if (this->order() != sizeof...(Args))
1124 throw TensorError("The number of axes specified and the order of this tensor do no match.");
1125 try {
1126 check_indexes({static_cast<size_t>(args)...});
1127 } catch (std::exception e) {
1128 throw txeo::TensorError(e.what());
1129 }
1130
1131 return (*this)(args...);
1132}
1133
1134template <typename T>
1135void Tensor<T>::fill_data_shape(const std::initializer_list<std::initializer_list<T>> &list,
1136 std::vector<T> &flat_data, std::vector<size_t> &shape) {
1137
1138 shape.emplace_back(list.size());
1139 std::vector<std::initializer_list<T>> v_list(list);
1140 for (size_t i{1}; i < v_list.size(); ++i)
1141 if (v_list[i].size() != v_list[i - 1].size())
1142 throw txeo::TensorError("Tensor initialization is inconsistent!");
1143
1144 shape.emplace_back(v_list[0].size());
1145 for (auto &item : v_list)
1146 for (auto &subitem : item)
1147 flat_data.emplace_back(subitem);
1148}
1149
1150template <typename T>
1152 const std::initializer_list<std::initializer_list<std::initializer_list<T>>> &list,
1153 std::vector<T> &flat_data, std::vector<size_t> &shape) {
1154 shape.emplace_back(list.size());
1155 std::vector<std::initializer_list<std::initializer_list<T>>> v_list(list);
1156 for (size_t i{1}; i < v_list.size(); ++i)
1157 if (v_list[i].size() != v_list[i - 1].size())
1158 throw txeo::TensorError("Tensor initialization is inconsistent!");
1159
1160 shape.emplace_back(v_list[0].size());
1161 bool emplaced{false};
1162 for (size_t i{0}; i < v_list.size(); ++i) {
1163 std::vector<std::initializer_list<T>> v_sublist(v_list[i]);
1164 for (size_t i{1}; i < v_sublist.size(); ++i)
1165 if (v_sublist[i].size() != v_sublist[i - 1].size())
1166 throw txeo::TensorError("Tensor initialization is inconsistent!");
1167
1168 if (!emplaced) {
1169 shape.emplace_back(v_sublist[0].size());
1170 emplaced = true;
1171 }
1172 for (auto &item : v_sublist)
1173 for (auto &subitem : item)
1174 flat_data.emplace_back(subitem);
1175 }
1176}
1177
1178} // namespace txeo
1179
1180#endif // TENSOR_H
Class that deals with the main tasks of prediction (inference)
Definition Predictor.h:45
A utility class for aggregation functions on tensors.
Definition TensorAgg.h:22
Exceptions concerning txeo::Tensor.
Definition Tensor.h:1069
A utility class for common math functions on tensors.
Definition TensorFunc.h:23
Implements the mathematical concept of tensor, which is a magnitude of multiple order....
Definition Tensor.h:48
Tensor(Tensor &&tensor) noexcept
Tensor(txeo::TensorShape &&shape)
Constructs a Tensor from a specified txeo::TensorShape.
Tensor(const std::vector< size_t > &shape, const T &fill_value)
Constructs a Tensor from a specified shape std::vector and fills it with a value.
friend std::ostream & operator<<(std::ostream &os, const Tensor< U > &tensor)
friend txeo::Tensor< U > operator+(const txeo::Tensor< U > &left, const U &right)
Tensor< T > clone() const
Returns a clone of this tensor.
T * data()
Acesses the raw data of this tensor.
void fill_with_uniform_random(const T &min, const T &max)
Fills the tensor with uniformly distributed random values ranging according to the specified interval...
Tensor< T > & operator/=(const T &scalar)
bool operator!=(const Tensor &tensor)
Tensor(std::vector< size_t > &&shape, const T &fill_value)
Constructs a Tensor from a specified shape std::vector and fills it with a value.
Tensor & operator=(const Tensor &tensor)
void squeeze()
Reshapes this tensor by removing all the axes of dimension one.
Tensor(const std::initializer_list< std::initializer_list< std::initializer_list< T > > > &values)
Constructs a third order Tensor from a nested std::initializer_list.
std::unique_ptr< Impl > _impl
Definition Tensor.h:1041
bool operator==(const Tensor &tensor)
Tensor & operator=(Tensor &&tensor) noexcept
friend txeo::Tensor< U > operator-(const txeo::Tensor< U > &left, const U &right)
Element-wise tensor-scalar addition operator.
void create_from_shape(P &&shape)
Tensor< T > flatten() const
Returns a first order reshaped view of this tensor.
Tensor< T > & operator+=(const Tensor< T > &tensor)
constexpr std::type_identity_t< T > type() const
Returns the data type of this tensor.
void shuffle()
Shuffles the elements of this tensor.
Tensor(const txeo::TensorShape &shape, const std::vector< T > &values)
Constructs a Tensor object from a specified txeo::TensorShape and fills it with a std::vector of valu...
Tensor< T > & operator-=(const Tensor< T > &tensor)
friend class txeo::detail::TensorHelper
Definition Tensor.h:1048
Tensor(const std::initializer_list< size_t > &shape, const T &fill_value)
Constructs a Tensor from a specified initializer list and fills it with a value.
Definition Tensor.h:282
Tensor< T > & operator*=(const T &scalar)
bool is_equal_shape(const Tensor< U > &other) const
Compares the shape of this tensor with the shape of the specified tensor.
Definition Tensor.h:519
friend txeo::Tensor< U > operator+(const txeo::Tensor< U > &left, const txeo::Tensor< U > &right)
Returns the sum of two tensors.
txeo::TensorIterator< const T > begin() const
friend txeo::Tensor< U > operator/(const txeo::Tensor< U > &left, const U &right)
Element-wise division operator (tensor / scalar)
Tensor(const std::initializer_list< std::initializer_list< T > > &values)
Constructs a second order Tensor from a nested std::initializer_list.
Tensor(const std::initializer_list< size_t > &shape)
Constructs a Tensor from a specified shape std::vector.
Definition Tensor.h:172
friend txeo::Tensor< U > operator-(const txeo::Tensor< U > &left, const txeo::Tensor< U > &right)
Returns the subtraction of two tensors.
Tensor(std::vector< size_t > &&shape)
Constructs a Tensor from a specified shape std::vector.
Tensor(const txeo::TensorShape &shape, const T &fill_value)
Constructs a Tensor from a specified txeo::TensorShape and fills it with a value.
friend txeo::Tensor< U > operator/(const U &left, const txeo::Tensor< U > &right)
Element-wise scalar-tensor division operator.
txeo::TensorIterator< T > end()
const T * data() const
Reads the raw data of this tensor.
void fill(const T &value)
Fills this tensor with the specified value.
Tensor< T > & operator=(const T &value)
Assigns a specified value to this tensor elements.
Tensor(txeo::TensorShape &&shape, const T &fill_value)
Constructs a Tensor from a specified txeo::TensorShape and fills it with a value.
void reshape(const txeo::TensorShape &shape)
Reshapes this tensor if the specified shape defines a number of elements equal to this tensor order.
txeo::TensorIterator< const T > end() const
Tensor(const Tensor &tensor)
T & operator()()
Accesses the value of this tensor if it is a scalar (order zero).
Tensor(const std::initializer_list< size_t > &shape, const std::vector< T > &values)
Constructs a Tensor object from a specified initializer list and fills it with a std::vector of value...
Definition Tensor.h:359
friend txeo::Tensor< U > operator*(const txeo::Tensor< U > &tensor, const U &scalar)
Returns the scalar multiplication of a tensor.
Tensor< T > & operator+=(const T &tensor)
Tensor< T > & operator-=(const T &tensor)
Tensor(const std::vector< size_t > &shape)
Constructs a Tensor from a specified shape std::vector.
const txeo::TensorShape & shape() const
Returns the shape of this tensor.
void view_of(const Tensor< T > &tensor, const txeo::TensorShape &shape)
Views the content of the specified tensor according to the specified shape. There is no element copyi...
txeo::TensorIterator< T > begin()
void fill_with_uniform_random(const T &min, const T &max, const size_t &seed1, const size_t &seed2)
Fills the tensor with uniformly distributed random values ranging according to the specified interval...
size_t memory_size() const
Returns the number of bytes occupied by this tensor.
void check_indexes(const std::vector< size_t > &indexes)
Tensor(const txeo::TensorShape &shape)
Constructs a tensor from a specified txeo::TensorShape.
T & at()
Accesses the value of this tensor if it is a scalar (order zero).
Tensor(const std::vector< size_t > &shape, const std::vector< T > &values)
Constructs a Tensor object from a specified std::vector<size_t> and fills it with a std::vector of va...
size_t dim() const
Returns the dimension of this tensor.
friend txeo::Tensor< U > operator-(const U &left, const txeo::Tensor< U > &right)
Element-wise scalar-tensor subtraction operator.
size_t number_of_elements() const
Returns the number of elements of this tensor, which corresponds to the dimension of this tensor.
Definition Tensor.h:447
Tensor< T > slice(size_t first_axis_begin, size_t first_axis_end) const
Returns a view ot this tensor from a specified range of dimensions of the first axis.
int order() const
Returns the order of this tensor.
void fill_data_shape(const std::initializer_list< std::initializer_list< T > > &list, std::vector< T > &flat_data, std::vector< size_t > &shape)
Definition Tensor.h:1135
A utility class for performing operations on tensors and vectors.
Definition TensorOp.h:21
A utility class for partitioning tensors.
Definition TensorPart.h:19
The shape of a tensor is an ordered collection of dimensions of mathematical vector spaces.
Definition TensorShape.h:30
Definition Matrix.h:11