Tatooine
dynamic_tensor.h
Go to the documentation of this file.
1#ifndef TATOOINE_DYNAMIC_TENSOR_H
2#define TATOOINE_DYNAMIC_TENSOR_H
3//==============================================================================
6
7#include <ostream>
8#include <sstream>
9//==============================================================================
10namespace tatooine {
11//==============================================================================
12template <arithmetic_or_complex T>
16 template <einstein_notation::index... Is>
19 template <einstein_notation::index... Is>
22 using parent_type::at;
23 using parent_type::operator();
24
25 static auto constexpr is_tensor() { return true; }
26 static auto constexpr is_dynamic() { return true; }
27 //============================================================================
28 // factories
29 //============================================================================
30 static auto zeros(integral auto const... size) {
31 return this_type{tag::zeros, size...};
32 }
33 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
34 static auto zeros(integral_range auto const& size) {
35 return this_type{tag::zeros, size};
36 }
37 //----------------------------------------------------------------------------
38 static auto ones(integral auto... size) {
39 return this_type{tag::ones, size...};
40 }
41 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
42 static auto ones(integral_range auto const& size) {
43 return this_type{tag::ones, size};
44 }
45 //------------------------------------------------------------------------------
46 template <typename RandEng = std::mt19937_64>
47 static auto randu(T const min, T const max, integral_range auto const& size,
48 RandEng&& eng = RandEng{std::random_device{}()}) {
49 return this_type{
50 random::uniform<T, RandEng>{min, max, std::forward<RandEng>(eng)},
51 size};
52 }
53 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
54 template <typename RandEng = std::mt19937_64>
55 static auto randu(integral_range auto const& size, T min = 0, T max = 1,
56 RandEng&& eng = RandEng{std::random_device{}()}) {
57 return this_type{
58 random::uniform<T, RandEng>{min, max, std::forward<RandEng>(eng)},
59 size};
60 }
61 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
62 template <typename RandEng = std::mt19937_64>
63 static auto randu(integral auto const... is) {
65 T(0), T(1), RandEng{std::random_device{}()}},
66 is...};
67 }
68 //------------------------------------------------------------------------------
69 template <typename RandEng = std::mt19937_64>
70 static auto randn(T const mean, T const stddev,
71 integral_range auto const& size,
72 RandEng&& eng = RandEng{std::random_device{}()}) {
73 return this_type{
74 random::uniform<T, RandEng>{mean, stddev, std::forward<RandEng>(eng)},
75 size};
76 }
77 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
78 template <typename RandEng = std::mt19937_64>
79 static auto randn(integral_range auto const& size, T mean = 0, T stddev = 1,
80 RandEng&& eng = RandEng{std::random_device{}()}) {
81 return this_type{
82 random::uniform<T, RandEng>{mean, stddev, std::forward<RandEng>(eng)},
83 size};
84 }
85 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
86 template <typename RandEng = std::mt19937_64>
87 static auto randn(integral auto const... is) {
89 T(1), T(1), RandEng{std::random_device{}()}},
90 is...};
91 }
92 //----------------------------------------------------------------------------
93 template <random_number_generator Rand, integral_range Size>
94 static auto rand(Rand&& rand, Size&& size) {
95 return this_type{std::forward<Rand>(rand), std::forward<Size>(size)};
96 }
97 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
98 template <random_number_generator Rand>
99 static auto rand(Rand&& rand, integral auto const... size){
100 return this_type{std::forward<Rand>(rand), size...};
101 }
102 //----------------------------------------------------------------------------
103 static auto vander(arithmetic_range auto const& v) {
104 return vander(v, std::ranges::size(v));
105 }
106 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107 template <arithmetic Real_, std::size_t N>
108 static auto vander(vec<Real_, N> const& v) {
109 return vander(v, N);
110 }
111 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
112 static auto vander(arithmetic_range auto const& v,
113 integral auto const degree) {
114 auto V = this_type{std::ranges::size(v), degree};
115 auto factor_up_row = [row = 0ul, &V, degree](auto const x) mutable {
116 V(row, 0) = 1;
117 for (std::size_t col = 1; col < degree; ++col) {
118 V(row, col) = V(row, col - 1) * x;
119 }
120 ++row;
121 };
122 auto v_it = begin(v);
123 for (std::size_t i = 0; i < degree; ++i, ++v_it) {
124 factor_up_row(static_cast<T>(*v_it));
125 }
126 return V;
127 }
128 //============================================================================
129 // constructors
130 //============================================================================
131 tensor() = default;
132 tensor(tensor const& other) = default;
133 tensor(tensor&& other) noexcept = default;
134 auto operator=(tensor const& other) -> tensor& = default;
135 auto operator=(tensor&& other) noexcept -> tensor& = default;
136 ~tensor() = default;
137 //============================================================================
138 explicit tensor(dynamic_tensor auto&& other) { assign(other); }
139 //----------------------------------------------------------------------------
142 explicit tensor(integral auto const... dimensions)
143 requires(!integral<T>) {
144 this->resize(dimensions...);
145 }
146 //----------------------------------------------------------------------------
148 : parent_type{tag, dimensions...} {}
149 //----------------------------------------------------------------------------
151 : parent_type{tag, std::forward<decltype(dimensions)>(dimensions)} {}
152 //----------------------------------------------------------------------------
154 : parent_type{tag, dimensions...} {}
155 //----------------------------------------------------------------------------
157 : parent_type{tag, std::forward<decltype(dimensions)>(dimensions)} {}
158 //----------------------------------------------------------------------------
159 template <random_number_generator Rand>
160 tensor(Rand&& rand, integral auto const... dimensions)
161 : parent_type{std::forward<Rand>(rand), dimensions...} {}
162 //----------------------------------------------------------------------------
163 template <random_number_generator Rand, integral_range Dimensions>
164 tensor(Rand&& rand, Dimensions&& dimensions)
165 : parent_type{std::forward<Rand>(rand),
166 std::forward<Dimensions>(dimensions)} {}
167 //----------------------------------------------------------------------------
168 template <general_tensor OtherTensor>
169 tensor(OtherTensor const& other) {
170 assign(other);
171 }
172 //----------------------------------------------------------------------------
174 template <convertible_to<T>... Components>
175 explicit tensor(Components&&... components) requires(
177 : parent_type{std::vector<T>{std::forward<Components>(components)...},
178 sizeof...(Components)} {}
179 //----------------------------------------------------------------------------
181 template <floating_point_range Components>
182 explicit tensor(Components&& components)
183 : parent_type{std::forward<Components>(components)} {}
184 //----------------------------------------------------------------------------
186 template <arithmetic_or_complex... Rows, std::size_t N>
187 explicit tensor(Rows(&&... rows)[N])
188 : parent_type{sizeof...(Rows), N} {
189 // lambda inserting row into data block
190 auto insert_row = [r = std::size_t(0), this](auto const& row) mutable {
191 for (std::size_t c = 0; c < N; ++c) {
192 at(r, c) = static_cast<T>(row[c]);
193 }
194 ++r;
195 };
196
197 for_each(insert_row, rows...);
198 }
199 //============================================================================
200 // operators
201 //============================================================================
202 template <general_tensor OtherTensor>
203 auto operator=(OtherTensor const& other) -> tensor<T>& {
204 if constexpr (transposed_tensor<OtherTensor>) {
205 if (this == &other.internal_tensor()) {
206 assing_self_transposed(other);
207 } else {
208 assign(other);
209 }
210 } else {
211 assign(other);
212 }
213 return *this;
214 }
215 //------------------------------------------------------------------------------
216 auto assing_self_transposed(general_tensor auto const& other) {
217 auto const old_size = dynamic_multidim_size{*this};
218 this->resize(other.dimensions());
219 for (std::size_t col = 0; col < this->size(1); ++col) {
220 for (std::size_t row = col + 1; row < this->size(0); ++row) {
221 std::swap(this->at(row, col),
222 this->data(old_size.plain_index(col, row)));
223 }
224 }
225 return *this;
226}
227 //----------------------------------------------------------------------------
228 auto assign(general_tensor auto const& other) {
229 this->resize(other.dimensions());
230 auto const s = this->size();
231 auto const r = this->num_dimensions();
232 auto max_cnt =
233 std::accumulate(begin(s), end(s), std::size_t(1), std::multiplies<std::size_t>{});
234 auto cnt = std::size_t(0);
235 auto is = std::vector<std::size_t>(r, 0);
236
237 while (cnt < max_cnt) {
238 this->at(is) = other(is);
239
240 ++is.front();
241 for (std::size_t i = 0; i < r - 1; ++i) {
242 if (is[i] == s[i]) {
243 is[i] = 0;
244 ++is[i + 1];
245 } else {
246 break;
247 }
248 }
249 ++cnt;
250 }
251 }
252 //============================================================================
253 // methods
254 //============================================================================
255 auto dimensions() const { return this->size(); }
256 auto dimension(std::size_t const i) const { return dimensions()[i]; }
257 auto rank() const { return this->num_dimensions(); }
258 //----------------------------------------------------------------------------
259 template <einstein_notation::index... Is>
260 auto at(Is const... /*is*/) {
261 assert(rank() == 0 || sizeof...(Is) == rank());
262 return indexed_type<Is...>{*this};
263 }
264 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
265 template <einstein_notation::index... Is>
266 auto at(Is const... /*is*/) const {
267 assert(rank() == 0 || sizeof...(Is) == rank());
268 return const_indexed_type<Is...>{*this};
269 }
270 //----------------------------------------------------------------------------
271 auto operator()(einstein_notation::index auto const... is) const {
272 assert(rank() == 0 || sizeof...(is) == rank());
273 return at(is...);
274 }
275 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
276 auto operator()(einstein_notation::index auto const... is) {
277 assert(rank() == 0 || sizeof...(is) == rank());
278 return at(is...);
279 }
280 //----------------------------------------------------------------------------
281 auto at(integral auto const... is) -> auto& {
282 assert(rank() == 0 || sizeof...(is) == rank());
283 return parent_type::at(is...);
284 }
285 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
286 auto at(integral auto const... is) const -> auto const& {
287 assert(rank() == 0 || sizeof...(is) == rank());
288 return parent_type::at(is...);
289 }
290 //----------------------------------------------------------------------------
291 auto operator()(integral auto const... is) -> auto& {
292 assert(rank() == 0 || sizeof...(is) == rank());
293 return parent_type::at(is...);
294 }
295 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
296 auto operator()(integral auto const... is) const -> auto const& {
297 assert(rank() == 0 || sizeof...(is) == rank());
298 return parent_type::at(is...);
299 }
300};
301//==============================================================================
302template <typename... Rows, std::size_t N>
303tensor(Rows(&&... rows)[N]) -> tensor<common_type<Rows...>>;
304
305template <typename... Ts>
306tensor(Ts...) -> tensor<common_type<Ts...>>;
307
308template <dynamic_tensor Tensor>
310//==============================================================================
311} // namespace tatooine
312//==============================================================================
313#endif
Definition: dynamic_multidim_array.h:18
Definition: dynamic_multidim_size.h:16
static std::size_t constexpr num_dimensions()
Definition: static_multidim_array.h:29
static auto constexpr size()
Definition: static_multidim_array.h:30
constexpr auto data() -> ValueType *
Definition: static_multidim_array.h:260
Definition: concepts.h:36
Definition: concepts.h:87
Definition: tensor_concepts.h:17
Definition: tensor_concepts.h:9
Definition: concepts.h:91
Definition: concepts.h:21
Definition: tensor_concepts.h:93
static constexpr zeros_t zeros
Definition: tags.h:103
static constexpr ones_t ones
Definition: tags.h:106
Definition: algorithm.h:6
typename common_type_impl< Ts... >::type common_type
Definition: common_type.h:23
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322
constexpr auto max(A &&a, B &&b)
Definition: math.h:20
constexpr auto min(A &&a, B &&b)
Definition: math.h:15
constexpr void for_each(F &&f, Ts &&... ts)
Definition: utility.h:39
static constexpr forward_tag forward
Definition: tags.h:9
auto constexpr assign(Other &&other) -> void
Definition: base_tensor.h:82
static auto constexpr dimensions()
Definition: base_tensor.h:47
Definition: indexed_dynamic_tensor.h:28
Definition: random.h:15
Definition: tags.h:105
Definition: tags.h:102
Definition: dynamic_tensor.h:13
static auto rand(Rand &&rand, integral auto const ... size)
Definition: dynamic_tensor.h:99
tensor(integral auto const ... dimensions)
Definition: dynamic_tensor.h:142
static auto randn(integral_range auto const &size, T mean=0, T stddev=1, RandEng &&eng=RandEng{std::random_device{}()})
Definition: dynamic_tensor.h:79
auto assing_self_transposed(general_tensor auto const &other)
Definition: dynamic_tensor.h:216
static auto vander(arithmetic_range auto const &v)
Definition: dynamic_tensor.h:103
auto operator()(einstein_notation::index auto const ... is)
Definition: dynamic_tensor.h:276
auto dimensions() const
Definition: dynamic_tensor.h:255
tensor(tag::zeros_t tag, integral auto... dimensions)
Definition: dynamic_tensor.h:153
static auto vander(vec< Real_, N > const &v)
Definition: dynamic_tensor.h:108
static auto randu(integral_range auto const &size, T min=0, T max=1, RandEng &&eng=RandEng{std::random_device{}()})
Definition: dynamic_tensor.h:55
auto rank() const
Definition: dynamic_tensor.h:257
static auto ones(integral_range auto const &size)
Definition: dynamic_tensor.h:42
tensor(Components &&components)
Constructs a rank 1 tensor aka vector.
Definition: dynamic_tensor.h:182
auto operator()(einstein_notation::index auto const ... is) const
Definition: dynamic_tensor.h:271
tensor(Rows(&&... rows)[N])
Constructs a rank 2 tensor aka matrix.
Definition: dynamic_tensor.h:187
tensor(Components &&... components)
Constructs a rank 1 tensor aka vector.
Definition: dynamic_tensor.h:175
tensor(Rand &&rand, integral auto const ... dimensions)
Definition: dynamic_tensor.h:160
tensor(tag::zeros_t tag, integral_range auto &&dimensions)
Definition: dynamic_tensor.h:156
static auto randu(integral auto const ... is)
Definition: dynamic_tensor.h:63
static auto zeros(integral auto const ... size)
Definition: dynamic_tensor.h:30
tensor(tensor &&other) noexcept=default
static auto zeros(integral_range auto const &size)
Definition: dynamic_tensor.h:34
auto dimension(std::size_t const i) const
Definition: dynamic_tensor.h:256
tensor(tensor const &other)=default
auto operator()(integral auto const ... is) const -> auto const &
Definition: dynamic_tensor.h:296
tensor(dynamic_tensor auto &&other)
Definition: dynamic_tensor.h:138
static auto randn(T const mean, T const stddev, integral_range auto const &size, RandEng &&eng=RandEng{std::random_device{}()})
Definition: dynamic_tensor.h:70
static auto constexpr is_tensor()
Definition: dynamic_tensor.h:25
tensor(tag::ones_t tag, integral auto... dimensions)
Definition: dynamic_tensor.h:147
static auto randn(integral auto const ... is)
Definition: dynamic_tensor.h:87
auto at(integral auto const ... is) const -> auto const &
Definition: dynamic_tensor.h:286
static auto ones(integral auto... size)
Definition: dynamic_tensor.h:38
auto at(Is const ...) const
Definition: dynamic_tensor.h:266
tensor(OtherTensor const &other)
Definition: dynamic_tensor.h:169
static auto constexpr is_dynamic()
Definition: dynamic_tensor.h:26
static auto randu(T const min, T const max, integral_range auto const &size, RandEng &&eng=RandEng{std::random_device{}()})
Definition: dynamic_tensor.h:47
auto assign(general_tensor auto const &other)
Definition: dynamic_tensor.h:228
auto at(integral auto const ... is) -> auto &
Definition: dynamic_tensor.h:281
auto operator=(tensor const &other) -> tensor &=default
auto operator()(integral auto const ... is) -> auto &
Definition: dynamic_tensor.h:291
static auto vander(arithmetic_range auto const &v, integral auto const degree)
Definition: dynamic_tensor.h:112
auto operator=(tensor &&other) noexcept -> tensor &=default
static auto rand(Rand &&rand, Size &&size)
Definition: dynamic_tensor.h:94
tensor(tag::ones_t tag, integral_range auto &&dimensions)
Definition: dynamic_tensor.h:150
auto at(Is const ...)
Definition: dynamic_tensor.h:260
tensor(Rand &&rand, Dimensions &&dimensions)
Definition: dynamic_tensor.h:164
auto operator=(OtherTensor const &other) -> tensor< T > &
Definition: dynamic_tensor.h:203
Definition: tensor.h:17
static auto constexpr rank()
Definition: base_tensor.h:41
auto constexpr at(integral auto const ... is) -> decltype(auto)
Definition: tensor.h:38
tensor< ValueType, Dims... > this_type
Definition: tensor.h:19
type_list_at< this_type, I > at
Definition: type_list.h:269
Definition: vec.h:12