IgANet
IgANets - Isogeometric Analysis Networks
Loading...
Searching...
No Matches
blocktensor.hpp
Go to the documentation of this file.
1
15#pragma once
16
17#include <array>
18#include <exception>
19#include <initializer_list>
20#include <memory>
21#include <type_traits>
22
23#include <core.hpp>
24#include <utils/fqn.hpp>
25
26namespace iganet {
27namespace utils {
28
31template <typename T> struct is_shared_ptr : std::false_type {};
32
33template <typename T>
34struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
36
38template <typename T> inline auto make_shared(T &&arg) {
40 return std::forward<typename std::decay<T>::type>(arg);
41 else
42 return std::make_shared<typename std::decay<T>::type>(std::forward<T>(arg));
43}
44
46template <typename T, std::size_t... Dims> class BlockTensor;
47
49template <typename T, std::size_t... Dims>
51
52protected:
54 std::array<std::shared_ptr<T>, (Dims * ...)> data_;
55
56public:
58 BlockTensorCore() = default;
59
61 template <typename... Ts, std::size_t... dims>
63 auto it = data_.begin();
64 (std::transform(other.data().begin(), other.data().end(), it,
65 [&it](auto &&d) {
66 it++;
67 return std::move(d);
68 }),
69 ...);
70 }
71
73 template <typename... Ts, std::size_t... dims>
75 auto it = data_.begin();
76 (std::transform(other.data().begin(), other.data().end(), it,
77 [&it](auto &&d) {
78 it++;
79 return std::move(d);
80 }),
81 ...);
82 }
83
85 template <typename... Ts>
86 explicit BlockTensorCore(Ts &&...data)
87 : data_({make_shared<Ts>(std::forward<Ts>(data))...}) {}
88
90 inline static constexpr auto dims() {
91 return std::array<std::size_t, sizeof...(Dims)>({Dims...});
92 }
93
95 template <std::size_t i> inline static constexpr std::size_t dim() {
96 if constexpr (i < sizeof...(Dims))
97 return std::get<i>(std::forward_as_tuple(Dims...));
98 else
99 return 0;
100 }
101
103 inline static constexpr std::size_t size() { return sizeof...(Dims); }
104
106 inline static constexpr std::size_t entries() { return (Dims * ...); }
107
109 inline const std::array<std::shared_ptr<T>, (Dims * ...)> &data() const {
110 return data_;
111 }
112
114 inline std::array<std::shared_ptr<T>, (Dims * ...)> &data() { return data_; }
115
117 inline const std::shared_ptr<T> &operator[](std::size_t idx) const {
118 assert(0 <= idx && idx < (Dims * ...));
119 return data_[idx];
120 }
121
123 inline std::shared_ptr<T> &operator[](std::size_t idx) {
124 assert(0 <= idx && idx < (Dims * ...));
125 return data_[idx];
126 }
127
129 inline const T &operator()(std::size_t idx) const {
130 assert(0 <= idx && idx < (Dims * ...));
131 return *data_[idx];
132 }
133
135 inline T &operator()(std::size_t idx) {
136 assert(0 <= idx && idx < (Dims * ...));
137 return *data_[idx];
138 }
139
141 template <typename Data> inline T &set(std::size_t idx, Data &&data) {
142 assert(0 <= idx && idx < (Dims * ...));
143 data_[idx] = make_shared<Data>(std::forward<Data>(data));
144 return *data_[idx];
145 }
146
148 inline virtual void
149 pretty_print(std::ostream &os = Log(log::info)) const noexcept = 0;
150};
151
153template <typename T, std::size_t... Dims>
154inline std::ostream &operator<<(std::ostream &os,
155 const BlockTensorCore<T, Dims...> &obj) {
156 obj.pretty_print(os);
157 return os;
158}
159
161template <typename T, std::size_t Rows>
162class BlockTensor<T, Rows> : public BlockTensorCore<T, Rows> {
163private:
165
166public:
167 using BlockTensorCore<T, Rows>::BlockTensorCore;
168
170 inline static constexpr std::size_t rows() { return Rows; }
171
173 inline virtual void
174 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
175 os << Base::name() << "\n";
176 for (std::size_t row = 0; row < Rows; ++row)
177 os << "[" << row << "] = \n" << *Base::data_[row] << "\n";
178 }
179};
180
186template <typename T, std::size_t Rows, std::size_t Cols>
187class BlockTensor<T, Rows, Cols> : public BlockTensorCore<T, Rows, Cols> {
188private:
190
191public:
192 using BlockTensorCore<T, Rows, Cols>::BlockTensorCore;
193
195 inline static constexpr std::size_t rows() { return Rows; }
196
198 inline static constexpr std::size_t cols() { return Cols; }
199
200 using Base::operator();
201
203 inline const T &operator()(std::size_t row, std::size_t col) const {
204 assert(0 <= row && row < Rows && 0 <= col && col < Cols);
205 return *Base::data_[Cols * row + col];
206 }
207
209 inline T &operator()(std::size_t row, std::size_t col) {
210 assert(0 <= row && row < Rows && 0 <= col && col < Cols);
211 return *Base::data_[Cols * row + col];
212 }
213
214 using Base::set;
215
217 template <typename D>
218 inline T &set(std::size_t row, std::size_t col, D &&data) {
219 assert(0 <= row && row < Rows && 0 <= col && col < Cols);
220 Base::data_[Cols * row + col] = make_shared<D>(std::forward<D>(data));
221 return *Base::data_[Cols * row + col];
222 }
223
225 inline auto tr() const {
227 for (std::size_t row = 0; row < Rows; ++row)
228 for (std::size_t col = 0; col < Cols; ++col)
229 result[Rows * col + row] = Base::data_[Cols * row + col];
230 return result;
231 }
232
236
237 inline auto det() const {
238 if constexpr (Rows == 1 && Cols == 1) {
239 auto result = *Base::data_[0];
240 return result;
241 } else if constexpr (Rows == 2 && Cols == 2) {
242 auto result = torch::mul(*Base::data_[0], *Base::data_[3]) -
243 torch::mul(*Base::data_[1], *Base::data_[2]);
244 return result;
245 } else if constexpr (Rows == 3 && Cols == 3) {
246 auto result =
247 torch::mul(*Base::data_[0],
248 torch::mul(*Base::data_[4], *Base::data_[8]) -
249 torch::mul(*Base::data_[5], *Base::data_[7])) -
250 torch::mul(*Base::data_[1],
251 torch::mul(*Base::data_[3], *Base::data_[8]) -
252 torch::mul(*Base::data_[5], *Base::data_[6])) +
253 torch::mul(*Base::data_[2],
254 torch::mul(*Base::data_[3], *Base::data_[7]) -
255 torch::mul(*Base::data_[4], *Base::data_[6]));
256 return result;
257 } else if constexpr (Rows == 4 && Cols == 4) {
258 auto a11 = torch::mul(*Base::data_[5],
259 (torch::mul(*Base::data_[10], *Base::data_[15]) -
260 torch::mul(*Base::data_[11], *Base::data_[14]))) -
261 torch::mul(*Base::data_[9],
262 (torch::mul(*Base::data_[6], *Base::data_[15]) -
263 torch::mul(*Base::data_[7], *Base::data_[14]))) -
264 torch::mul(*Base::data_[13],
265 (torch::mul(*Base::data_[7], *Base::data_[10]) -
266 torch::mul(*Base::data_[6], *Base::data_[11])));
267
268 auto a21 = torch::mul(*Base::data_[4],
269 (torch::mul(*Base::data_[11], *Base::data_[14]) -
270 torch::mul(*Base::data_[10], *Base::data_[15]))) -
271 torch::mul(*Base::data_[8],
272 (torch::mul(*Base::data_[7], *Base::data_[14]) -
273 torch::mul(*Base::data_[6], *Base::data_[15]))) -
274 torch::mul(*Base::data_[12],
275 (torch::mul(*Base::data_[6], *Base::data_[11]) -
276 torch::mul(*Base::data_[7], *Base::data_[10])));
277
278 auto a31 = torch::mul(*Base::data_[4],
279 (torch::mul(*Base::data_[9], *Base::data_[15]) -
280 torch::mul(*Base::data_[11], *Base::data_[13]))) -
281 torch::mul(*Base::data_[8],
282 (torch::mul(*Base::data_[5], *Base::data_[15]) -
283 torch::mul(*Base::data_[7], *Base::data_[13]))) -
284 torch::mul(*Base::data_[12],
285 (torch::mul(*Base::data_[7], *Base::data_[9]) -
286 torch::mul(*Base::data_[5], *Base::data_[11])));
287
288 auto a41 = torch::mul(*Base::data_[4],
289 (torch::mul(*Base::data_[10], *Base::data_[13]) -
290 torch::mul(*Base::data_[9], *Base::data_[14]))) -
291 torch::mul(*Base::data_[8],
292 (torch::mul(*Base::data_[6], *Base::data_[13]) -
293 torch::mul(*Base::data_[5], *Base::data_[14]))) -
294 torch::mul(*Base::data_[12],
295 (torch::mul(*Base::data_[5], *Base::data_[10]) -
296 torch::mul(*Base::data_[6], *Base::data_[9])));
297
298 auto result =
299 torch::mul(*Base::data_[0], a11) + torch::mul(*Base::data_[1], a21) +
300 torch::mul(*Base::data_[2], a31) + torch::mul(*Base::data_[3], a41);
301
302 return result;
303 } else {
304 throw std::runtime_error("Unsupported block tensor dimension");
305 return *this;
306 }
307 }
308
312 inline auto inv() const {
313
314 auto det_ = this->det();
315
316 if constexpr (Rows == 1 && Cols == 1) {
318 result[0] = std::make_shared<T>(torch::reciprocal(*Base::data_[0]));
319 return result;
320 } else if constexpr (Rows == 2 && Cols == 2) {
321
323 result[0] = std::make_shared<T>(torch::div(*Base::data_[3], det_));
324 result[1] = std::make_shared<T>(torch::div(*Base::data_[2], -det_));
325 result[2] = std::make_shared<T>(torch::div(*Base::data_[1], -det_));
326 result[3] = std::make_shared<T>(torch::div(*Base::data_[0], det_));
327 return result;
328 } else if constexpr (Rows == 3 && Cols == 3) {
329
330 auto a11 = torch::mul(*Base::data_[4], *Base::data_[8]) -
331 torch::mul(*Base::data_[5], *Base::data_[7]);
332 auto a12 = torch::mul(*Base::data_[2], *Base::data_[7]) -
333 torch::mul(*Base::data_[1], *Base::data_[8]);
334 auto a13 = torch::mul(*Base::data_[1], *Base::data_[5]) -
335 torch::mul(*Base::data_[2], *Base::data_[4]);
336 auto a21 = torch::mul(*Base::data_[5], *Base::data_[6]) -
337 torch::mul(*Base::data_[3], *Base::data_[8]);
338 auto a22 = torch::mul(*Base::data_[0], *Base::data_[8]) -
339 torch::mul(*Base::data_[2], *Base::data_[6]);
340 auto a23 = torch::mul(*Base::data_[2], *Base::data_[3]) -
341 torch::mul(*Base::data_[0], *Base::data_[5]);
342 auto a31 = torch::mul(*Base::data_[3], *Base::data_[7]) -
343 torch::mul(*Base::data_[4], *Base::data_[6]);
344 auto a32 = torch::mul(*Base::data_[1], *Base::data_[6]) -
345 torch::mul(*Base::data_[0], *Base::data_[7]);
346 auto a33 = torch::mul(*Base::data_[0], *Base::data_[4]) -
347 torch::mul(*Base::data_[1], *Base::data_[3]);
348
350 result[0] = std::make_shared<T>(torch::div(a11, det_));
351 result[1] = std::make_shared<T>(torch::div(a12, det_));
352 result[2] = std::make_shared<T>(torch::div(a13, det_));
353 result[3] = std::make_shared<T>(torch::div(a21, det_));
354 result[4] = std::make_shared<T>(torch::div(a22, det_));
355 result[5] = std::make_shared<T>(torch::div(a23, det_));
356 result[6] = std::make_shared<T>(torch::div(a31, det_));
357 result[7] = std::make_shared<T>(torch::div(a32, det_));
358 result[8] = std::make_shared<T>(torch::div(a33, det_));
359 return result;
360 } else if constexpr (Rows == 4 && Cols == 4) {
361 auto a11 = torch::mul(*Base::data_[5],
362 (torch::mul(*Base::data_[10], *Base::data_[15]) -
363 torch::mul(*Base::data_[11], *Base::data_[14]))) -
364 torch::mul(*Base::data_[9],
365 (torch::mul(*Base::data_[6], *Base::data_[15]) -
366 torch::mul(*Base::data_[7], *Base::data_[14]))) -
367 torch::mul(*Base::data_[13],
368 (torch::mul(*Base::data_[7], *Base::data_[10]) -
369 torch::mul(*Base::data_[6], *Base::data_[11])));
370
371 auto a12 = torch::mul(*Base::data_[1],
372 (torch::mul(*Base::data_[11], *Base::data_[14]) -
373 torch::mul(*Base::data_[10], *Base::data_[15]))) -
374 torch::mul(*Base::data_[9],
375 (torch::mul(*Base::data_[3], *Base::data_[14]) -
376 torch::mul(*Base::data_[2], *Base::data_[15]))) -
377 torch::mul(*Base::data_[13],
378 (torch::mul(*Base::data_[2], *Base::data_[11]) -
379 torch::mul(*Base::data_[3], *Base::data_[10])));
380
381 auto a13 = torch::mul(*Base::data_[1],
382 (torch::mul(*Base::data_[6], *Base::data_[15]) -
383 torch::mul(*Base::data_[7], *Base::data_[14]))) -
384 torch::mul(*Base::data_[5],
385 (torch::mul(*Base::data_[2], *Base::data_[15]) -
386 torch::mul(*Base::data_[3], *Base::data_[14]))) -
387 torch::mul(*Base::data_[13],
388 (torch::mul(*Base::data_[3], *Base::data_[6]) -
389 torch::mul(*Base::data_[2], *Base::data_[7])));
390
391 auto a14 = torch::mul(*Base::data_[1],
392 (torch::mul(*Base::data_[7], *Base::data_[10]) -
393 torch::mul(*Base::data_[6], *Base::data_[11]))) -
394 torch::mul(*Base::data_[5],
395 (torch::mul(*Base::data_[3], *Base::data_[10]) -
396 torch::mul(*Base::data_[2], *Base::data_[11]))) -
397 torch::mul(*Base::data_[9],
398 (torch::mul(*Base::data_[2], *Base::data_[7]) -
399 torch::mul(*Base::data_[3], *Base::data_[6])));
400
401 auto a21 = torch::mul(*Base::data_[4],
402 (torch::mul(*Base::data_[11], *Base::data_[14]) -
403 torch::mul(*Base::data_[10], *Base::data_[15]))) -
404 torch::mul(*Base::data_[8],
405 (torch::mul(*Base::data_[7], *Base::data_[14]) -
406 torch::mul(*Base::data_[6], *Base::data_[15]))) -
407 torch::mul(*Base::data_[12],
408 (torch::mul(*Base::data_[6], *Base::data_[11]) -
409 torch::mul(*Base::data_[7], *Base::data_[10])));
410
411 auto a22 = torch::mul(*Base::data_[0],
412 (torch::mul(*Base::data_[10], *Base::data_[15]) -
413 torch::mul(*Base::data_[11], *Base::data_[14]))) -
414 torch::mul(*Base::data_[8],
415 (torch::mul(*Base::data_[2], *Base::data_[15]) -
416 torch::mul(*Base::data_[3], *Base::data_[14]))) -
417 torch::mul(*Base::data_[12],
418 (torch::mul(*Base::data_[3], *Base::data_[10]) -
419 torch::mul(*Base::data_[2], *Base::data_[11])));
420
421 auto a23 = torch::mul(*Base::data_[0],
422 (torch::mul(*Base::data_[7], *Base::data_[14]) -
423 torch::mul(*Base::data_[6], *Base::data_[15]))) -
424 torch::mul(*Base::data_[4],
425 (torch::mul(*Base::data_[3], *Base::data_[14]) -
426 torch::mul(*Base::data_[2], *Base::data_[15]))) -
427 torch::mul(*Base::data_[12],
428 (torch::mul(*Base::data_[2], *Base::data_[7]) -
429 torch::mul(*Base::data_[3], *Base::data_[6])));
430
431 auto a24 = torch::mul(*Base::data_[0],
432 (torch::mul(*Base::data_[6], *Base::data_[11]) -
433 torch::mul(*Base::data_[7], *Base::data_[10]))) -
434 torch::mul(*Base::data_[4],
435 (torch::mul(*Base::data_[2], *Base::data_[11]) -
436 torch::mul(*Base::data_[3], *Base::data_[10]))) -
437 torch::mul(*Base::data_[8],
438 (torch::mul(*Base::data_[3], *Base::data_[6]) -
439 torch::mul(*Base::data_[2], *Base::data_[7])));
440
441 auto a31 = torch::mul(*Base::data_[4],
442 (torch::mul(*Base::data_[9], *Base::data_[15]) -
443 torch::mul(*Base::data_[11], *Base::data_[13]))) -
444 torch::mul(*Base::data_[8],
445 (torch::mul(*Base::data_[5], *Base::data_[15]) -
446 torch::mul(*Base::data_[7], *Base::data_[13]))) -
447 torch::mul(*Base::data_[12],
448 (torch::mul(*Base::data_[7], *Base::data_[9]) -
449 torch::mul(*Base::data_[5], *Base::data_[11])));
450
451 auto a32 = torch::mul(*Base::data_[0],
452 (torch::mul(*Base::data_[11], *Base::data_[13]) -
453 torch::mul(*Base::data_[9], *Base::data_[15]))) -
454 torch::mul(*Base::data_[8],
455 (torch::mul(*Base::data_[3], *Base::data_[13]) -
456 torch::mul(*Base::data_[1], *Base::data_[15]))) -
457 torch::mul(*Base::data_[12],
458 (torch::mul(*Base::data_[1], *Base::data_[11]) -
459 torch::mul(*Base::data_[3], *Base::data_[9])));
460
461 auto a33 = torch::mul(*Base::data_[0],
462 (torch::mul(*Base::data_[5], *Base::data_[15]) -
463 torch::mul(*Base::data_[7], *Base::data_[13]))) -
464 torch::mul(*Base::data_[4],
465 (torch::mul(*Base::data_[1], *Base::data_[15]) -
466 torch::mul(*Base::data_[3], *Base::data_[13]))) -
467 torch::mul(*Base::data_[12],
468 (torch::mul(*Base::data_[3], *Base::data_[5]) -
469 torch::mul(*Base::data_[1], *Base::data_[7])));
470
471 auto a34 = torch::mul(*Base::data_[0],
472 (torch::mul(*Base::data_[7], *Base::data_[9]) -
473 torch::mul(*Base::data_[5], *Base::data_[11]))) -
474 torch::mul(*Base::data_[4],
475 (torch::mul(*Base::data_[3], *Base::data_[9]) -
476 torch::mul(*Base::data_[1], *Base::data_[11]))) -
477 torch::mul(*Base::data_[8],
478 (torch::mul(*Base::data_[1], *Base::data_[7]) -
479 torch::mul(*Base::data_[3], *Base::data_[5])));
480
481 auto a41 = torch::mul(*Base::data_[4],
482 (torch::mul(*Base::data_[10], *Base::data_[13]) -
483 torch::mul(*Base::data_[9], *Base::data_[14]))) -
484 torch::mul(*Base::data_[8],
485 (torch::mul(*Base::data_[6], *Base::data_[13]) -
486 torch::mul(*Base::data_[5], *Base::data_[14]))) -
487 torch::mul(*Base::data_[12],
488 (torch::mul(*Base::data_[5], *Base::data_[10]) -
489 torch::mul(*Base::data_[6], *Base::data_[9])));
490
491 auto a42 = torch::mul(*Base::data_[0],
492 (torch::mul(*Base::data_[9], *Base::data_[14]) -
493 torch::mul(*Base::data_[10], *Base::data_[13]))) -
494 torch::mul(*Base::data_[8],
495 (torch::mul(*Base::data_[1], *Base::data_[14]) -
496 torch::mul(*Base::data_[2], *Base::data_[13]))) -
497 torch::mul(*Base::data_[12],
498 (torch::mul(*Base::data_[2], *Base::data_[9]) -
499 torch::mul(*Base::data_[1], *Base::data_[10])));
500
501 auto a43 = torch::mul(*Base::data_[0],
502 (torch::mul(*Base::data_[6], *Base::data_[13]) -
503 torch::mul(*Base::data_[5], *Base::data_[14]))) -
504 torch::mul(*Base::data_[4],
505 (torch::mul(*Base::data_[2], *Base::data_[13]) -
506 torch::mul(*Base::data_[1], *Base::data_[14]))) -
507 torch::mul(*Base::data_[12],
508 (torch::mul(*Base::data_[1], *Base::data_[6]) -
509 torch::mul(*Base::data_[2], *Base::data_[5])));
510
511 auto a44 = torch::mul(*Base::data_[0],
512 (torch::mul(*Base::data_[5], *Base::data_[10]) -
513 torch::mul(*Base::data_[6], *Base::data_[9]))) -
514 torch::mul(*Base::data_[4],
515 (torch::mul(*Base::data_[1], *Base::data_[10]) -
516 torch::mul(*Base::data_[2], *Base::data_[9]))) -
517 torch::mul(*Base::data_[8],
518 (torch::mul(*Base::data_[2], *Base::data_[5]) -
519 torch::mul(*Base::data_[1], *Base::data_[6])));
521 result[0] = std::make_shared<T>(torch::div(a11, det_));
522 result[1] = std::make_shared<T>(torch::div(a12, det_));
523 result[2] = std::make_shared<T>(torch::div(a13, det_));
524 result[3] = std::make_shared<T>(torch::div(a14, det_));
525 result[4] = std::make_shared<T>(torch::div(a21, det_));
526 result[5] = std::make_shared<T>(torch::div(a22, det_));
527 result[6] = std::make_shared<T>(torch::div(a23, det_));
528 result[7] = std::make_shared<T>(torch::div(a24, det_));
529 result[8] = std::make_shared<T>(torch::div(a31, det_));
530 result[9] = std::make_shared<T>(torch::div(a32, det_));
531 result[10] = std::make_shared<T>(torch::div(a33, det_));
532 result[11] = std::make_shared<T>(torch::div(a34, det_));
533 result[12] = std::make_shared<T>(torch::div(a41, det_));
534 result[13] = std::make_shared<T>(torch::div(a42, det_));
535 result[14] = std::make_shared<T>(torch::div(a43, det_));
536 result[15] = std::make_shared<T>(torch::div(a44, det_));
537 return result;
538 } else {
539 throw std::runtime_error("Unsupported block tensor dimension");
540 return *this;
541 }
542 }
543
551 inline auto ginv() const {
552 if constexpr (Rows == Cols)
553 return this->inv();
554 else
555 // Compute the generalized inverse, i.e. (A^T A)^{-1} A^T
556 return (this->tr() * (*this)).inv() * this->tr();
557 }
558
564 inline auto invtr() const {
565
566 auto det_ = this->det();
567
568 if constexpr (Rows == 1 && Cols == 1) {
570 result[0] = std::make_shared<T>(torch::reciprocal(*Base::data_[0]));
571 return result;
572 } else if constexpr (Rows == 2 && Cols == 2) {
573
575 result[0] = std::make_shared<T>(torch::div(*Base::data_[3], det_));
576 result[1] = std::make_shared<T>(torch::div(*Base::data_[1], -det_));
577 result[2] = std::make_shared<T>(torch::div(*Base::data_[2], -det_));
578 result[3] = std::make_shared<T>(torch::div(*Base::data_[0], det_));
579 return result;
580 } else if constexpr (Rows == 3 && Cols == 3) {
581
582 auto a11 = torch::mul(*Base::data_[4], *Base::data_[8]) -
583 torch::mul(*Base::data_[5], *Base::data_[7]);
584 auto a12 = torch::mul(*Base::data_[2], *Base::data_[7]) -
585 torch::mul(*Base::data_[1], *Base::data_[8]);
586 auto a13 = torch::mul(*Base::data_[1], *Base::data_[5]) -
587 torch::mul(*Base::data_[2], *Base::data_[4]);
588 auto a21 = torch::mul(*Base::data_[5], *Base::data_[6]) -
589 torch::mul(*Base::data_[3], *Base::data_[8]);
590 auto a22 = torch::mul(*Base::data_[0], *Base::data_[8]) -
591 torch::mul(*Base::data_[2], *Base::data_[6]);
592 auto a23 = torch::mul(*Base::data_[2], *Base::data_[3]) -
593 torch::mul(*Base::data_[0], *Base::data_[5]);
594 auto a31 = torch::mul(*Base::data_[3], *Base::data_[7]) -
595 torch::mul(*Base::data_[4], *Base::data_[6]);
596 auto a32 = torch::mul(*Base::data_[1], *Base::data_[6]) -
597 torch::mul(*Base::data_[0], *Base::data_[7]);
598 auto a33 = torch::mul(*Base::data_[0], *Base::data_[4]) -
599 torch::mul(*Base::data_[1], *Base::data_[3]);
600
602 result[0] = std::make_shared<T>(torch::div(a11, det_));
603 result[1] = std::make_shared<T>(torch::div(a21, det_));
604 result[2] = std::make_shared<T>(torch::div(a31, det_));
605 result[3] = std::make_shared<T>(torch::div(a12, det_));
606 result[4] = std::make_shared<T>(torch::div(a22, det_));
607 result[5] = std::make_shared<T>(torch::div(a32, det_));
608 result[6] = std::make_shared<T>(torch::div(a13, det_));
609 result[7] = std::make_shared<T>(torch::div(a23, det_));
610 result[8] = std::make_shared<T>(torch::div(a33, det_));
611 return result;
612 } else if constexpr (Rows == 4 && Cols == 4) {
613
614 auto a11 = torch::mul(*Base::data_[5],
615 (torch::mul(*Base::data_[10], *Base::data_[15]) -
616 torch::mul(*Base::data_[11], *Base::data_[14]))) -
617 torch::mul(*Base::data_[9],
618 (torch::mul(*Base::data_[6], *Base::data_[15]) -
619 torch::mul(*Base::data_[7], *Base::data_[14]))) -
620 torch::mul(*Base::data_[13],
621 (torch::mul(*Base::data_[7], *Base::data_[10]) -
622 torch::mul(*Base::data_[6], *Base::data_[11])));
623
624 auto a12 = torch::mul(*Base::data_[1],
625 (torch::mul(*Base::data_[11], *Base::data_[14]) -
626 torch::mul(*Base::data_[10], *Base::data_[15]))) -
627 torch::mul(*Base::data_[9],
628 (torch::mul(*Base::data_[3], *Base::data_[14]) -
629 torch::mul(*Base::data_[2], *Base::data_[15]))) -
630 torch::mul(*Base::data_[13],
631 (torch::mul(*Base::data_[2], *Base::data_[11]) -
632 torch::mul(*Base::data_[3], *Base::data_[10])));
633
634 auto a13 = torch::mul(*Base::data_[1],
635 (torch::mul(*Base::data_[6], *Base::data_[15]) -
636 torch::mul(*Base::data_[7], *Base::data_[14]))) -
637 torch::mul(*Base::data_[5],
638 (torch::mul(*Base::data_[2], *Base::data_[15]) -
639 torch::mul(*Base::data_[3], *Base::data_[14]))) -
640 torch::mul(*Base::data_[13],
641 (torch::mul(*Base::data_[3], *Base::data_[6]) -
642 torch::mul(*Base::data_[2], *Base::data_[7])));
643
644 auto a14 = torch::mul(*Base::data_[1],
645 (torch::mul(*Base::data_[7], *Base::data_[10]) -
646 torch::mul(*Base::data_[6], *Base::data_[11]))) -
647 torch::mul(*Base::data_[5],
648 (torch::mul(*Base::data_[3], *Base::data_[10]) -
649 torch::mul(*Base::data_[2], *Base::data_[11]))) -
650 torch::mul(*Base::data_[9],
651 (torch::mul(*Base::data_[2], *Base::data_[7]) -
652 torch::mul(*Base::data_[3], *Base::data_[6])));
653
654 auto a21 = torch::mul(*Base::data_[4],
655 (torch::mul(*Base::data_[11], *Base::data_[14]) -
656 torch::mul(*Base::data_[10], *Base::data_[15]))) -
657 torch::mul(*Base::data_[8],
658 (torch::mul(*Base::data_[7], *Base::data_[14]) -
659 torch::mul(*Base::data_[6], *Base::data_[15]))) -
660 torch::mul(*Base::data_[12],
661 (torch::mul(*Base::data_[6], *Base::data_[11]) -
662 torch::mul(*Base::data_[7], *Base::data_[10])));
663
664 auto a22 = torch::mul(*Base::data_[0],
665 (torch::mul(*Base::data_[10], *Base::data_[15]) -
666 torch::mul(*Base::data_[11], *Base::data_[14]))) -
667 torch::mul(*Base::data_[8],
668 (torch::mul(*Base::data_[2], *Base::data_[15]) -
669 torch::mul(*Base::data_[3], *Base::data_[14]))) -
670 torch::mul(*Base::data_[12],
671 (torch::mul(*Base::data_[3], *Base::data_[10]) -
672 torch::mul(*Base::data_[2], *Base::data_[11])));
673
674 auto a23 = torch::mul(*Base::data_[0],
675 (torch::mul(*Base::data_[7], *Base::data_[14]) -
676 torch::mul(*Base::data_[6], *Base::data_[15]))) -
677 torch::mul(*Base::data_[4],
678 (torch::mul(*Base::data_[3], *Base::data_[14]) -
679 torch::mul(*Base::data_[2], *Base::data_[15]))) -
680 torch::mul(*Base::data_[12],
681 (torch::mul(*Base::data_[2], *Base::data_[7]) -
682 torch::mul(*Base::data_[3], *Base::data_[6])));
683
684 auto a24 = torch::mul(*Base::data_[0],
685 (torch::mul(*Base::data_[6], *Base::data_[11]) -
686 torch::mul(*Base::data_[7], *Base::data_[10]))) -
687 torch::mul(*Base::data_[4],
688 (torch::mul(*Base::data_[2], *Base::data_[11]) -
689 torch::mul(*Base::data_[3], *Base::data_[10]))) -
690 torch::mul(*Base::data_[8],
691 (torch::mul(*Base::data_[3], *Base::data_[6]) -
692 torch::mul(*Base::data_[2], *Base::data_[7])));
693
694 auto a31 = torch::mul(*Base::data_[4],
695 (torch::mul(*Base::data_[9], *Base::data_[15]) -
696 torch::mul(*Base::data_[11], *Base::data_[13]))) -
697 torch::mul(*Base::data_[8],
698 (torch::mul(*Base::data_[5], *Base::data_[15]) -
699 torch::mul(*Base::data_[7], *Base::data_[13]))) -
700 torch::mul(*Base::data_[12],
701 (torch::mul(*Base::data_[7], *Base::data_[9]) -
702 torch::mul(*Base::data_[5], *Base::data_[11])));
703
704 auto a32 = torch::mul(*Base::data_[0],
705 (torch::mul(*Base::data_[11], *Base::data_[13]) -
706 torch::mul(*Base::data_[9], *Base::data_[15]))) -
707 torch::mul(*Base::data_[8],
708 (torch::mul(*Base::data_[3], *Base::data_[13]) -
709 torch::mul(*Base::data_[1], *Base::data_[15]))) -
710 torch::mul(*Base::data_[12],
711 (torch::mul(*Base::data_[1], *Base::data_[11]) -
712 torch::mul(*Base::data_[3], *Base::data_[9])));
713
714 auto a33 = torch::mul(*Base::data_[0],
715 (torch::mul(*Base::data_[5], *Base::data_[15]) -
716 torch::mul(*Base::data_[7], *Base::data_[13]))) -
717 torch::mul(*Base::data_[4],
718 (torch::mul(*Base::data_[1], *Base::data_[15]) -
719 torch::mul(*Base::data_[3], *Base::data_[13]))) -
720 torch::mul(*Base::data_[12],
721 (torch::mul(*Base::data_[3], *Base::data_[5]) -
722 torch::mul(*Base::data_[1], *Base::data_[7])));
723
724 auto a34 = torch::mul(*Base::data_[0],
725 (torch::mul(*Base::data_[7], *Base::data_[9]) -
726 torch::mul(*Base::data_[5], *Base::data_[11]))) -
727 torch::mul(*Base::data_[4],
728 (torch::mul(*Base::data_[3], *Base::data_[9]) -
729 torch::mul(*Base::data_[1], *Base::data_[11]))) -
730 torch::mul(*Base::data_[8],
731 (torch::mul(*Base::data_[1], *Base::data_[7]) -
732 torch::mul(*Base::data_[3], *Base::data_[5])));
733
734 auto a41 = torch::mul(*Base::data_[4],
735 (torch::mul(*Base::data_[10], *Base::data_[13]) -
736 torch::mul(*Base::data_[9], *Base::data_[14]))) -
737 torch::mul(*Base::data_[8],
738 (torch::mul(*Base::data_[6], *Base::data_[13]) -
739 torch::mul(*Base::data_[5], *Base::data_[14]))) -
740 torch::mul(*Base::data_[12],
741 (torch::mul(*Base::data_[5], *Base::data_[10]) -
742 torch::mul(*Base::data_[6], *Base::data_[9])));
743
744 auto a42 = torch::mul(*Base::data_[0],
745 (torch::mul(*Base::data_[9], *Base::data_[14]) -
746 torch::mul(*Base::data_[10], *Base::data_[13]))) -
747 torch::mul(*Base::data_[8],
748 (torch::mul(*Base::data_[1], *Base::data_[14]) -
749 torch::mul(*Base::data_[2], *Base::data_[13]))) -
750 torch::mul(*Base::data_[12],
751 (torch::mul(*Base::data_[2], *Base::data_[9]) -
752 torch::mul(*Base::data_[1], *Base::data_[10])));
753
754 auto a43 = torch::mul(*Base::data_[0],
755 (torch::mul(*Base::data_[6], *Base::data_[13]) -
756 torch::mul(*Base::data_[5], *Base::data_[14]))) -
757 torch::mul(*Base::data_[4],
758 (torch::mul(*Base::data_[2], *Base::data_[13]) -
759 torch::mul(*Base::data_[1], *Base::data_[14]))) -
760 torch::mul(*Base::data_[12],
761 (torch::mul(*Base::data_[1], *Base::data_[6]) -
762 torch::mul(*Base::data_[2], *Base::data_[5])));
763
764 auto a44 = torch::mul(*Base::data_[0],
765 (torch::mul(*Base::data_[5], *Base::data_[10]) -
766 torch::mul(*Base::data_[6], *Base::data_[9]))) -
767 torch::mul(*Base::data_[4],
768 (torch::mul(*Base::data_[1], *Base::data_[10]) -
769 torch::mul(*Base::data_[2], *Base::data_[9]))) -
770 torch::mul(*Base::data_[8],
771 (torch::mul(*Base::data_[2], *Base::data_[5]) -
772 torch::mul(*Base::data_[1], *Base::data_[6])));
773
775 result[0] = std::make_shared<T>(torch::div(a11, det_));
776 result[1] = std::make_shared<T>(torch::div(a21, det_));
777 result[2] = std::make_shared<T>(torch::div(a31, det_));
778 result[3] = std::make_shared<T>(torch::div(a41, det_));
779 result[4] = std::make_shared<T>(torch::div(a12, det_));
780 result[5] = std::make_shared<T>(torch::div(a22, det_));
781 result[6] = std::make_shared<T>(torch::div(a32, det_));
782 result[7] = std::make_shared<T>(torch::div(a42, det_));
783 result[8] = std::make_shared<T>(torch::div(a13, det_));
784 result[9] = std::make_shared<T>(torch::div(a23, det_));
785 result[10] = std::make_shared<T>(torch::div(a33, det_));
786 result[11] = std::make_shared<T>(torch::div(a43, det_));
787 result[12] = std::make_shared<T>(torch::div(a14, det_));
788 result[13] = std::make_shared<T>(torch::div(a24, det_));
789 result[14] = std::make_shared<T>(torch::div(a34, det_));
790 result[15] = std::make_shared<T>(torch::div(a44, det_));
791 return result;
792 } else {
793 throw std::runtime_error("Unsupported block tensor dimension");
794 return *this;
795 }
796 }
797
807 inline auto ginvtr() const {
808 if constexpr (Rows == Cols)
809 return this->invtr();
810 else
811 // Compute the transpose of the generalized inverse, i.e. A (A^T A)^{-T}
812 return (*this) * (this->tr() * (*this)).invtr();
813 }
814
816 inline auto trace() const {
817 static_assert(Rows == Cols, "trace(.) requires square block tensor");
818
819 if constexpr (Rows == 1)
820 return BlockTensor<T, 1, 1>(*Base::data_[0]);
821
822 else if constexpr (Rows == 2)
823 return BlockTensor<T, 1, 1>(*Base::data_[0] + *Base::data_[3]);
824
825 else if constexpr (Rows == 3)
826 return BlockTensor<T, 1, 1>(*Base::data_[0] + *Base::data_[4] +
827 *Base::data_[8]);
828
829 else if constexpr (Rows == 4)
830 return BlockTensor<T, 1, 1>(*Base::data_[0] + *Base::data_[5] +
831 *Base::data_[10] + *Base::data_[15]);
832
833 else
834 throw std::runtime_error("Unsupported block tensor dimension");
835 }
836
837private:
839 template <std::size_t... Is>
840 inline auto norm_(std::index_sequence<Is...>) const {
841 return torch::sqrt(std::apply([](const auto&... tensors) {
842 return (tensors + ...);
843 }, std::make_tuple(std::get<Is>(Base::data_)->square()...)));
844 }
845
846public:
848 inline auto norm() const {
849 return BlockTensor<T, 1, 1>(std::make_shared<T>(norm_(std::make_index_sequence<Rows*Cols>{})));
850 }
851
852private:
854 template <std::size_t... Is>
855 inline auto normalize_(std::index_sequence<Is...> is) const {
856 auto n_ = norm_(is);
857 return BlockTensor<T, Rows, Cols>(std::make_shared<T>(*std::get<Is>(Base::data_)/n_)...);
858 }
859
860public:
862 inline auto normalize() const {
863 return normalize_(std::make_index_sequence<Rows*Cols>{});
864 }
865
866private:
868 template <std::size_t... Is>
869 inline auto dot_(std::index_sequence<Is...>, const BlockTensor<T, Rows, Cols> &other) const {
870 return std::apply([](const auto&... tensors) {
871 return (tensors + ...);
872 }, std::make_tuple(torch::mul(*std::get<Is>(Base::data_), *std::get<Is>(other.data_))...));
873 }
874
875public:
877 inline auto dot(const BlockTensor<T, Rows, Cols> & other) const {
878 return BlockTensor<T, 1, 1>(std::make_shared<T>(dot_(std::make_index_sequence<Rows*Cols>{}, other)));
879 }
880
882 inline virtual void
883 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
884 os << Base::name() << "\n";
885 for (std::size_t row = 0; row < Rows; ++row)
886 for (std::size_t col = 0; col < Cols; ++col)
887 os << "[" << row << "," << col << "] = \n"
888 << *Base::data_[Cols * row + col] << "\n";
889 }
890};
891
894template <typename T, typename U, std::size_t Rows, std::size_t Common,
895 std::size_t Cols>
897 const BlockTensor<U, Common, Cols> &rhs) {
899 for (std::size_t row = 0; row < Rows; ++row)
900 for (std::size_t col = 0; col < Cols; ++col) {
901 T tmp =
902 (lhs[Common * row]->dim() > rhs[col]->dim()
903 ? torch::mul(*lhs[Common * row], rhs[col]->unsqueeze(-1))
904 : (lhs[Common * row]->dim() < rhs[col]->dim()
905 ? torch::mul(lhs[Common * row]->unsqueeze(-1), *rhs[col])
906 : torch::mul(*lhs[Common * row], *rhs[col])));
907 for (std::size_t idx = 1; idx < Common; ++idx)
908 tmp += (lhs[Common * row]->dim() > rhs[col]->dim()
909 ? torch::mul(*lhs[Common * row + idx],
910 rhs[Cols * idx + col]->unsqueeze(-1))
911 : (lhs[Common * row]->dim() < rhs[col]->dim()
912 ? torch::mul(lhs[Common * row + idx]->unsqueeze(-1),
913 *rhs[Cols * idx + col])
914 : torch::mul(*lhs[Common * row + idx],
915 *rhs[Cols * idx + col])));
916 result[Cols * row + col] = std::make_shared<T>(tmp);
917 }
918 return result;
919}
920
927template <typename T, std::size_t Rows, std::size_t Cols, std::size_t Slices>
928class BlockTensor<T, Rows, Cols, Slices>
929 : public BlockTensorCore<T, Rows, Cols, Slices> {
930private:
932
933public:
934 using BlockTensorCore<T, Rows, Cols, Slices>::BlockTensorCore;
935
937 inline static constexpr std::size_t rows() { return Rows; }
938
940 inline static constexpr std::size_t cols() { return Cols; }
941
943 inline static constexpr std::size_t slices() { return Slices; }
944
945 using Base::operator();
946
948 inline const T &operator()(std::size_t row, std::size_t col,
949 std::size_t slice) const {
950 assert(0 <= row && row < Rows && 0 <= col && col < Cols && 0 <= slice &&
951 slice < Slices);
952 return *Base::data_[Rows * Cols * slice + Cols * row + col];
953 }
954
956 inline T &operator()(std::size_t row, std::size_t col, std::size_t slice) {
957 assert(0 <= row && row < Rows && 0 <= col && col < Cols && 0 <= slice &&
958 slice < Slices);
959 return *Base::data_[Rows * Cols * slice + Cols * row + col];
960 }
961
962 using Base::set;
963
965 template <typename D>
966 inline T &set(std::size_t row, std::size_t col, std::size_t slice, D &&data) {
967 Base::data_[Rows * Cols * slice + Cols * row + col] =
968 make_shared<D>(std::forward<D>(data));
969 return *Base::data_[Rows * Cols * slice + Cols * row + col];
970 }
971
973 inline auto slice(std::size_t slice) const {
974 assert(0 <= slice && slice < Slices);
976 for (std::size_t row = 0; row < Rows; ++row)
977 for (std::size_t col = 0; col < Cols; ++col)
978 result[Cols * row + col] =
979 Base::data_[Rows * Cols * slice + Cols * row + col];
980 return result;
981 }
982
985 inline auto reorder_ikj() const {
987 for (std::size_t slice = 0; slice < Slices; ++slice)
988 for (std::size_t row = 0; row < Rows; ++row)
989 for (std::size_t col = 0; col < Cols; ++col)
990 result[Rows * Slices * col + Slices * row + slice] =
991 Base::data_[Rows * Cols * slice + Cols * row + col];
992 return result;
993 }
994
998 inline auto reorder_jik() const {
1000 for (std::size_t slice = 0; slice < Slices; ++slice)
1001 for (std::size_t row = 0; row < Rows; ++row)
1002 for (std::size_t col = 0; col < Cols; ++col)
1003 result[Rows * Cols * slice + Rows * col + row] =
1004 Base::data_[Rows * Cols * slice + Cols * row + col];
1005 return result;
1006 }
1007
1010 inline auto reorder_kji() const {
1012 for (std::size_t slice = 0; slice < Slices; ++slice)
1013 for (std::size_t row = 0; row < Rows; ++row)
1014 for (std::size_t col = 0; col < Cols; ++col)
1015 result[Slices * Cols * row + Cols * slice + col] =
1016 Base::data_[Rows * Cols * slice + Cols * row + col];
1017 return result;
1018 }
1019
1022 inline auto reorder_kij() const {
1024 for (std::size_t slice = 0; slice < Slices; ++slice)
1025 for (std::size_t row = 0; row < Rows; ++row)
1026 for (std::size_t col = 0; col < Cols; ++col)
1027 result[Slices * Rows * col + Rows * slice + row] =
1028 Base::data_[Rows * Cols * slice + Cols * row + col];
1029 return result;
1030 }
1031
1033 inline virtual void
1034 pretty_print(std::ostream &os = Log(log::info)) const noexcept override {
1035 os << Base::name() << "\n";
1036 for (std::size_t slice = 0; slice < Slices; ++slice)
1037 for (std::size_t row = 0; row < Rows; ++row)
1038 for (std::size_t col = 0; col < Cols; ++col)
1039 os << "[" << row << "," << col << "," << slice << "] = \n"
1040 << *Base::data_[Rows * Cols * slice + Cols * row + col] << "\n";
1041 }
1042};
1043
1046template <typename T, typename U, std::size_t Rows, std::size_t Common,
1047 std::size_t Cols, std::size_t Slices>
1050 BlockTensor<typename std::common_type<T, U>::type, Rows, Cols, Slices> result;
1051 for (std::size_t slice = 0; slice < Slices; ++slice)
1052 for (std::size_t row = 0; row < Rows; ++row)
1053 for (std::size_t col = 0; col < Cols; ++col) {
1054 T tmp =
1055 (lhs[Common * row]->dim() > rhs[Rows * Cols * slice + col]->dim()
1056 ? torch::mul(*lhs[Common * row],
1057 rhs[Rows * Cols * slice + col]->unsqueeze(-1))
1058 : (lhs[Common * row]->dim() <
1059 rhs[Rows * Cols * slice + col]->dim()
1060 ? torch::mul(lhs[Common * row]->unsqueeze(-1),
1061 *rhs[Rows * Cols * slice + col])
1062 : torch::mul(*lhs[Common * row],
1063 *rhs[Rows * Cols * slice + col])));
1064 for (std::size_t idx = 1; idx < Common; ++idx)
1065 tmp +=
1066 (lhs[Common * row]->dim() > rhs[Rows * Cols * slice + col]->dim()
1067 ? torch::mul(
1068 *lhs[Common * row + idx],
1069 rhs[Rows * Cols * slice + Cols * idx + col]->unsqueeze(
1070 -1))
1071 : (lhs[Common * row]->dim() <
1072 rhs[Rows * Cols * slice + col]->dim()
1073 ? torch::mul(
1074 lhs[Common * row + idx]->unsqueeze(-1),
1075 *rhs[Rows * Cols * slice + Cols * idx + col])
1076 : torch::mul(
1077 *lhs[Common * row + idx],
1078 *rhs[Rows * Cols * slice + Cols * idx + col])));
1079 result[Rows * Cols * slice + Cols * row + col] =
1080 std::make_shared<T>(tmp);
1081 }
1082 return result;
1083}
1084
1087template <typename T, typename U, std::size_t Rows, std::size_t Common,
1088 std::size_t Cols, std::size_t Slices>
1090 const BlockTensor<U, Common, Cols> &rhs) {
1091 BlockTensor<typename std::common_type<T, U>::type, Rows, Cols, Slices> result;
1092 for (std::size_t slice = 0; slice < Slices; ++slice)
1093 for (std::size_t row = 0; row < Rows; ++row)
1094 for (std::size_t col = 0; col < Cols; ++col) {
1095 T tmp =
1096 (lhs[Rows * Cols * slice + Common * row]->dim() > rhs[col]->dim()
1097 ? torch::mul(*lhs[Rows * Cols * slice + Common * row],
1098 rhs[col]->unsqueeze(-1))
1099 : (lhs[Rows * Cols * slice + Common * row]->dim() <
1100 rhs[col]->dim()
1101 ? torch::mul(lhs[Rows * Cols * slice + Common * row]
1102 ->unsqueeze(-1),
1103 *rhs[col])
1104 : torch::mul(*lhs[Rows * Cols * slice + Common * row],
1105 *rhs[col])));
1106 for (std::size_t idx = 1; idx < Common; ++idx)
1107 tmp +=
1108 (lhs[Rows * Cols * slice + Common * row + idx]->dim() >
1109 rhs[Cols * idx + col]->dim()
1110 ? torch::mul(*lhs[Rows * Cols * slice + Common * row + idx],
1111 rhs[Cols * idx + col])
1112 ->unsqueeze(-1)
1113 : (lhs[Rows * Cols * slice + Common * row + idx]->dim() <
1114 rhs[Cols * idx + col]->dim()
1115 ? torch::mul(
1116 lhs[Rows * Cols * slice + Common * row + idx]
1117 ->unsqueeze(-1),
1118 *rhs[Cols * idx + col])
1119 : torch::mul(
1120 *lhs[Rows * Cols * slice + Common * row + idx],
1121 *rhs[Cols * idx + col])));
1122 result[Rows * Cols * slice + Cols * row + col] =
1123 std::make_shared<T>(tmp);
1124 }
1125 return result;
1126}
1127
1128#define blocktensor_unary_op(name) \
1129 template <typename T, std::size_t... Dims> \
1130 inline auto name(const BlockTensor<T, Dims...> &input) { \
1131 BlockTensor<T, Dims...> result; \
1132 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) \
1133 result[idx] = std::make_shared<T>(torch::name(*input[idx])); \
1134 return result; \
1135 }
1136
1137#define blocktensor_unary_special_op(name) \
1138 template <typename T, std::size_t... Dims> \
1139 inline auto name(const BlockTensor<T, Dims...> &input) { \
1140 BlockTensor<T, Dims...> result; \
1141 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) \
1142 result[idx] = std::make_shared<T>(torch::special::name(*input[idx])); \
1143 return result; \
1144 }
1145
1146#define blocktensor_binary_op(name) \
1147 template <typename T, typename U, std::size_t... Dims> \
1148 inline auto name(const BlockTensor<T, Dims...> &input, \
1149 const BlockTensor<U, Dims...> &other) { \
1150 BlockTensor<typename std::common_type<T, U>::type, Dims...> result; \
1151 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) \
1152 result[idx] = \
1153 std::make_shared<T>(torch::name(*input[idx], *other[idx])); \
1154 return result; \
1155 }
1156
1157#define blocktensor_binary_special_op(name) \
1158 template <typename T, typename U, std::size_t... Dims> \
1159 inline auto name(const BlockTensor<T, Dims...> &input, \
1160 const BlockTensor<U, Dims...> &other) { \
1161 BlockTensor<typename std::common_type<T, U>::type, Dims...> result; \
1162 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) \
1163 result[idx] = \
1164 std::make_shared<T>(torch::special::name(*input[idx], *other[idx])); \
1165 return result; \
1166 }
1167
1171
1174
1178
1181
1185
1188
1191template <typename T, typename U, typename V, std::size_t... Dims>
1192inline auto add(const BlockTensor<T, Dims...> &input,
1193 const BlockTensor<U, Dims...> &other, V alpha = 1.0) {
1195 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1196 result[idx] =
1197 std::make_shared<T>(torch::add(*input[idx], *other[idx], alpha));
1198 return result;
1199}
1200
1203template <typename T, typename U, typename V, std::size_t... Dims>
1204inline auto add(const BlockTensor<T, Dims...> &input, U other, V alpha = 1.0) {
1205 BlockTensor<T, Dims...> result;
1206 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1207 result[idx] = std::make_shared<T>(torch::add(*input[idx], other, alpha));
1208 return result;
1209}
1210
1213template <typename T, typename U, typename V, std::size_t... Dims>
1214inline auto add(T input, const BlockTensor<U, Dims...> &other, V alpha = 1.0) {
1215 BlockTensor<U, Dims...> result;
1216 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1217 result[idx] = std::make_shared<T>(torch::add(input, *other[idx], alpha));
1218 return result;
1219}
1220
1224template <typename T, typename U, typename V, typename W, std::size_t... Dims>
1225inline auto addcdiv(const BlockTensor<T, Dims...> &input,
1226 const BlockTensor<U, Dims...> &tensor1,
1227 const BlockTensor<V, Dims...> &tensor2, W value = 1.0) {
1229 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1230 result[idx] = std::make_shared<T>(
1231 torch::addcdiv(*input[idx], *tensor1[idx], *tensor2[idx], value));
1232 return result;
1233}
1234
1239template <typename T, typename U, typename V, typename W, std::size_t... Dims>
1240inline auto addcmul(const BlockTensor<T, Dims...> &input,
1241 const BlockTensor<U, Dims...> &tensor1,
1242 const BlockTensor<V, Dims...> &tensor2, W value = 1.0) {
1244 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1245 result[idx] = std::make_shared<T>(
1246 torch::addcmul(*input[idx], *tensor1[idx], *tensor2[idx], value));
1247 return result;
1248}
1249
1253
1257
1260
1264
1267
1271
1274
1278
1279
1281
1286
1287#if TORCH_VERSION_MAJOR >= 1 && TORCH_VERSION_MINOR >= 11 || \
1288 TORCH_VERSION_MAJOR >= 2
1290blocktensor_binary_op(arctan2);
1291#endif
1292
1296
1300
1304
1308
1312
1316
1321
1324template <typename T, typename U, std::size_t... Dims>
1325inline auto clamp(const BlockTensor<T, Dims...> &input, U min, U max) {
1326 BlockTensor<T, Dims...> result;
1327 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1328 result[idx] = std::make_shared<T>(torch::clamp(*input[idx], min, max));
1329 return result;
1330}
1331
1333template <typename T, typename U, std::size_t... Dims>
1334inline auto clip(const BlockTensor<T, Dims...> &input, U min, U max) {
1335 BlockTensor<T, Dims...> result;
1336 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1337 result[idx] = std::make_shared<T>(torch::clip(*input[idx], min, max));
1338 return result;
1339}
1340
1344
1348
1352
1356
1360
1361
1364
1367
1371
1374template <typename T, std::size_t Rows, std::size_t Cols>
1375inline auto dot(const BlockTensor<T, Rows, Cols> &input, const BlockTensor<T, Rows, Cols> &tensor) {
1376 return input.dot(tensor);
1377}
1378
1382
1386
1390
1394
1398
1402
1405
1410
1414
1418
1422
1426
1430
1434
1439
1443
1447
1451
1455
1459
1463
1467
1468
1471
1475
1479
1481
1484
1489
1493
1496
1500
1503
1507
1510
1514
1517
1521
1524
1528
1532
1536
1540
1544
1548
1552
1556
1559
1563
1567
1571
1575
1579
1583
1587
1591
1593template <typename T, typename U, typename V, std::size_t... Dims>
1594inline auto sub(const BlockTensor<T, Dims...> &input,
1595 const BlockTensor<U, Dims...> &other, V alpha = 1.0) {
1597 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1598 result[idx] =
1599 std::make_shared<T>(torch::sub(*input[idx], *other[idx], alpha));
1600 return result;
1601}
1602
1604template <typename T, typename U, typename V, std::size_t... Dims>
1605inline auto subtract(const BlockTensor<T, Dims...> &input,
1606 const BlockTensor<U, Dims...> &other, V alpha = 1.0) {
1608 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1609 result[idx] =
1610 std::make_shared<T>(torch::sub(*input[idx], *other[idx], alpha));
1611 return result;
1612}
1613
1617
1621
1625
1626
1628
1631template <typename T, typename U, std::size_t... Dims>
1632inline auto operator+(const BlockTensor<T, Dims...> &lhs,
1633 const BlockTensor<U, Dims...> &rhs) {
1635 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1636 result[idx] = std::make_shared<T>(*lhs[idx] + *rhs[idx]);
1637 return result;
1638}
1639
1642template <typename T, typename U, std::size_t... Dims>
1643inline auto operator+(const BlockTensor<T, Dims...> &lhs, const U &rhs) {
1644 BlockTensor<T, Dims...> result;
1645 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1646 result[idx] = std::make_shared<T>(*lhs[idx] + rhs);
1647 return result;
1648}
1649
1652template <typename T, typename U, std::size_t... Dims>
1653inline auto operator+(const T &lhs, const BlockTensor<U, Dims...> &rhs) {
1654 BlockTensor<U, Dims...> result;
1655 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1656 result[idx] = std::make_shared<U>(lhs + *rhs[idx]);
1657 return result;
1658}
1659
1661template <typename T, typename U, std::size_t... Dims>
1663 const BlockTensor<U, Dims...> &rhs) {
1664 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1665 lhs[idx] = std::make_shared<T>(*lhs[idx] + *rhs[idx]);
1666 return lhs;
1667}
1668
1670template <typename T, typename U, std::size_t... Dims>
1671inline auto operator+=(BlockTensor<T, Dims...> &lhs, const U &rhs) {
1672 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1673 lhs[idx] = std::make_shared<T>(*lhs[idx] + rhs);
1674 return lhs;
1675}
1676
1679template <typename T, typename U, std::size_t... Dims>
1680inline auto operator-(const BlockTensor<T, Dims...> &lhs,
1681 const BlockTensor<U, Dims...> &rhs) {
1683 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1684 result[idx] = std::make_shared<T>(*lhs[idx] - *rhs[idx]);
1685 return result;
1686}
1687
1690template <typename T, typename U, std::size_t... Dims>
1691inline auto operator-(const BlockTensor<T, Dims...> &lhs, const U &rhs) {
1692 BlockTensor<T, Dims...> result;
1693 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1694 result[idx] = std::make_shared<T>(*lhs[idx] - rhs);
1695 return result;
1696}
1697
1700template <typename T, typename U, std::size_t... Dims>
1701inline auto operator-(const T &lhs, const BlockTensor<U, Dims...> &rhs) {
1702 BlockTensor<U, Dims...> result;
1703 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1704 result[idx] = std::make_shared<U>(lhs - *rhs[idx]);
1705 return result;
1706}
1707
1709template <typename T, typename U, std::size_t... Dims>
1711 const BlockTensor<U, Dims...> &rhs) {
1712 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1713 lhs[idx] = std::make_shared<T>(*lhs[idx] - *rhs[idx]);
1714 return lhs;
1715}
1716
1718template <typename T, typename U, std::size_t... Dims>
1719inline auto operator-=(BlockTensor<T, Dims...> &lhs, const U &rhs) {
1720 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1721 lhs[idx] = std::make_shared<T>(*lhs[idx] - rhs);
1722 return lhs;
1723}
1724
1727template <typename T, typename U, std::size_t... Dims>
1728inline auto operator*(const BlockTensor<T, Dims...> &lhs, const U &rhs) {
1729 BlockTensor<T, Dims...> result;
1730 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1731 result[idx] =
1732 (lhs[idx]->dim() > rhs.dim()
1733 ? std::make_shared<T>(*lhs[idx] * rhs.unsqueeze(-1))
1734 : (lhs[idx]->dim() < rhs.dim()
1735 ? std::make_shared<T>(lhs[idx]->unsqueeze(-1) * rhs)
1736 : std::make_shared<T>(*lhs[idx] * rhs)));
1737 ;
1738 return result;
1739}
1740
1743template <typename T, typename U, std::size_t... Dims>
1744inline auto operator*(const T &lhs, const BlockTensor<U, Dims...> &rhs) {
1745 BlockTensor<U, Dims...> result;
1746 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1747 result[idx] =
1748 (lhs.dim() > rhs[idx]->dim()
1749 ? std::make_shared<U>(lhs * rhs[idx]->unsqueeze(-1))
1750 : (lhs.dim() < rhs[idx]->dim()
1751 ? std::make_shared<U>(lhs.unsqueeze(-1) * *rhs[idx])
1752 : std::make_shared<U>(lhs * *rhs[idx])));
1753 return result;
1754}
1755
1757template <typename T, typename U, std::size_t... TDims, std::size_t... UDims>
1759 const BlockTensor<U, UDims...> &rhs) {
1760 if constexpr ((sizeof...(TDims) != sizeof...(UDims)) ||
1761 ((TDims != UDims) || ...))
1762 return false;
1763
1764 bool result = true;
1765 for (std::size_t idx = 0; idx < (TDims * ...); ++idx)
1766 result = result && torch::equal(*lhs[idx], *rhs[idx]);
1767
1768 return result;
1769}
1770
1772template <typename T, typename U, std::size_t... TDims, std::size_t... UDims>
1774 const BlockTensor<U, UDims...> &rhs) {
1775 return !(lhs == rhs);
1776}
1777
1778} // namespace utils
1779} // namespace iganet
#define blocktensor_unary_op(name)
Definition blocktensor.hpp:1128
#define blocktensor_unary_special_op(name)
Definition blocktensor.hpp:1137
#define blocktensor_binary_op(name)
Definition blocktensor.hpp:1146
#define blocktensor_binary_special_op(name)
Definition blocktensor.hpp:1157
static constexpr std::size_t slices()
Returns the number of slices.
Definition blocktensor.hpp:943
auto reorder_jik() const
Returns a new block tensor with rows and columns transposed and slices remaining fixed....
Definition blocktensor.hpp:998
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the BSplineCommon object.
Definition blocktensor.hpp:1034
const T & operator()(std::size_t row, std::size_t col, std::size_t slice) const
Returns a constant reference to entry (row, col, slice)
Definition blocktensor.hpp:948
T & set(std::size_t row, std::size_t col, std::size_t slice, D &&data)
Stores the given data object at the given position.
Definition blocktensor.hpp:966
auto reorder_kij() const
Returns a new block tensor with rows, columns, and slices permuted according to (i,...
Definition blocktensor.hpp:1022
auto reorder_ikj() const
Returns a new block tensor with rows, columns, and slices permuted according to (i,...
Definition blocktensor.hpp:985
static constexpr std::size_t rows()
Returns the number of rows.
Definition blocktensor.hpp:937
T & operator()(std::size_t row, std::size_t col, std::size_t slice)
Returns a non-constant reference to entry (row, col, slice)
Definition blocktensor.hpp:956
auto reorder_kji() const
Returns a new block tensor with rows, columns, and slices permuted according to (i,...
Definition blocktensor.hpp:1010
auto slice(std::size_t slice) const
Returns a rank-2 tensor of the k-th slice.
Definition blocktensor.hpp:973
static constexpr std::size_t cols()
Returns the number of columns.
Definition blocktensor.hpp:940
auto inv() const
Returns the inverse of the block tensor.
Definition blocktensor.hpp:312
auto dot_(std::index_sequence< Is... >, const BlockTensor< T, Rows, Cols > &other) const
Returns the dot product of two BlockTensor objects.
Definition blocktensor.hpp:869
auto ginv() const
Returns the (generalized) inverse of the block tensor.
Definition blocktensor.hpp:551
auto ginvtr() const
Returns the transpose of the (generalized) inverse of the block tensor.
Definition blocktensor.hpp:807
auto tr() const
Returns the transpose of the block tensor.
Definition blocktensor.hpp:225
auto invtr() const
Returns the transpose of the inverse of the block tensor.
Definition blocktensor.hpp:564
static constexpr std::size_t cols()
Returns the number of columns.
Definition blocktensor.hpp:198
auto normalize_(std::index_sequence< Is... > is) const
Returns the normalized BlockTensor object.
Definition blocktensor.hpp:855
static constexpr std::size_t rows()
Returns the number of rows.
Definition blocktensor.hpp:195
auto norm() const
Returns the norm of the BlockTensor object.
Definition blocktensor.hpp:848
const T & operator()(std::size_t row, std::size_t col) const
Returns a constant reference to entry (row, col)
Definition blocktensor.hpp:203
T & set(std::size_t row, std::size_t col, D &&data)
Stores the given data object at the given position.
Definition blocktensor.hpp:218
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the BlockTensor object.
Definition blocktensor.hpp:883
auto dot(const BlockTensor< T, Rows, Cols > &other) const
Returns the dot product of two BlockTensor objects.
Definition blocktensor.hpp:877
auto trace() const
Returns the trace of the block tensor.
Definition blocktensor.hpp:816
auto det() const
Returns the determinant of a square block tensor.
Definition blocktensor.hpp:237
T & operator()(std::size_t row, std::size_t col)
Returns a non-constant reference to entry (row, col)
Definition blocktensor.hpp:209
auto norm_(std::index_sequence< Is... >) const
Returns the norm of the BlockTensor object.
Definition blocktensor.hpp:840
auto normalize() const
Returns the normalized BlockTensor object.
Definition blocktensor.hpp:862
static constexpr std::size_t rows()
Returns the number of rows.
Definition blocktensor.hpp:170
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept override
Returns a string representation of the BlockTensor object.
Definition blocktensor.hpp:174
Compile-time block tensor core.
Definition blocktensor.hpp:50
const std::array< std::shared_ptr< T >,(Dims *...)> & data() const
Returns a constant reference to the data array.
Definition blocktensor.hpp:109
static constexpr auto dims()
Returns all dimensions as array.
Definition blocktensor.hpp:90
BlockTensorCore(BlockTensorCore< Ts, dims... > &&...other)
Constructur from BlockTensorCore objects.
Definition blocktensor.hpp:62
BlockTensorCore(Ts &&...data)
Constructor from variadic templates.
Definition blocktensor.hpp:86
BlockTensorCore()=default
Default constructor.
std::shared_ptr< T > & operator[](std::size_t idx)
Returns a non-constant shared pointer to entry (idx)
Definition blocktensor.hpp:123
T & set(std::size_t idx, Data &&data)
Stores the given data object at the given index.
Definition blocktensor.hpp:141
virtual void pretty_print(std::ostream &os=Log(log::info)) const noexcept=0
Returns a string representation of the BlockTensorCore object.
static constexpr std::size_t dim()
Returns the i-th dimension.
Definition blocktensor.hpp:95
const std::shared_ptr< T > & operator[](std::size_t idx) const
Returns a constant shared pointer to entry (idx)
Definition blocktensor.hpp:117
BlockTensorCore(BlockTensor< Ts, dims... > &&...other)
Constructur from BlockTensor objects.
Definition blocktensor.hpp:74
static constexpr std::size_t entries()
Returns the total number of entries.
Definition blocktensor.hpp:106
std::array< std::shared_ptr< T >,(Dims *...)> & data()
Returns a non-constant reference to the data array.
Definition blocktensor.hpp:114
static constexpr std::size_t size()
Returns the number of dimensions.
Definition blocktensor.hpp:103
const T & operator()(std::size_t idx) const
Returns a constant reference to entry (idx)
Definition blocktensor.hpp:129
std::array< std::shared_ptr< T >,(Dims *...)> data_
Array storing the data.
Definition blocktensor.hpp:54
T & operator()(std::size_t idx)
Returns a non-constant reference to entry (idx)
Definition blocktensor.hpp:135
Full qualified name descriptor.
Definition fqn.hpp:26
Core components.
Full qualified name utility functions.
auto addcmul(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &tensor1, const BlockTensor< V, Dims... > &tensor2, W value=1.0)
Returns a new block tensor with the elements of tensor1 multiplied by the elements of tensor2,...
Definition blocktensor.hpp:1240
auto log2(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the logarithm to the base-2 of the elements of input
Definition blocktensor.hpp:1454
auto tan(const BlockTensor< T, Dims... > &input)
Returns a new tensor with the tangent of the elements of input.
Definition blocktensor.hpp:1616
auto square(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the square of the elements of input
Definition blocktensor.hpp:1590
auto mul(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the product of each element of input and other
Definition blocktensor.hpp:1506
auto divide(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Alias for div()
Definition blocktensor.hpp:1366
auto exp2(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the base-2 exponential of the elements of input
Definition blocktensor.hpp:1397
auto frexp(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the decomposition of the elements of input into mantissae and exponen...
Definition blocktensor.hpp:1425
auto xlogy(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Computes input * log(other)
Definition blocktensor.hpp:1627
auto operator-(const BlockTensor< T, Dims... > &lhs, const BlockTensor< U, Dims... > &rhs)
Subtracts one compile-time block tensor from another and returns a new compile-time block tensor.
Definition blocktensor.hpp:1680
auto floor(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the floor of the elements of input, the largest integer less than or ...
Definition blocktensor.hpp:1413
auto bitwise_not(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the bitwise NOT of the elements of input
Definition blocktensor.hpp:1295
auto i0(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the element-wise zeroth order modified Bessel function of the first k...
Definition blocktensor.hpp:1488
auto float_power(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the elements of input raised to the power of exponent,...
Definition blocktensor.hpp:1409
auto round(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the elements of input rounded to the nearest integer.
Definition blocktensor.hpp:1547
auto hypot(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
logit
Definition blocktensor.hpp:1483
auto imag(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the imaginary values of the elements of input
Definition blocktensor.hpp:1429
auto atan(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the arctangent of the elements of input
Definition blocktensor.hpp:1270
auto copysign(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the magnitude of the elements of input and the sign of the elements o...
Definition blocktensor.hpp:1347
auto add(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other, V alpha=1.0)
Returns a new block tensor with the elements of other, scaled by alpha, added to the elements of inpu...
Definition blocktensor.hpp:1192
auto asin(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the arcsine of the elements of input
Definition blocktensor.hpp:1256
bool operator==(const BlockTensor< T, TDims... > &lhs, const BlockTensor< U, UDims... > &rhs)
Returns true if both compile-time block tensors are equal.
Definition blocktensor.hpp:1758
auto angle(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the angle (in radians) of the elements of input
Definition blocktensor.hpp:1252
auto nextafter(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Return a new block tensor with the next elementwise floating-point value after input towards other
Definition blocktensor.hpp:1520
auto arcsinh(const BlockTensor< T, Dims... > &input)
Alias for asinh()
Definition blocktensor.hpp:1266
auto sub(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other, V alpha=1.0)
Subtracts other, scaled by alpha, from input.
Definition blocktensor.hpp:1594
auto sign(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the signs of the elements of input
Definition blocktensor.hpp:1562
auto logical_and(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the element-wise logical AND of the elements of input and other
Definition blocktensor.hpp:1466
auto absolute(const BlockTensor< T, Dims... > &input)
Alias for abs()
Definition blocktensor.hpp:1173
auto fix(const BlockTensor< T, Dims... > &input)
Alias for trunc()
Definition blocktensor.hpp:1404
auto sinc(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the normalized sinc of the elements of input
Definition blocktensor.hpp:1578
auto logical_not(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the element-wise logical NOT of the elements of input
Definition blocktensor.hpp:1470
auto positive(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the input
Definition blocktensor.hpp:1523
auto sqrt(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the square-root of the elements of input
Definition blocktensor.hpp:1586
auto reciprocal(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the reciprocal of the elements of input
Definition blocktensor.hpp:1539
auto clip(const BlockTensor< T, Dims... > &input, U min, U max)
Alias for clamp()
Definition blocktensor.hpp:1334
auto arcsin(const BlockTensor< T, Dims... > &input)
Alias for asin()
Definition blocktensor.hpp:1259
auto bitwise_or(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the bitwise OR of the elements of input and other
Definition blocktensor.hpp:1303
auto atanh(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the inverse hyperbolic tangent of the elements of input
Definition blocktensor.hpp:1277
auto subtract(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other, V alpha=1.0)
Alias for sub()
Definition blocktensor.hpp:1605
auto atan2(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the arctangent of the elements in input and other with consideration ...
Definition blocktensor.hpp:1285
auto expit(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the expit (also known as the logistic sigmoid function) of the elemen...
Definition blocktensor.hpp:1555
auto rsqrt(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the reciprocal of the square-root of the elements of input
Definition blocktensor.hpp:1551
auto sin(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the sine of the elements of input
Definition blocktensor.hpp:1574
auto cosh(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the hyperbolic cosine of the elements of input
Definition blocktensor.hpp:1355
std::ostream & operator<<(std::ostream &os, const BlockTensorCore< T, Dims... > &obj)
Prints (as string) a compile-time block tensor object.
Definition blocktensor.hpp:154
auto bitwise_and(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the bitwise AND of the elements of input and other
Definition blocktensor.hpp:1299
auto erfc(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the complementary error function of the elements of input
Definition blocktensor.hpp:1385
auto gammainc(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the regularized lower incomplete gamma function of each element of in...
Definition blocktensor.hpp:1492
auto operator-=(BlockTensor< T, Dims... > &lhs, const BlockTensor< U, Dims... > &rhs)
Decrements one compile-time block tensor by another.
Definition blocktensor.hpp:1710
auto arccos(const BlockTensor< T, Dims... > &input)
Alias for acos()
Definition blocktensor.hpp:1180
auto negative(const BlockTensor< T, Dims... > &input)
Alias for neg()
Definition blocktensor.hpp:1516
auto multiply(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Alias for mul()
Definition blocktensor.hpp:1509
auto dot(const BlockTensor< T, Rows, Cols > &input, const BlockTensor< T, Rows, Cols > &tensor)
Returns a new block tensor with the dot product of the two input block tensors.
Definition blocktensor.hpp:1375
auto logaddexp2(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block-vector with the logarithm of the sum of exponentiations of the elements of input ...
Definition blocktensor.hpp:1462
auto pow(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the power of each element in input with exponent other
Definition blocktensor.hpp:1527
auto bitwise_xor(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the bitwise XOR of the elements of input and other
Definition blocktensor.hpp:1307
auto ldexp(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the elements of input multiplied by 2**other.
Definition blocktensor.hpp:1433
auto igammac(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Alias for gammainc()
Definition blocktensor.hpp:1502
auto neg(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the negative of the elements of input
Definition blocktensor.hpp:1513
auto exp(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the exponential of the elements of input
Definition blocktensor.hpp:1393
auto arctan(const BlockTensor< T, Dims... > &input)
Alias for atan()
Definition blocktensor.hpp:1273
auto log1p(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the natural logarithm of (1 + the elements of input)
Definition blocktensor.hpp:1450
auto arctanh(const BlockTensor< T, Dims... > &input)
Alias for atanh()
Definition blocktensor.hpp:1280
auto ceil(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the ceil of the elements of input, the smallest integer greater than ...
Definition blocktensor.hpp:1320
auto trunc(const BlockTensor< T, Dims... > &input)
Returns a new tensor with the truncated integer values of the elements of input.
Definition blocktensor.hpp:1624
auto cos(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the cosine of the elements of input
Definition blocktensor.hpp:1351
auto erfinv(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the inverse error function of the elements of input
Definition blocktensor.hpp:1389
bool operator!=(const BlockTensor< T, TDims... > &lhs, const BlockTensor< U, UDims... > &rhs)
Returns true if both compile-time block tensors are not equal.
Definition blocktensor.hpp:1773
auto expm1(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the exponential minus 1 of the elements of input
Definition blocktensor.hpp:1401
auto signbit(const BlockTensor< T, Dims... > &input)
Tests if each element of input has its sign bit set (is less than zero) or not.
Definition blocktensor.hpp:1570
auto conj_physical(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the conjugate of the elements of input tensor.
Definition blocktensor.hpp:1343
auto sinh(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the hyperbolic sine of the elements of input
Definition blocktensor.hpp:1582
auto remainder(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the modulus of the elements of input
Definition blocktensor.hpp:1543
auto digamma(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the logarithmic derivative of the gamma function of the elements of i...
Definition blocktensor.hpp:1370
auto asinh(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the inverse hyperbolic sine of the elements of input
Definition blocktensor.hpp:1263
auto div(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the elements of input divided by the elements of other
Definition blocktensor.hpp:1363
auto igamma(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Alias for gammainc()
Definition blocktensor.hpp:1495
auto bitwise_left_shift(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the left arithmetic shift of the elements of input by other bits.
Definition blocktensor.hpp:1311
auto rad2deg(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with each of the elements of input converted from angles in radians to deg...
Definition blocktensor.hpp:1531
auto real(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the real values of the elements of input
Definition blocktensor.hpp:1535
auto lgamma(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the natural logarithm of the absolute value of the gamma function of ...
Definition blocktensor.hpp:1438
auto gammaincc(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the regularized upper incomplete gamma function of each element of in...
Definition blocktensor.hpp:1499
auto acos(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the inverse cosine of the elements of input
Definition blocktensor.hpp:1177
auto fmod(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the fmod of the elements of input and other
Definition blocktensor.hpp:1417
auto bitwise_right_shift(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the right arithmetic shift of the element of input by other bits.
Definition blocktensor.hpp:1315
auto operator+=(BlockTensor< T, Dims... > &lhs, const BlockTensor< U, Dims... > &rhs)
Increments one compile-time block tensor by another.
Definition blocktensor.hpp:1662
auto sgn(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the signs of the elements of input, extension to complex value.
Definition blocktensor.hpp:1566
auto arccosh(const BlockTensor< T, Dims... > &input)
Alias for acosh()`.
Definition blocktensor.hpp:1187
auto abs(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the absolute value of the elements of input
Definition blocktensor.hpp:1170
auto logical_xor(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the element-wise logical XOR of the elements of input and other
Definition blocktensor.hpp:1478
auto addcdiv(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &tensor1, const BlockTensor< V, Dims... > &tensor2, W value=1.0)
Returns a new block tensor with the elements of tensor1 divided by the elements of tensor2,...
Definition blocktensor.hpp:1225
auto deg2rad(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the elements of input converted from angles in degrees to radians.
Definition blocktensor.hpp:1359
auto logaddexp(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block-vector with the logarithm of the sum of exponentiations of the elements of input
Definition blocktensor.hpp:1458
auto erf(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the error function of the elements of input
Definition blocktensor.hpp:1381
auto operator*(const BlockTensor< T, Rows, Common > &lhs, const BlockTensor< U, Common, Cols > &rhs)
Multiplies one compile-time rank-2 block tensor with another compile-time rank-2 block tensor.
Definition blocktensor.hpp:896
auto log10(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the logarithm to the base-10 of the elements of input
Definition blocktensor.hpp:1446
auto make_shared(T &&arg)
Returns an std::shared_ptr<T> object from arg.
Definition blocktensor.hpp:38
auto acosh(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the inverse hyperbolic cosine of the elements of input
Definition blocktensor.hpp:1184
auto clamp(const BlockTensor< T, Dims... > &input, U min, U max)
Returns a new block tensor with the elements of input clamped into the range [ min,...
Definition blocktensor.hpp:1325
auto logical_or(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Returns a new block tensor with the element-wise logical OR of the elements of input and other
Definition blocktensor.hpp:1474
auto frac(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the fractional portion of the elements of input
Definition blocktensor.hpp:1421
Forward declaration of BlockTensor.
Definition blocktensor.hpp:46
Definition boundary.hpp:22
constexpr auto operator+(deriv lhs, deriv rhs)
Adds two enumerators for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:91
struct iganet::@0 Log
Logger.
log
Enumerator for specifying the logging level.
Definition core.hpp:90
STL namespace.
Type trait checks if template argument is of type std::shared_ptr<T>
Definition blocktensor.hpp:31