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 <memory>
19#include <type_traits>
20
21#include <iganet/core/core.hpp>
22#include <iganet/utils/fqn.hpp>
23
24namespace iganet::utils {
25
28template <typename T> struct is_shared_ptr : std::false_type {};
29
30template <typename T>
31struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};
33
39template <typename T> inline auto make_shared(T &&arg) {
40 if constexpr (is_shared_ptr<std::decay_t<T>>::value)
41 return std::forward<std::decay_t<T>>(arg);
42 else
43 return std::make_shared<std::decay_t<T>>(std::forward<T>(arg));
44}
45
47template <typename T, std::size_t... Dims> class BlockTensor;
48
50template <typename T, std::size_t... Dims>
52
53protected:
55 std::array<std::shared_ptr<T>, (Dims * ...)> data_;
56
57public:
59 BlockTensorCore() = default;
60
65 template <typename... Ts, std::size_t... dims>
67 auto it = data_.begin();
68 (std::transform(other.data().begin(), other.data().end(), it,
69 [&it]<typename D>(D &&d) {
70 ++it;
71 return std::forward<D>(d);
72 }),
73 ...);
74 }
75
80 template <typename... Ts, std::size_t... dims>
82 auto it = data_.begin();
83 (std::transform(other.data().begin(), other.data().end(), it,
84 [&it]<typename D>(D &&d) {
85 ++it;
86 return std::forward<D>(d);
87 }),
88 ...);
89 }
90
94 template <typename... Ts>
95 explicit BlockTensorCore(Ts &&...data)
96 : data_({make_shared<Ts>(std::forward<Ts>(data))...}) {}
97
101 inline static constexpr auto dims() {
102 return std::array<std::size_t, sizeof...(Dims)>({Dims...});
103 }
104
108 template <std::size_t i> inline static constexpr std::size_t dim() {
109 if constexpr (i < sizeof...(Dims))
110 return std::get<i>(std::forward_as_tuple(Dims...));
111 else
112 return 0;
113 }
114
117 inline static constexpr std::size_t size() { return sizeof...(Dims); }
118
121 inline static constexpr std::size_t entries() { return (Dims * ...); }
122
125 inline const std::array<std::shared_ptr<T>, (Dims * ...)> &data() const {
126 return data_;
127 }
128
131 inline std::array<std::shared_ptr<T>, (Dims * ...)> &data() { return data_; }
132
136 inline const std::shared_ptr<T> &operator[](std::size_t idx) const {
137 assert(idx < (Dims * ...));
138 return data_[idx];
139 }
140
144 inline std::shared_ptr<T> &operator[](std::size_t idx) {
145 assert(idx < (Dims * ...));
146 return data_[idx];
147 }
148
151 inline const T &operator()(std::size_t idx) const {
152 assert(idx < (Dims * ...));
153 return *data_[idx];
154 }
155
158 inline T &operator()(std::size_t idx) {
159 assert(idx < (Dims * ...));
160 return *data_[idx];
161 }
162
168 template <typename Data> inline T &set(std::size_t idx, Data &&data) {
169 assert(idx < (Dims * ...));
170 data_[idx] = make_shared<Data>(std::forward<Data>(data));
171 return *data_[idx];
172 }
173
176 inline void pretty_print(std::ostream &os) const noexcept override = 0;
177};
178
185template <typename T, std::size_t... Dims>
186inline std::ostream &operator<<(std::ostream &os,
187 const BlockTensorCore<T, Dims...> &obj) {
188 obj.pretty_print(os);
189 return os;
190}
191
193template <typename T, std::size_t Rows>
194class BlockTensor<T, Rows> : public BlockTensorCore<T, Rows> {
195private:
197
198public:
199 using BlockTensorCore<T, Rows>::BlockTensorCore;
200
203 inline static constexpr std::size_t rows() { return Rows; }
204
207 inline void pretty_print(std::ostream &os) const noexcept override {
208 os << Base::name() << "\n";
209 for (std::size_t row = 0; row < Rows; ++row)
210 os << "[" << row << "] = \n" << *Base::data_[row] << "\n";
211 }
212};
213
219template <typename T, std::size_t Rows, std::size_t Cols>
220class BlockTensor<T, Rows, Cols> : public BlockTensorCore<T, Rows, Cols> {
221private:
223
224public:
225 using BlockTensorCore<T, Rows, Cols>::BlockTensorCore;
226
229 inline static constexpr std::size_t rows() { return Rows; }
230
233 inline static constexpr std::size_t cols() { return Cols; }
234
235 using Base::operator();
236
239 inline const T &operator()(std::size_t row, std::size_t col) const {
240 assert(row < Rows && col < Cols);
241 return *Base::data_[Cols * row + col];
242 }
243
246 inline T &operator()(std::size_t row, std::size_t col) {
247 assert(row < Rows && col < Cols);
248 return *Base::data_[Cols * row + col];
249 }
250
251 using Base::set;
252
259 template <typename D>
260 inline T &set(std::size_t row, std::size_t col, D &&data) {
261 assert(row < Rows && col < Cols);
262 Base::data_[Cols * row + col] = make_shared<D>(std::forward<D>(data));
263 return *Base::data_[Cols * row + col];
264 }
265
268 inline auto tr() const {
270 for (std::size_t row = 0; row < Rows; ++row)
271 for (std::size_t col = 0; col < Cols; ++col)
272 result[Rows * col + row] = Base::data_[Cols * row + col];
273 return result;
274 }
275
279
282 inline auto det() const {
283 if constexpr (Rows == 1 && Cols == 1) {
284 auto result = *Base::data_[0];
285 return result;
286 } else if constexpr (Rows == 2 && Cols == 2) {
287 auto result = torch::mul(*Base::data_[0], *Base::data_[3]) -
288 torch::mul(*Base::data_[1], *Base::data_[2]);
289 return result;
290 } else if constexpr (Rows == 3 && Cols == 3) {
291 auto result =
292 torch::mul(*Base::data_[0],
293 torch::mul(*Base::data_[4], *Base::data_[8]) -
294 torch::mul(*Base::data_[5], *Base::data_[7])) -
295 torch::mul(*Base::data_[1],
296 torch::mul(*Base::data_[3], *Base::data_[8]) -
297 torch::mul(*Base::data_[5], *Base::data_[6])) +
298 torch::mul(*Base::data_[2],
299 torch::mul(*Base::data_[3], *Base::data_[7]) -
300 torch::mul(*Base::data_[4], *Base::data_[6]));
301 return result;
302 } else if constexpr (Rows == 4 && Cols == 4) {
303 auto a11 = torch::mul(*Base::data_[5],
304 (torch::mul(*Base::data_[10], *Base::data_[15]) -
305 torch::mul(*Base::data_[11], *Base::data_[14]))) -
306 torch::mul(*Base::data_[9],
307 (torch::mul(*Base::data_[6], *Base::data_[15]) -
308 torch::mul(*Base::data_[7], *Base::data_[14]))) -
309 torch::mul(*Base::data_[13],
310 (torch::mul(*Base::data_[7], *Base::data_[10]) -
311 torch::mul(*Base::data_[6], *Base::data_[11])));
312
313 auto a21 = torch::mul(*Base::data_[4],
314 (torch::mul(*Base::data_[11], *Base::data_[14]) -
315 torch::mul(*Base::data_[10], *Base::data_[15]))) -
316 torch::mul(*Base::data_[8],
317 (torch::mul(*Base::data_[7], *Base::data_[14]) -
318 torch::mul(*Base::data_[6], *Base::data_[15]))) -
319 torch::mul(*Base::data_[12],
320 (torch::mul(*Base::data_[6], *Base::data_[11]) -
321 torch::mul(*Base::data_[7], *Base::data_[10])));
322
323 auto a31 = torch::mul(*Base::data_[4],
324 (torch::mul(*Base::data_[9], *Base::data_[15]) -
325 torch::mul(*Base::data_[11], *Base::data_[13]))) -
326 torch::mul(*Base::data_[8],
327 (torch::mul(*Base::data_[5], *Base::data_[15]) -
328 torch::mul(*Base::data_[7], *Base::data_[13]))) -
329 torch::mul(*Base::data_[12],
330 (torch::mul(*Base::data_[7], *Base::data_[9]) -
331 torch::mul(*Base::data_[5], *Base::data_[11])));
332
333 auto a41 = torch::mul(*Base::data_[4],
334 (torch::mul(*Base::data_[10], *Base::data_[13]) -
335 torch::mul(*Base::data_[9], *Base::data_[14]))) -
336 torch::mul(*Base::data_[8],
337 (torch::mul(*Base::data_[6], *Base::data_[13]) -
338 torch::mul(*Base::data_[5], *Base::data_[14]))) -
339 torch::mul(*Base::data_[12],
340 (torch::mul(*Base::data_[5], *Base::data_[10]) -
341 torch::mul(*Base::data_[6], *Base::data_[9])));
342
343 auto result =
344 torch::mul(*Base::data_[0], a11) + torch::mul(*Base::data_[1], a21) +
345 torch::mul(*Base::data_[2], a31) + torch::mul(*Base::data_[3], a41);
346
347 return result;
348 } else {
349 throw std::runtime_error("Unsupported block tensor dimension");
350 return *this;
351 }
352 }
353
358 inline auto inv() const {
359
360 auto det_ = this->det();
361
362 if constexpr (Rows == 1 && Cols == 1) {
364 result[0] = std::make_shared<T>(torch::reciprocal(*Base::data_[0]));
365 return result;
366 } else if constexpr (Rows == 2 && Cols == 2) {
367
369 result[0] = std::make_shared<T>(torch::div(*Base::data_[3], det_));
370 result[1] = std::make_shared<T>(torch::div(*Base::data_[1], -det_));
371 result[2] = std::make_shared<T>(torch::div(*Base::data_[2], -det_));
372 result[3] = std::make_shared<T>(torch::div(*Base::data_[0], det_));
373 return result;
374 } else if constexpr (Rows == 3 && Cols == 3) {
375
376 auto a11 = torch::mul(*Base::data_[4], *Base::data_[8]) -
377 torch::mul(*Base::data_[5], *Base::data_[7]);
378 auto a12 = torch::mul(*Base::data_[2], *Base::data_[7]) -
379 torch::mul(*Base::data_[1], *Base::data_[8]);
380 auto a13 = torch::mul(*Base::data_[1], *Base::data_[5]) -
381 torch::mul(*Base::data_[2], *Base::data_[4]);
382 auto a21 = torch::mul(*Base::data_[5], *Base::data_[6]) -
383 torch::mul(*Base::data_[3], *Base::data_[8]);
384 auto a22 = torch::mul(*Base::data_[0], *Base::data_[8]) -
385 torch::mul(*Base::data_[2], *Base::data_[6]);
386 auto a23 = torch::mul(*Base::data_[2], *Base::data_[3]) -
387 torch::mul(*Base::data_[0], *Base::data_[5]);
388 auto a31 = torch::mul(*Base::data_[3], *Base::data_[7]) -
389 torch::mul(*Base::data_[4], *Base::data_[6]);
390 auto a32 = torch::mul(*Base::data_[1], *Base::data_[6]) -
391 torch::mul(*Base::data_[0], *Base::data_[7]);
392 auto a33 = torch::mul(*Base::data_[0], *Base::data_[4]) -
393 torch::mul(*Base::data_[1], *Base::data_[3]);
394
396 result[0] = std::make_shared<T>(torch::div(a11, det_));
397 result[1] = std::make_shared<T>(torch::div(a12, det_));
398 result[2] = std::make_shared<T>(torch::div(a13, det_));
399 result[3] = std::make_shared<T>(torch::div(a21, det_));
400 result[4] = std::make_shared<T>(torch::div(a22, det_));
401 result[5] = std::make_shared<T>(torch::div(a23, det_));
402 result[6] = std::make_shared<T>(torch::div(a31, det_));
403 result[7] = std::make_shared<T>(torch::div(a32, det_));
404 result[8] = std::make_shared<T>(torch::div(a33, det_));
405 return result;
406 } else if constexpr (Rows == 4 && Cols == 4) {
407 auto a11 = torch::mul(*Base::data_[5],
408 (torch::mul(*Base::data_[10], *Base::data_[15]) -
409 torch::mul(*Base::data_[11], *Base::data_[14]))) -
410 torch::mul(*Base::data_[9],
411 (torch::mul(*Base::data_[6], *Base::data_[15]) -
412 torch::mul(*Base::data_[7], *Base::data_[14]))) -
413 torch::mul(*Base::data_[13],
414 (torch::mul(*Base::data_[7], *Base::data_[10]) -
415 torch::mul(*Base::data_[6], *Base::data_[11])));
416
417 auto a12 = torch::mul(*Base::data_[1],
418 (torch::mul(*Base::data_[11], *Base::data_[14]) -
419 torch::mul(*Base::data_[10], *Base::data_[15]))) -
420 torch::mul(*Base::data_[9],
421 (torch::mul(*Base::data_[3], *Base::data_[14]) -
422 torch::mul(*Base::data_[2], *Base::data_[15]))) -
423 torch::mul(*Base::data_[13],
424 (torch::mul(*Base::data_[2], *Base::data_[11]) -
425 torch::mul(*Base::data_[3], *Base::data_[10])));
426
427 auto a13 = torch::mul(*Base::data_[1],
428 (torch::mul(*Base::data_[6], *Base::data_[15]) -
429 torch::mul(*Base::data_[7], *Base::data_[14]))) -
430 torch::mul(*Base::data_[5],
431 (torch::mul(*Base::data_[2], *Base::data_[15]) -
432 torch::mul(*Base::data_[3], *Base::data_[14]))) -
433 torch::mul(*Base::data_[13],
434 (torch::mul(*Base::data_[3], *Base::data_[6]) -
435 torch::mul(*Base::data_[2], *Base::data_[7])));
436
437 auto a14 = torch::mul(*Base::data_[1],
438 (torch::mul(*Base::data_[7], *Base::data_[10]) -
439 torch::mul(*Base::data_[6], *Base::data_[11]))) -
440 torch::mul(*Base::data_[5],
441 (torch::mul(*Base::data_[3], *Base::data_[10]) -
442 torch::mul(*Base::data_[2], *Base::data_[11]))) -
443 torch::mul(*Base::data_[9],
444 (torch::mul(*Base::data_[2], *Base::data_[7]) -
445 torch::mul(*Base::data_[3], *Base::data_[6])));
446
447 auto a21 = torch::mul(*Base::data_[4],
448 (torch::mul(*Base::data_[11], *Base::data_[14]) -
449 torch::mul(*Base::data_[10], *Base::data_[15]))) -
450 torch::mul(*Base::data_[8],
451 (torch::mul(*Base::data_[7], *Base::data_[14]) -
452 torch::mul(*Base::data_[6], *Base::data_[15]))) -
453 torch::mul(*Base::data_[12],
454 (torch::mul(*Base::data_[6], *Base::data_[11]) -
455 torch::mul(*Base::data_[7], *Base::data_[10])));
456
457 auto a22 = torch::mul(*Base::data_[0],
458 (torch::mul(*Base::data_[10], *Base::data_[15]) -
459 torch::mul(*Base::data_[11], *Base::data_[14]))) -
460 torch::mul(*Base::data_[8],
461 (torch::mul(*Base::data_[2], *Base::data_[15]) -
462 torch::mul(*Base::data_[3], *Base::data_[14]))) -
463 torch::mul(*Base::data_[12],
464 (torch::mul(*Base::data_[3], *Base::data_[10]) -
465 torch::mul(*Base::data_[2], *Base::data_[11])));
466
467 auto a23 = torch::mul(*Base::data_[0],
468 (torch::mul(*Base::data_[7], *Base::data_[14]) -
469 torch::mul(*Base::data_[6], *Base::data_[15]))) -
470 torch::mul(*Base::data_[4],
471 (torch::mul(*Base::data_[3], *Base::data_[14]) -
472 torch::mul(*Base::data_[2], *Base::data_[15]))) -
473 torch::mul(*Base::data_[12],
474 (torch::mul(*Base::data_[2], *Base::data_[7]) -
475 torch::mul(*Base::data_[3], *Base::data_[6])));
476
477 auto a24 = torch::mul(*Base::data_[0],
478 (torch::mul(*Base::data_[6], *Base::data_[11]) -
479 torch::mul(*Base::data_[7], *Base::data_[10]))) -
480 torch::mul(*Base::data_[4],
481 (torch::mul(*Base::data_[2], *Base::data_[11]) -
482 torch::mul(*Base::data_[3], *Base::data_[10]))) -
483 torch::mul(*Base::data_[8],
484 (torch::mul(*Base::data_[3], *Base::data_[6]) -
485 torch::mul(*Base::data_[2], *Base::data_[7])));
486
487 auto a31 = torch::mul(*Base::data_[4],
488 (torch::mul(*Base::data_[9], *Base::data_[15]) -
489 torch::mul(*Base::data_[11], *Base::data_[13]))) -
490 torch::mul(*Base::data_[8],
491 (torch::mul(*Base::data_[5], *Base::data_[15]) -
492 torch::mul(*Base::data_[7], *Base::data_[13]))) -
493 torch::mul(*Base::data_[12],
494 (torch::mul(*Base::data_[7], *Base::data_[9]) -
495 torch::mul(*Base::data_[5], *Base::data_[11])));
496
497 auto a32 = torch::mul(*Base::data_[0],
498 (torch::mul(*Base::data_[11], *Base::data_[13]) -
499 torch::mul(*Base::data_[9], *Base::data_[15]))) -
500 torch::mul(*Base::data_[8],
501 (torch::mul(*Base::data_[3], *Base::data_[13]) -
502 torch::mul(*Base::data_[1], *Base::data_[15]))) -
503 torch::mul(*Base::data_[12],
504 (torch::mul(*Base::data_[1], *Base::data_[11]) -
505 torch::mul(*Base::data_[3], *Base::data_[9])));
506
507 auto a33 = torch::mul(*Base::data_[0],
508 (torch::mul(*Base::data_[5], *Base::data_[15]) -
509 torch::mul(*Base::data_[7], *Base::data_[13]))) -
510 torch::mul(*Base::data_[4],
511 (torch::mul(*Base::data_[1], *Base::data_[15]) -
512 torch::mul(*Base::data_[3], *Base::data_[13]))) -
513 torch::mul(*Base::data_[12],
514 (torch::mul(*Base::data_[3], *Base::data_[5]) -
515 torch::mul(*Base::data_[1], *Base::data_[7])));
516
517 auto a34 = torch::mul(*Base::data_[0],
518 (torch::mul(*Base::data_[7], *Base::data_[9]) -
519 torch::mul(*Base::data_[5], *Base::data_[11]))) -
520 torch::mul(*Base::data_[4],
521 (torch::mul(*Base::data_[3], *Base::data_[9]) -
522 torch::mul(*Base::data_[1], *Base::data_[11]))) -
523 torch::mul(*Base::data_[8],
524 (torch::mul(*Base::data_[1], *Base::data_[7]) -
525 torch::mul(*Base::data_[3], *Base::data_[5])));
526
527 auto a41 = torch::mul(*Base::data_[4],
528 (torch::mul(*Base::data_[10], *Base::data_[13]) -
529 torch::mul(*Base::data_[9], *Base::data_[14]))) -
530 torch::mul(*Base::data_[8],
531 (torch::mul(*Base::data_[6], *Base::data_[13]) -
532 torch::mul(*Base::data_[5], *Base::data_[14]))) -
533 torch::mul(*Base::data_[12],
534 (torch::mul(*Base::data_[5], *Base::data_[10]) -
535 torch::mul(*Base::data_[6], *Base::data_[9])));
536
537 auto a42 = torch::mul(*Base::data_[0],
538 (torch::mul(*Base::data_[9], *Base::data_[14]) -
539 torch::mul(*Base::data_[10], *Base::data_[13]))) -
540 torch::mul(*Base::data_[8],
541 (torch::mul(*Base::data_[1], *Base::data_[14]) -
542 torch::mul(*Base::data_[2], *Base::data_[13]))) -
543 torch::mul(*Base::data_[12],
544 (torch::mul(*Base::data_[2], *Base::data_[9]) -
545 torch::mul(*Base::data_[1], *Base::data_[10])));
546
547 auto a43 = torch::mul(*Base::data_[0],
548 (torch::mul(*Base::data_[6], *Base::data_[13]) -
549 torch::mul(*Base::data_[5], *Base::data_[14]))) -
550 torch::mul(*Base::data_[4],
551 (torch::mul(*Base::data_[2], *Base::data_[13]) -
552 torch::mul(*Base::data_[1], *Base::data_[14]))) -
553 torch::mul(*Base::data_[12],
554 (torch::mul(*Base::data_[1], *Base::data_[6]) -
555 torch::mul(*Base::data_[2], *Base::data_[5])));
556
557 auto a44 = torch::mul(*Base::data_[0],
558 (torch::mul(*Base::data_[5], *Base::data_[10]) -
559 torch::mul(*Base::data_[6], *Base::data_[9]))) -
560 torch::mul(*Base::data_[4],
561 (torch::mul(*Base::data_[1], *Base::data_[10]) -
562 torch::mul(*Base::data_[2], *Base::data_[9]))) -
563 torch::mul(*Base::data_[8],
564 (torch::mul(*Base::data_[2], *Base::data_[5]) -
565 torch::mul(*Base::data_[1], *Base::data_[6])));
567 result[0] = std::make_shared<T>(torch::div(a11, det_));
568 result[1] = std::make_shared<T>(torch::div(a12, det_));
569 result[2] = std::make_shared<T>(torch::div(a13, det_));
570 result[3] = std::make_shared<T>(torch::div(a14, det_));
571 result[4] = std::make_shared<T>(torch::div(a21, det_));
572 result[5] = std::make_shared<T>(torch::div(a22, det_));
573 result[6] = std::make_shared<T>(torch::div(a23, det_));
574 result[7] = std::make_shared<T>(torch::div(a24, det_));
575 result[8] = std::make_shared<T>(torch::div(a31, det_));
576 result[9] = std::make_shared<T>(torch::div(a32, det_));
577 result[10] = std::make_shared<T>(torch::div(a33, det_));
578 result[11] = std::make_shared<T>(torch::div(a34, det_));
579 result[12] = std::make_shared<T>(torch::div(a41, det_));
580 result[13] = std::make_shared<T>(torch::div(a42, det_));
581 result[14] = std::make_shared<T>(torch::div(a43, det_));
582 result[15] = std::make_shared<T>(torch::div(a44, det_));
583 return result;
584 } else {
585 throw std::runtime_error("Unsupported block tensor dimension");
586 return *this;
587 }
588 }
589
598 inline auto ginv() const {
599 if constexpr (Rows == Cols)
600 return this->inv();
601 else
602 // Compute the generalized inverse, i.e. (A^T A)^{-1} A^T
603 return (this->tr() * (*this)).inv() * this->tr();
604 }
605
612 inline auto invtr() const {
613
614 auto det_ = this->det();
615
616 if constexpr (Rows == 1 && Cols == 1) {
618 result[0] = std::make_shared<T>(torch::reciprocal(*Base::data_[0]));
619 return result;
620 } else if constexpr (Rows == 2 && Cols == 2) {
621
623 result[0] = std::make_shared<T>(torch::div(*Base::data_[3], det_));
624 result[1] = std::make_shared<T>(torch::div(*Base::data_[2], -det_));
625 result[2] = std::make_shared<T>(torch::div(*Base::data_[1], -det_));
626 result[3] = std::make_shared<T>(torch::div(*Base::data_[0], det_));
627 return result;
628 } else if constexpr (Rows == 3 && Cols == 3) {
629
630 auto a11 = torch::mul(*Base::data_[4], *Base::data_[8]) -
631 torch::mul(*Base::data_[5], *Base::data_[7]);
632 auto a12 = torch::mul(*Base::data_[2], *Base::data_[7]) -
633 torch::mul(*Base::data_[1], *Base::data_[8]);
634 auto a13 = torch::mul(*Base::data_[1], *Base::data_[5]) -
635 torch::mul(*Base::data_[2], *Base::data_[4]);
636 auto a21 = torch::mul(*Base::data_[5], *Base::data_[6]) -
637 torch::mul(*Base::data_[3], *Base::data_[8]);
638 auto a22 = torch::mul(*Base::data_[0], *Base::data_[8]) -
639 torch::mul(*Base::data_[2], *Base::data_[6]);
640 auto a23 = torch::mul(*Base::data_[2], *Base::data_[3]) -
641 torch::mul(*Base::data_[0], *Base::data_[5]);
642 auto a31 = torch::mul(*Base::data_[3], *Base::data_[7]) -
643 torch::mul(*Base::data_[4], *Base::data_[6]);
644 auto a32 = torch::mul(*Base::data_[1], *Base::data_[6]) -
645 torch::mul(*Base::data_[0], *Base::data_[7]);
646 auto a33 = torch::mul(*Base::data_[0], *Base::data_[4]) -
647 torch::mul(*Base::data_[1], *Base::data_[3]);
648
650 result[0] = std::make_shared<T>(torch::div(a11, det_));
651 result[1] = std::make_shared<T>(torch::div(a21, det_));
652 result[2] = std::make_shared<T>(torch::div(a31, det_));
653 result[3] = std::make_shared<T>(torch::div(a12, det_));
654 result[4] = std::make_shared<T>(torch::div(a22, det_));
655 result[5] = std::make_shared<T>(torch::div(a32, det_));
656 result[6] = std::make_shared<T>(torch::div(a13, det_));
657 result[7] = std::make_shared<T>(torch::div(a23, det_));
658 result[8] = std::make_shared<T>(torch::div(a33, det_));
659 return result;
660 } else if constexpr (Rows == 4 && Cols == 4) {
661
662 auto a11 = torch::mul(*Base::data_[5],
663 (torch::mul(*Base::data_[10], *Base::data_[15]) -
664 torch::mul(*Base::data_[11], *Base::data_[14]))) -
665 torch::mul(*Base::data_[9],
666 (torch::mul(*Base::data_[6], *Base::data_[15]) -
667 torch::mul(*Base::data_[7], *Base::data_[14]))) -
668 torch::mul(*Base::data_[13],
669 (torch::mul(*Base::data_[7], *Base::data_[10]) -
670 torch::mul(*Base::data_[6], *Base::data_[11])));
671
672 auto a12 = torch::mul(*Base::data_[1],
673 (torch::mul(*Base::data_[11], *Base::data_[14]) -
674 torch::mul(*Base::data_[10], *Base::data_[15]))) -
675 torch::mul(*Base::data_[9],
676 (torch::mul(*Base::data_[3], *Base::data_[14]) -
677 torch::mul(*Base::data_[2], *Base::data_[15]))) -
678 torch::mul(*Base::data_[13],
679 (torch::mul(*Base::data_[2], *Base::data_[11]) -
680 torch::mul(*Base::data_[3], *Base::data_[10])));
681
682 auto a13 = torch::mul(*Base::data_[1],
683 (torch::mul(*Base::data_[6], *Base::data_[15]) -
684 torch::mul(*Base::data_[7], *Base::data_[14]))) -
685 torch::mul(*Base::data_[5],
686 (torch::mul(*Base::data_[2], *Base::data_[15]) -
687 torch::mul(*Base::data_[3], *Base::data_[14]))) -
688 torch::mul(*Base::data_[13],
689 (torch::mul(*Base::data_[3], *Base::data_[6]) -
690 torch::mul(*Base::data_[2], *Base::data_[7])));
691
692 auto a14 = torch::mul(*Base::data_[1],
693 (torch::mul(*Base::data_[7], *Base::data_[10]) -
694 torch::mul(*Base::data_[6], *Base::data_[11]))) -
695 torch::mul(*Base::data_[5],
696 (torch::mul(*Base::data_[3], *Base::data_[10]) -
697 torch::mul(*Base::data_[2], *Base::data_[11]))) -
698 torch::mul(*Base::data_[9],
699 (torch::mul(*Base::data_[2], *Base::data_[7]) -
700 torch::mul(*Base::data_[3], *Base::data_[6])));
701
702 auto a21 = torch::mul(*Base::data_[4],
703 (torch::mul(*Base::data_[11], *Base::data_[14]) -
704 torch::mul(*Base::data_[10], *Base::data_[15]))) -
705 torch::mul(*Base::data_[8],
706 (torch::mul(*Base::data_[7], *Base::data_[14]) -
707 torch::mul(*Base::data_[6], *Base::data_[15]))) -
708 torch::mul(*Base::data_[12],
709 (torch::mul(*Base::data_[6], *Base::data_[11]) -
710 torch::mul(*Base::data_[7], *Base::data_[10])));
711
712 auto a22 = torch::mul(*Base::data_[0],
713 (torch::mul(*Base::data_[10], *Base::data_[15]) -
714 torch::mul(*Base::data_[11], *Base::data_[14]))) -
715 torch::mul(*Base::data_[8],
716 (torch::mul(*Base::data_[2], *Base::data_[15]) -
717 torch::mul(*Base::data_[3], *Base::data_[14]))) -
718 torch::mul(*Base::data_[12],
719 (torch::mul(*Base::data_[3], *Base::data_[10]) -
720 torch::mul(*Base::data_[2], *Base::data_[11])));
721
722 auto a23 = torch::mul(*Base::data_[0],
723 (torch::mul(*Base::data_[7], *Base::data_[14]) -
724 torch::mul(*Base::data_[6], *Base::data_[15]))) -
725 torch::mul(*Base::data_[4],
726 (torch::mul(*Base::data_[3], *Base::data_[14]) -
727 torch::mul(*Base::data_[2], *Base::data_[15]))) -
728 torch::mul(*Base::data_[12],
729 (torch::mul(*Base::data_[2], *Base::data_[7]) -
730 torch::mul(*Base::data_[3], *Base::data_[6])));
731
732 auto a24 = torch::mul(*Base::data_[0],
733 (torch::mul(*Base::data_[6], *Base::data_[11]) -
734 torch::mul(*Base::data_[7], *Base::data_[10]))) -
735 torch::mul(*Base::data_[4],
736 (torch::mul(*Base::data_[2], *Base::data_[11]) -
737 torch::mul(*Base::data_[3], *Base::data_[10]))) -
738 torch::mul(*Base::data_[8],
739 (torch::mul(*Base::data_[3], *Base::data_[6]) -
740 torch::mul(*Base::data_[2], *Base::data_[7])));
741
742 auto a31 = torch::mul(*Base::data_[4],
743 (torch::mul(*Base::data_[9], *Base::data_[15]) -
744 torch::mul(*Base::data_[11], *Base::data_[13]))) -
745 torch::mul(*Base::data_[8],
746 (torch::mul(*Base::data_[5], *Base::data_[15]) -
747 torch::mul(*Base::data_[7], *Base::data_[13]))) -
748 torch::mul(*Base::data_[12],
749 (torch::mul(*Base::data_[7], *Base::data_[9]) -
750 torch::mul(*Base::data_[5], *Base::data_[11])));
751
752 auto a32 = torch::mul(*Base::data_[0],
753 (torch::mul(*Base::data_[11], *Base::data_[13]) -
754 torch::mul(*Base::data_[9], *Base::data_[15]))) -
755 torch::mul(*Base::data_[8],
756 (torch::mul(*Base::data_[3], *Base::data_[13]) -
757 torch::mul(*Base::data_[1], *Base::data_[15]))) -
758 torch::mul(*Base::data_[12],
759 (torch::mul(*Base::data_[1], *Base::data_[11]) -
760 torch::mul(*Base::data_[3], *Base::data_[9])));
761
762 auto a33 = torch::mul(*Base::data_[0],
763 (torch::mul(*Base::data_[5], *Base::data_[15]) -
764 torch::mul(*Base::data_[7], *Base::data_[13]))) -
765 torch::mul(*Base::data_[4],
766 (torch::mul(*Base::data_[1], *Base::data_[15]) -
767 torch::mul(*Base::data_[3], *Base::data_[13]))) -
768 torch::mul(*Base::data_[12],
769 (torch::mul(*Base::data_[3], *Base::data_[5]) -
770 torch::mul(*Base::data_[1], *Base::data_[7])));
771
772 auto a34 = torch::mul(*Base::data_[0],
773 (torch::mul(*Base::data_[7], *Base::data_[9]) -
774 torch::mul(*Base::data_[5], *Base::data_[11]))) -
775 torch::mul(*Base::data_[4],
776 (torch::mul(*Base::data_[3], *Base::data_[9]) -
777 torch::mul(*Base::data_[1], *Base::data_[11]))) -
778 torch::mul(*Base::data_[8],
779 (torch::mul(*Base::data_[1], *Base::data_[7]) -
780 torch::mul(*Base::data_[3], *Base::data_[5])));
781
782 auto a41 = torch::mul(*Base::data_[4],
783 (torch::mul(*Base::data_[10], *Base::data_[13]) -
784 torch::mul(*Base::data_[9], *Base::data_[14]))) -
785 torch::mul(*Base::data_[8],
786 (torch::mul(*Base::data_[6], *Base::data_[13]) -
787 torch::mul(*Base::data_[5], *Base::data_[14]))) -
788 torch::mul(*Base::data_[12],
789 (torch::mul(*Base::data_[5], *Base::data_[10]) -
790 torch::mul(*Base::data_[6], *Base::data_[9])));
791
792 auto a42 = torch::mul(*Base::data_[0],
793 (torch::mul(*Base::data_[9], *Base::data_[14]) -
794 torch::mul(*Base::data_[10], *Base::data_[13]))) -
795 torch::mul(*Base::data_[8],
796 (torch::mul(*Base::data_[1], *Base::data_[14]) -
797 torch::mul(*Base::data_[2], *Base::data_[13]))) -
798 torch::mul(*Base::data_[12],
799 (torch::mul(*Base::data_[2], *Base::data_[9]) -
800 torch::mul(*Base::data_[1], *Base::data_[10])));
801
802 auto a43 = torch::mul(*Base::data_[0],
803 (torch::mul(*Base::data_[6], *Base::data_[13]) -
804 torch::mul(*Base::data_[5], *Base::data_[14]))) -
805 torch::mul(*Base::data_[4],
806 (torch::mul(*Base::data_[2], *Base::data_[13]) -
807 torch::mul(*Base::data_[1], *Base::data_[14]))) -
808 torch::mul(*Base::data_[12],
809 (torch::mul(*Base::data_[1], *Base::data_[6]) -
810 torch::mul(*Base::data_[2], *Base::data_[5])));
811
812 auto a44 = torch::mul(*Base::data_[0],
813 (torch::mul(*Base::data_[5], *Base::data_[10]) -
814 torch::mul(*Base::data_[6], *Base::data_[9]))) -
815 torch::mul(*Base::data_[4],
816 (torch::mul(*Base::data_[1], *Base::data_[10]) -
817 torch::mul(*Base::data_[2], *Base::data_[9]))) -
818 torch::mul(*Base::data_[8],
819 (torch::mul(*Base::data_[2], *Base::data_[5]) -
820 torch::mul(*Base::data_[1], *Base::data_[6])));
821
823 result[0] = std::make_shared<T>(torch::div(a11, det_));
824 result[1] = std::make_shared<T>(torch::div(a21, det_));
825 result[2] = std::make_shared<T>(torch::div(a31, det_));
826 result[3] = std::make_shared<T>(torch::div(a41, det_));
827 result[4] = std::make_shared<T>(torch::div(a12, det_));
828 result[5] = std::make_shared<T>(torch::div(a22, det_));
829 result[6] = std::make_shared<T>(torch::div(a32, det_));
830 result[7] = std::make_shared<T>(torch::div(a42, det_));
831 result[8] = std::make_shared<T>(torch::div(a13, det_));
832 result[9] = std::make_shared<T>(torch::div(a23, det_));
833 result[10] = std::make_shared<T>(torch::div(a33, det_));
834 result[11] = std::make_shared<T>(torch::div(a43, det_));
835 result[12] = std::make_shared<T>(torch::div(a14, det_));
836 result[13] = std::make_shared<T>(torch::div(a24, det_));
837 result[14] = std::make_shared<T>(torch::div(a34, det_));
838 result[15] = std::make_shared<T>(torch::div(a44, det_));
839 return result;
840 } else {
841 throw std::runtime_error("Unsupported block tensor dimension");
842 return *this;
843 }
844 }
845
856 inline auto ginvtr() const {
857 if constexpr (Rows == Cols)
858 return this->invtr();
859 else
860 // Compute the transpose of the generalized inverse, i.e. A (A^T A)^{-T}
861 return (*this) * (this->tr() * (*this)).invtr();
862 }
863
866 inline auto trace() const {
867 static_assert(Rows == Cols, "trace(.) requires square block tensor");
868
869 if constexpr (Rows == 1)
870 return BlockTensor<T, 1, 1>(*Base::data_[0]);
871
872 else if constexpr (Rows == 2)
873 return BlockTensor<T, 1, 1>(*Base::data_[0] + *Base::data_[3]);
874
875 else if constexpr (Rows == 3)
876 return BlockTensor<T, 1, 1>(*Base::data_[0] + *Base::data_[4] +
877 *Base::data_[8]);
878
879 else if constexpr (Rows == 4)
880 return BlockTensor<T, 1, 1>(*Base::data_[0] + *Base::data_[5] +
881 *Base::data_[10] + *Base::data_[15]);
882
883 else
884 throw std::runtime_error("Unsupported block tensor dimension");
885 }
886
887private:
889 template <std::size_t... Is>
890 inline auto norm_(std::index_sequence<Is...>) const {
891 return torch::sqrt(
892 std::apply([](const auto &...tensors) { return (tensors + ...); },
893 std::make_tuple(std::get<Is>(Base::data_)->square()...)));
894 }
895
896public:
899 inline auto norm() const {
901 std::make_shared<T>(norm_(std::make_index_sequence<Rows * Cols>{})));
902 }
903
904private:
906 template <std::size_t... Is>
907 inline auto normalize_(std::index_sequence<Is...> is) const {
908 auto n_ = norm_(is);
910 std::make_shared<T>(*std::get<Is>(Base::data_) / n_)...);
911 }
912
913public:
916 inline auto normalize() const {
917 return normalize_(std::make_index_sequence<Rows * Cols>{});
918 }
919
920private:
922 template <std::size_t... Is>
923 inline auto dot_(std::index_sequence<Is...>,
924 const BlockTensor<T, Rows, Cols> &other) const {
925 return std::apply(
926 [](const auto &...tensors) { return (tensors + ...); },
927 std::make_tuple(torch::mul(*std::get<Is>(Base::data_),
928 *std::get<Is>(other.data_))...));
929 }
930
931public:
935 inline auto dot(const BlockTensor<T, Rows, Cols> &other) const {
936 return BlockTensor<T, 1, 1>(std::make_shared<T>(
937 dot_(std::make_index_sequence<Rows * Cols>{}, other)));
938 }
939
942 inline void pretty_print(std::ostream &os) const noexcept override {
943 os << Base::name() << "\n";
944 for (std::size_t row = 0; row < Rows; ++row)
945 for (std::size_t col = 0; col < Cols; ++col)
946 os << "[" << row << "," << col << "] = \n"
947 << *Base::data_[Cols * row + col] << "\n";
948 }
949};
950
956template <typename T, typename U, std::size_t Rows, std::size_t Common,
957 std::size_t Cols>
959 const BlockTensor<U, Common, Cols> &rhs) {
960 BlockTensor<std::common_type_t<T, U>, Rows, Cols> result;
961 for (std::size_t row = 0; row < Rows; ++row)
962 for (std::size_t col = 0; col < Cols; ++col) {
963 T tmp =
964 (lhs[Common * row]->dim() > rhs[col]->dim()
965 ? torch::mul(*lhs[Common * row], rhs[col]->unsqueeze(-1))
966 : (lhs[Common * row]->dim() < rhs[col]->dim()
967 ? torch::mul(lhs[Common * row]->unsqueeze(-1), *rhs[col])
968 : torch::mul(*lhs[Common * row], *rhs[col])));
969 for (std::size_t idx = 1; idx < Common; ++idx)
970 tmp += (lhs[Common * row]->dim() > rhs[col]->dim()
971 ? torch::mul(*lhs[Common * row + idx],
972 rhs[Cols * idx + col]->unsqueeze(-1))
973 : (lhs[Common * row]->dim() < rhs[col]->dim()
974 ? torch::mul(lhs[Common * row + idx]->unsqueeze(-1),
975 *rhs[Cols * idx + col])
976 : torch::mul(*lhs[Common * row + idx],
977 *rhs[Cols * idx + col])));
978 result[Cols * row + col] = std::make_shared<T>(tmp);
979 }
980 return result;
981}
982
989template <typename T, std::size_t Rows, std::size_t Cols, std::size_t Slices>
990class BlockTensor<T, Rows, Cols, Slices>
991 : public BlockTensorCore<T, Rows, Cols, Slices> {
992private:
994
995public:
996 using BlockTensorCore<T, Rows, Cols, Slices>::BlockTensorCore;
997
1000 inline static constexpr std::size_t rows() { return Rows; }
1001
1004 inline static constexpr std::size_t cols() { return Cols; }
1005
1008 inline static constexpr std::size_t slices() { return Slices; }
1009
1010 using Base::operator();
1011
1014 inline const T &operator()(std::size_t row, std::size_t col,
1015 std::size_t slice) const {
1016 assert(row < Rows && col < Cols && slice < Slices);
1017 return *Base::data_[Rows * Cols * slice + Cols * row + col];
1018 }
1019
1022 inline T &operator()(std::size_t row, std::size_t col, std::size_t slice) {
1023 assert(row < Rows && col < Cols && slice < Slices);
1024 return *Base::data_[Rows * Cols * slice + Cols * row + col];
1025 }
1026
1027 using Base::set;
1028
1036 template <typename D>
1037 inline T &set(std::size_t row, std::size_t col, std::size_t slice, D &&data) {
1038 assert(row < Rows && col < Cols && slice < Slices);
1039 Base::data_[Rows * Cols * slice + Cols * row + col] =
1040 make_shared<D>(std::forward<D>(data));
1041 return *Base::data_[Rows * Cols * slice + Cols * row + col];
1042 }
1043
1047 inline auto slice(std::size_t slice) const {
1048 assert(slice < Slices);
1050 for (std::size_t row = 0; row < Rows; ++row)
1051 for (std::size_t col = 0; col < Cols; ++col)
1052 result[Cols * row + col] =
1053 Base::data_[Rows * Cols * slice + Cols * row + col];
1054 return result;
1055 }
1056
1060 inline auto reorder_ikj() const {
1062 for (std::size_t slice = 0; slice < Slices; ++slice)
1063 for (std::size_t row = 0; row < Rows; ++row)
1064 for (std::size_t col = 0; col < Cols; ++col)
1065 result[Rows * Slices * col + Slices * row + slice] =
1066 Base::data_[Rows * Cols * slice + Cols * row + col];
1067 return result;
1068 }
1069
1074 inline auto reorder_jik() const {
1076 for (std::size_t slice = 0; slice < Slices; ++slice)
1077 for (std::size_t row = 0; row < Rows; ++row)
1078 for (std::size_t col = 0; col < Cols; ++col)
1079 result[Rows * Cols * slice + Rows * col + row] =
1080 Base::data_[Rows * Cols * slice + Cols * row + col];
1081 return result;
1082 }
1083
1087 inline auto reorder_kji() const {
1089 for (std::size_t slice = 0; slice < Slices; ++slice)
1090 for (std::size_t row = 0; row < Rows; ++row)
1091 for (std::size_t col = 0; col < Cols; ++col)
1092 result[Slices * Cols * row + Cols * slice + col] =
1093 Base::data_[Rows * Cols * slice + Cols * row + col];
1094 return result;
1095 }
1096
1100 inline auto reorder_kij() const {
1102 for (std::size_t slice = 0; slice < Slices; ++slice)
1103 for (std::size_t row = 0; row < Rows; ++row)
1104 for (std::size_t col = 0; col < Cols; ++col)
1105 result[Slices * Rows * col + Rows * slice + row] =
1106 Base::data_[Rows * Cols * slice + Cols * row + col];
1107 return result;
1108 }
1109
1112 inline void pretty_print(std::ostream &os) const noexcept override {
1113 os << Base::name() << "\n";
1114 for (std::size_t slice = 0; slice < Slices; ++slice)
1115 for (std::size_t row = 0; row < Rows; ++row)
1116 for (std::size_t col = 0; col < Cols; ++col)
1117 os << "[" << row << "," << col << "," << slice << "] = \n"
1118 << *Base::data_[Rows * Cols * slice + Cols * row + col] << "\n";
1119 }
1120};
1121
1127template <typename T, typename U, std::size_t Rows, std::size_t Common,
1128 std::size_t Cols, std::size_t Slices>
1131 BlockTensor<std::common_type_t<T, U>, Rows, Cols, Slices> result;
1132 for (std::size_t slice = 0; slice < Slices; ++slice)
1133 for (std::size_t row = 0; row < Rows; ++row)
1134 for (std::size_t col = 0; col < Cols; ++col) {
1135 T tmp =
1136 (lhs[Common * row]->dim() > rhs[Rows * Cols * slice + col]->dim()
1137 ? torch::mul(*lhs[Common * row],
1138 rhs[Rows * Cols * slice + col]->unsqueeze(-1))
1139 : (lhs[Common * row]->dim() <
1140 rhs[Rows * Cols * slice + col]->dim()
1141 ? torch::mul(lhs[Common * row]->unsqueeze(-1),
1142 *rhs[Rows * Cols * slice + col])
1143 : torch::mul(*lhs[Common * row],
1144 *rhs[Rows * Cols * slice + col])));
1145 for (std::size_t idx = 1; idx < Common; ++idx)
1146 tmp +=
1147 (lhs[Common * row]->dim() > rhs[Rows * Cols * slice + col]->dim()
1148 ? torch::mul(
1149 *lhs[Common * row + idx],
1150 rhs[Rows * Cols * slice + Cols * idx + col]->unsqueeze(
1151 -1))
1152 : (lhs[Common * row]->dim() <
1153 rhs[Rows * Cols * slice + col]->dim()
1154 ? torch::mul(
1155 lhs[Common * row + idx]->unsqueeze(-1),
1156 *rhs[Rows * Cols * slice + Cols * idx + col])
1157 : torch::mul(
1158 *lhs[Common * row + idx],
1159 *rhs[Rows * Cols * slice + Cols * idx + col])));
1160 result[Rows * Cols * slice + Cols * row + col] =
1161 std::make_shared<T>(tmp);
1162 }
1163 return result;
1164}
1165
1171template <typename T, typename U, std::size_t Rows, std::size_t Common,
1172 std::size_t Cols, std::size_t Slices>
1174 const BlockTensor<U, Common, Cols> &rhs) {
1175 BlockTensor<std::common_type_t<T, U>, Rows, Cols, Slices> result;
1176 auto multiply = [](const auto &left, const auto &right) {
1177 return left.dim() > right.dim()
1178 ? torch::mul(left, right.unsqueeze(-1))
1179 : (left.dim() < right.dim()
1180 ? torch::mul(left.unsqueeze(-1), right)
1181 : torch::mul(left, right));
1182 };
1183 for (std::size_t slice = 0; slice < Slices; ++slice)
1184 for (std::size_t row = 0; row < Rows; ++row)
1185 for (std::size_t col = 0; col < Cols; ++col) {
1186 const auto lhs_offset = Rows * Common * slice + Common * row;
1187 T tmp = multiply(*lhs[lhs_offset], *rhs[col]);
1188 for (std::size_t idx = 1; idx < Common; ++idx)
1189 tmp += multiply(*lhs[lhs_offset + idx], *rhs[Cols * idx + col]);
1190 result[Rows * Cols * slice + Cols * row + col] =
1191 std::make_shared<T>(tmp);
1192 }
1193 return result;
1194}
1195
1198#define blocktensor_unary_op(name) \
1199 \
1203 template <typename T, std::size_t... Dims> \
1204 inline auto name(const BlockTensor<T, Dims...> &input) { \
1205 BlockTensor<T, Dims...> result; \
1206 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) \
1207 result[idx] = std::make_shared<T>(torch::name(*input[idx])); \
1208 return result; \
1209 }
1213#define blocktensor_unary_special_op(name) \
1214 \
1218 template <typename T, std::size_t... Dims> \
1219 inline auto name(const BlockTensor<T, Dims...> &input) { \
1220 BlockTensor<T, Dims...> result; \
1221 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) \
1222 result[idx] = std::make_shared<T>(torch::special::name(*input[idx])); \
1223 return result; \
1224 }
1225
1228#define blocktensor_binary_op(name) \
1229
\
1235 template <typename T, typename U, std::size_t... Dims> \
1236 inline auto name(const BlockTensor<T, Dims...> &input, \
1237 const BlockTensor<U, Dims...> &other) { \
1238 BlockTensor<typename std::common_type<T, U>::type, Dims...> result; \
1239 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) \
1240 result[idx] = \
1241 std::make_shared<T>(torch::name(*input[idx], *other[idx])); \
1242 return result; \
1243 }
1244
1247#define blocktensor_binary_special_op(name) \
1248 \
1254 template <typename T, typename U, std::size_t... Dims> \
1255 inline auto name(const BlockTensor<T, Dims...> &input, \
1256 const BlockTensor<U, Dims...> &other) { \
1257 BlockTensor<typename std::common_type<T, U>::type, Dims...> result; \
1258 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) \
1259 result[idx] = \
1260 std::make_shared<T>(torch::special::name(*input[idx], *other[idx])); \
1261 return result; \
1262 }
1263
1267
1271
1290template <typename T, typename U, typename V, std::size_t... Dims>
1291inline auto add(const BlockTensor<T, Dims...> &input,
1292 const BlockTensor<U, Dims...> &other, V alpha = 1.0) {
1300 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1301 result[idx] =
1302 std::make_shared<T>(torch::add(*input[idx], *other[idx], alpha));
1303 return result;
1304}
1305
1308template <typename T, typename U, typename V, std::size_t... Dims>
1309inline auto add(const BlockTensor<T, Dims...> &input, U other, V alpha = 1.0) {
1310 BlockTensor<T, Dims...> result;
1311 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1312 result[idx] = std::make_shared<T>(torch::add(*input[idx], other, alpha));
1313 return result;
1314}
1315
1326template <typename T, typename U, typename V, std::size_t... Dims>
1327inline auto add(T input, const BlockTensor<U, Dims...> &other, V alpha = 1.0) {
1328 BlockTensor<U, Dims...> result;
1329 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1330 result[idx] = std::make_shared<T>(torch::add(input, *other[idx], alpha));
1331 return result;
1332}
1333
1337template <typename T, typename U, typename V, typename W, std::size_t... Dims>
1338inline auto addcdiv(const BlockTensor<T, Dims...> &input,
1339 const BlockTensor<U, Dims...> &tensor1,
1340 const BlockTensor<V, Dims...> &tensor2, W value = 1.0) {
1342 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1343 result[idx] = std::make_shared<T>(
1344 torch::addcdiv(*input[idx], *tensor1[idx], *tensor2[idx], value));
1345 return result;
1346}
1347
1352template <typename T, typename U, typename V, typename W, std::size_t... Dims>
1353inline auto addcmul(const BlockTensor<T, Dims...> &input,
1354 const BlockTensor<U, Dims...> &tensor1,
1355 const BlockTensor<V, Dims...> &tensor2, W value = 1.0) {
1357 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1358 result[idx] = std::make_shared<T>(
1359 torch::addcmul(*input[idx], *tensor1[idx], *tensor2[idx], value));
1360 return result;
1361}
1362
1366
1373
1380
1384
1387
1391
1394
1399
1400#if TORCH_VERSION_MAJOR >= 1 && TORCH_VERSION_MINOR >= 11 || \
1401 TORCH_VERSION_MAJOR >= 2
1403blocktensor_binary_op(arctan2);
1404#endif
1417
1422
1426
1430
1435
1438template <typename T, typename U, std::size_t... Dims>
1439inline auto clamp(const BlockTensor<T, Dims...> &input, U min, U max) {
1440 BlockTensor<T, Dims...> result;
1441 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1442 result[idx] = std::make_shared<T>(torch::clamp(*input[idx], min, max));
1443 return result;
1444}
1447template <typename T, typename U, std::size_t... Dims>
1448inline auto clip(const BlockTensor<T, Dims...> &input, U min, U max) {
1449 BlockTensor<T, Dims...> result;
1450 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1451 result[idx] = std::make_shared<T>(torch::clip(*input[idx], min, max));
1452 return result;
1454
1458
1462
1466
1470
1478
1481
1485
1488template <typename T, std::size_t Rows, std::size_t Cols>
1489inline auto dot(const BlockTensor<T, Rows, Cols> &input,
1490 const BlockTensor<T, Rows, Cols> &tensor) {
1491 return input.dot(tensor);
1493
1497
1501
1505
1509
1513
1517
1525
1529
1533
1554
1558
1562
1566
1570
1574
1578
1583
1586
1590
1596
1599
1604
1611
1618
1625
1629
1632
1636
1639
1643
1647
1651
1655
1659
1663
1667
1671
1674
1678
1682
1686
1690
1702
1706
1708template <typename T, typename U, typename V, std::size_t... Dims>
1709inline auto sub(const BlockTensor<T, Dims...> &input,
1710 const BlockTensor<U, Dims...> &other, V alpha = 1.0) {
1711 BlockTensor<std::common_type_t<T, U>, Dims...> result;
1712 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1713 result[idx] =
1714 std::make_shared<T>(torch::sub(*input[idx], *other[idx], alpha));
1715 return result;
1716}
1717
1719template <typename T, typename U, typename V, std::size_t... Dims>
1720inline auto subtract(const BlockTensor<T, Dims...> &input,
1721 const BlockTensor<U, Dims...> &other, V alpha = 1.0) {
1722 BlockTensor<std::common_type_t<T, U>, Dims...> result;
1723 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1724 result[idx] =
1725 std::make_shared<T>(torch::sub(*input[idx], *other[idx], alpha));
1726 return result;
1727}
1731
1735
1740
1741
1743
1751template <typename T, typename U, std::size_t... Dims>
1752inline auto operator+(const BlockTensor<T, Dims...> &lhs,
1753 const BlockTensor<U, Dims...> &rhs) {
1759 BlockTensor<std::common_type_t<T, U>, Dims...> result;
1760 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1761 result[idx] = std::make_shared<T>(*lhs[idx] + *rhs[idx]);
1762 return result;
1763}
1764
1767template <typename T, typename U, std::size_t... Dims>
1768inline auto operator+(const BlockTensor<T, Dims...> &lhs, const U &rhs) {
1774 BlockTensor<T, Dims...> result;
1775 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1776 result[idx] = std::make_shared<T>(*lhs[idx] + rhs);
1777 return result;
1778}
1779
1788template <typename T, typename U, std::size_t... Dims>
1789inline auto operator+(const T &lhs, const BlockTensor<U, Dims...> &rhs) {
1790 BlockTensor<U, Dims...> result;
1791 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1792 result[idx] = std::make_shared<U>(lhs + *rhs[idx]);
1793 return result;
1794}
1802template <typename T, typename U, std::size_t... Dims>
1803inline auto operator+=(BlockTensor<T, Dims...> &lhs,
1804 const BlockTensor<U, Dims...> &rhs) {
1805 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1806 lhs[idx] = std::make_shared<T>(*lhs[idx] + *rhs[idx]);
1807 return lhs;
1808}
1809
1811template <typename T, typename U, std::size_t... Dims>
1812inline auto operator+=(BlockTensor<T, Dims...> &lhs, const U &rhs) {
1818 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1819 lhs[idx] = std::make_shared<T>(*lhs[idx] + rhs);
1820 return lhs;
1821}
1822
1825template <typename T, typename U, std::size_t... Dims>
1826inline auto operator-(const BlockTensor<T, Dims...> &lhs,
1827 const BlockTensor<U, Dims...> &rhs) {
1833 BlockTensor<std::common_type_t<T, U>, Dims...> result;
1834 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1835 result[idx] = std::make_shared<T>(*lhs[idx] - *rhs[idx]);
1836 return result;
1837}
1838
1841template <typename T, typename U, std::size_t... Dims>
1842inline auto operator-(const BlockTensor<T, Dims...> &lhs, const U &rhs) {
1843 BlockTensor<T, Dims...> result;
1844 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1845 result[idx] = std::make_shared<T>(*lhs[idx] - rhs);
1846 return result;
1847}
1848
1857template <typename T, typename U, std::size_t... Dims>
1858inline auto operator-(const T &lhs, const BlockTensor<U, Dims...> &rhs) {
1859 BlockTensor<U, Dims...> result;
1860 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1861 result[idx] = std::make_shared<U>(lhs - *rhs[idx]);
1862 return result;
1863}
1871template <typename T, typename U, std::size_t... Dims>
1872inline auto operator-=(BlockTensor<T, Dims...> &lhs,
1873 const BlockTensor<U, Dims...> &rhs) {
1874 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1875 lhs[idx] = std::make_shared<T>(*lhs[idx] - *rhs[idx]);
1876 return lhs;
1877}
1878
1880template <typename T, typename U, std::size_t... Dims>
1881inline auto operator-=(BlockTensor<T, Dims...> &lhs, const U &rhs) {
1882 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1883 lhs[idx] = std::make_shared<T>(*lhs[idx] - rhs);
1884 return lhs;
1885}
1886
1895template <typename T, typename U, std::size_t... Dims>
1896inline auto operator*(const BlockTensor<T, Dims...> &lhs, const U &rhs) {
1897 BlockTensor<T, Dims...> result;
1898 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) {
1899 if constexpr (std::is_arithmetic_v<std::remove_cvref_t<U>>)
1900 result[idx] = std::make_shared<T>(*lhs[idx] * rhs);
1901 else
1902 result[idx] =
1903 (lhs[idx]->dim() > rhs.dim()
1904 ? std::make_shared<T>(*lhs[idx] * rhs.unsqueeze(-1))
1905 : (lhs[idx]->dim() < rhs.dim()
1906 ? std::make_shared<T>(lhs[idx]->unsqueeze(-1) * rhs)
1907 : std::make_shared<T>(*lhs[idx] * rhs)));
1908 }
1909 return result;
1910}
1911
1920template <typename T, typename U, std::size_t... Dims>
1921inline auto operator*(const T &lhs, const BlockTensor<U, Dims...> &rhs) {
1922 BlockTensor<U, Dims...> result;
1923 for (std::size_t idx = 0; idx < (Dims * ...); ++idx) {
1924 if constexpr (std::is_arithmetic_v<std::remove_cvref_t<T>>)
1925 result[idx] = std::make_shared<U>(lhs * *rhs[idx]);
1926 else
1927 result[idx] =
1928 (lhs.dim() > rhs[idx]->dim()
1929 ? std::make_shared<U>(lhs * rhs[idx]->unsqueeze(-1))
1930 : (lhs.dim() < rhs[idx]->dim()
1931 ? std::make_shared<U>(lhs.unsqueeze(-1) * *rhs[idx])
1932 : std::make_shared<U>(lhs * *rhs[idx])));
1933 }
1934 return result;
1935}
1940
1942template <typename T, typename U, std::size_t... TDims, std::size_t... UDims>
1943inline bool operator==(const BlockTensor<T, TDims...> &lhs,
1944 const BlockTensor<U, UDims...> &rhs) {
1945 if constexpr ((sizeof...(TDims) != sizeof...(UDims)) ||
1946 ((TDims != UDims) || ...))
1947 return false;
1948
1949 bool result = true;
1950 for (std::size_t idx = 0; idx < (TDims * ...); ++idx)
1951 result = result && torch::equal(*lhs[idx], *rhs[idx]);
1952
1953 return result;
1954}
1955
1957template <typename T, typename U, std::size_t... TDims, std::size_t... UDims>
1958inline bool operator!=(const BlockTensor<T, TDims...> &lhs,
1959 const BlockTensor<U, UDims...> &rhs) {
1960 return !(lhs == rhs);
1961}
1962
1963} // namespace iganet::utils
#define blocktensor_unary_op(name)
Defines an element-wise unary block-tensor operation.
Definition blocktensor.hpp:1198
#define blocktensor_unary_special_op(name)
Defines an element-wise unary special-function operation.
Definition blocktensor.hpp:1210
#define blocktensor_binary_op(name)
Defines an element-wise binary block-tensor operation.
Definition blocktensor.hpp:1222
#define blocktensor_binary_special_op(name)
Defines an element-wise binary special-function operation.
Definition blocktensor.hpp:1236
static constexpr std::size_t slices()
Returns the number of slices.
Definition blocktensor.hpp:1008
auto reorder_jik() const
Returns a new block tensor with rows and columns transposed and slices remaining fixed....
Definition blocktensor.hpp:1074
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:1014
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:1037
auto reorder_kij() const
Returns a new block tensor with rows, columns, and slices permuted according to (i,...
Definition blocktensor.hpp:1100
auto reorder_ikj() const
Returns a new block tensor with rows, columns, and slices permuted according to (i,...
Definition blocktensor.hpp:1060
static constexpr std::size_t rows()
Returns the number of rows.
Definition blocktensor.hpp:1000
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:1022
auto reorder_kji() const
Returns a new block tensor with rows, columns, and slices permuted according to (i,...
Definition blocktensor.hpp:1087
auto slice(std::size_t slice) const
Returns a rank-2 tensor of the k-th slice.
Definition blocktensor.hpp:1047
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the BSplineCommon object.
Definition blocktensor.hpp:1112
static constexpr std::size_t cols()
Returns the number of columns.
Definition blocktensor.hpp:1004
auto inv() const
Returns the inverse of the block tensor.
Definition blocktensor.hpp:358
auto dot_(std::index_sequence< Is... >, const BlockTensor< T, Rows, Cols > &other) const
Returns the dot product of two BlockTensor objects.
Definition blocktensor.hpp:923
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the BlockTensor object.
Definition blocktensor.hpp:942
auto ginv() const
Returns the (generalized) inverse of the block tensor.
Definition blocktensor.hpp:598
auto ginvtr() const
Returns the transpose of the (generalized) inverse of the block tensor.
Definition blocktensor.hpp:856
auto tr() const
Returns the transpose of the block tensor.
Definition blocktensor.hpp:268
auto invtr() const
Returns the transpose of the inverse of the block tensor.
Definition blocktensor.hpp:612
static constexpr std::size_t cols()
Returns the number of columns.
Definition blocktensor.hpp:233
auto normalize_(std::index_sequence< Is... > is) const
Returns the normalized BlockTensor object.
Definition blocktensor.hpp:907
static constexpr std::size_t rows()
Returns the number of rows.
Definition blocktensor.hpp:229
auto norm() const
Returns the norm of the BlockTensor object.
Definition blocktensor.hpp:899
const T & operator()(std::size_t row, std::size_t col) const
Returns a constant reference to entry (row, col).
Definition blocktensor.hpp:239
T & set(std::size_t row, std::size_t col, D &&data)
Stores the given data object at the given position.
Definition blocktensor.hpp:260
auto dot(const BlockTensor< T, Rows, Cols > &other) const
Returns the dot product of two BlockTensor objects.
Definition blocktensor.hpp:935
auto trace() const
Returns the trace of the block tensor.
Definition blocktensor.hpp:866
auto det() const
Returns the determinant of a square block tensor.
Definition blocktensor.hpp:282
T & operator()(std::size_t row, std::size_t col)
Returns a non-constant reference to entry (row, col).
Definition blocktensor.hpp:246
auto norm_(std::index_sequence< Is... >) const
Returns the norm of the BlockTensor object.
Definition blocktensor.hpp:890
auto normalize() const
Returns the normalized BlockTensor object.
Definition blocktensor.hpp:916
void pretty_print(std::ostream &os) const noexcept override
Returns a string representation of the BlockTensor object.
Definition blocktensor.hpp:207
static constexpr std::size_t rows()
Returns the number of rows.
Definition blocktensor.hpp:203
Compile-time block tensor core.
Definition blocktensor.hpp:51
const std::array< std::shared_ptr< T >,(Dims *...)> & data() const
Returns a constant reference to the data array.
Definition blocktensor.hpp:125
static constexpr auto dims()
Returns all dimensions as array.
Definition blocktensor.hpp:101
BlockTensorCore(BlockTensorCore< Ts, dims... > &&...other)
Constructor from BlockTensorCore objects.
Definition blocktensor.hpp:66
BlockTensorCore(Ts &&...data)
Constructor from variadic templates.
Definition blocktensor.hpp:95
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:144
void pretty_print(std::ostream &os) const noexcept override=0
Returns a string representation of the BlockTensorCore object.
T & set(std::size_t idx, Data &&data)
Stores the given data object at the given index.
Definition blocktensor.hpp:168
static constexpr std::size_t dim()
Returns the i-th dimension.
Definition blocktensor.hpp:108
const std::shared_ptr< T > & operator[](std::size_t idx) const
Returns a constant shared pointer to entry (idx).
Definition blocktensor.hpp:136
BlockTensorCore(BlockTensor< Ts, dims... > &&...other)
Constructor from BlockTensor objects.
Definition blocktensor.hpp:81
static constexpr std::size_t entries()
Returns the total number of entries.
Definition blocktensor.hpp:121
std::array< std::shared_ptr< T >,(Dims *...)> & data()
Returns a non-constant reference to the data array.
Definition blocktensor.hpp:131
static constexpr std::size_t size()
Returns the number of dimensions.
Definition blocktensor.hpp:117
const T & operator()(std::size_t idx) const
Returns a constant reference to entry (idx).
Definition blocktensor.hpp:151
std::array< std::shared_ptr< T >,(Dims *...)> data_
Array storing the data.
Definition blocktensor.hpp:55
T & operator()(std::size_t idx)
Returns a non-constant reference to entry (idx).
Definition blocktensor.hpp:158
Full qualified name descriptor.
Definition fqn.hpp:22
Core components.
Full qualified name utility functions.
Definition blocktensor.hpp:24
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:1337
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:1553
auto tan(const BlockTensor< T, Dims... > &input)
Returns a new tensor with the tangent of the elements of input.
Definition blocktensor.hpp:1714
auto square(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the square of the elements of input.
Definition blocktensor.hpp:1689
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:1605
auto divide(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Alias for div().
Definition blocktensor.hpp:1464
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:1496
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:1524
auto xlogy(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Computes input * log(other).
Definition blocktensor.hpp:1726
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:1810
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:1512
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:1392
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:1587
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:1508
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:1646
auto hypot(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
logit.
Definition blocktensor.hpp:1582
auto imag(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the imaginary values of the elements of input.
Definition blocktensor.hpp:1528
auto atan(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the arctangent of the elements of input.
Definition blocktensor.hpp:1367
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:1445
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:1275
auto asin(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the arcsine of the elements of input.
Definition blocktensor.hpp:1353
bool operator==(const BlockTensor< T, TDims... > &lhs, const BlockTensor< U, UDims... > &rhs)
Provides the operator== operation.
Definition blocktensor.hpp:1927
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:1349
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:1619
auto arcsinh(const BlockTensor< T, Dims... > &input)
Alias for asinh().
Definition blocktensor.hpp:1363
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:1693
auto sign(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the signs of the elements of input.
Definition blocktensor.hpp:1661
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:1565
auto absolute(const BlockTensor< T, Dims... > &input)
Alias for abs().
Definition blocktensor.hpp:1254
auto fix(const BlockTensor< T, Dims... > &input)
Alias for trunc().
Definition blocktensor.hpp:1503
auto sinc(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the normalized sinc of the elements of input.
Definition blocktensor.hpp:1677
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:1569
auto positive(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the input.
Definition blocktensor.hpp:1622
auto sqrt(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the square-root of the elements of input.
Definition blocktensor.hpp:1685
auto reciprocal(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the reciprocal of the elements of input.
Definition blocktensor.hpp:1638
auto clip(const BlockTensor< T, Dims... > &input, U min, U max)
Alias for clamp().
Definition blocktensor.hpp:1432
auto arcsin(const BlockTensor< T, Dims... > &input)
Alias for asin().
Definition blocktensor.hpp:1356
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:1400
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:1374
auto subtract(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other, V alpha=1.0)
Alias for sub().
Definition blocktensor.hpp:1704
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:1382
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:1654
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:1650
auto sin(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the sine of the elements of input.
Definition blocktensor.hpp:1673
auto cosh(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the hyperbolic cosine of the elements of input.
Definition blocktensor.hpp:1453
std::ostream & operator<<(std::ostream &os, const BlockTensorCore< T, Dims... > &obj)
Prints (as string) a compile-time block tensor object.
Definition blocktensor.hpp:186
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:1396
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:1484
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:1591
auto operator-=(BlockTensor< T, Dims... > &lhs, const BlockTensor< U, Dims... > &rhs)
Decrements one compile-time block tensor by another.
Definition blocktensor.hpp:1856
auto arccos(const BlockTensor< T, Dims... > &input)
Alias for acos().
Definition blocktensor.hpp:1261
auto negative(const BlockTensor< T, Dims... > &input)
Alias for neg().
Definition blocktensor.hpp:1615
auto multiply(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Alias for mul().
Definition blocktensor.hpp:1608
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:1473
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:1561
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:1626
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:1405
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:1532
auto igammac(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Alias for gammainc().
Definition blocktensor.hpp:1601
auto neg(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the negative of the elements of input.
Definition blocktensor.hpp:1612
auto exp(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the exponential of the elements of input.
Definition blocktensor.hpp:1492
auto arctan(const BlockTensor< T, Dims... > &input)
Alias for atan().
Definition blocktensor.hpp:1370
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:1549
auto arctanh(const BlockTensor< T, Dims... > &input)
Alias for atanh().
Definition blocktensor.hpp:1377
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:1418
auto trunc(const BlockTensor< T, Dims... > &input)
Returns a new tensor with the truncated integer values of the elements of input.
Definition blocktensor.hpp:1723
auto cos(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the cosine of the elements of input.
Definition blocktensor.hpp:1449
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:1488
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:1942
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:1500
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:1669
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:1441
auto sinh(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the hyperbolic sine of the elements of input.
Definition blocktensor.hpp:1681
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:1642
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:1468
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:1360
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:1461
auto igamma(const BlockTensor< T, Dims... > &input, const BlockTensor< U, Dims... > &other)
Alias for gammainc().
Definition blocktensor.hpp:1594
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:1409
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:1630
auto real(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the real values of the elements of input.
Definition blocktensor.hpp:1634
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:1537
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:1598
auto acos(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the inverse cosine of the elements of input.
Definition blocktensor.hpp:1258
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:1516
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:1413
auto operator+=(BlockTensor< T, Dims... > &lhs, const BlockTensor< U, Dims... > &rhs)
Increments one compile-time block tensor by another.
Definition blocktensor.hpp:1787
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:1665
auto arccosh(const BlockTensor< T, Dims... > &input)
Provides the acosh operation.
Definition blocktensor.hpp:1270
auto abs(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the absolute value of the elements of input.
Definition blocktensor.hpp:1250
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:1577
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:1322
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:1457
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:1557
auto erf(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the error function of the elements of input.
Definition blocktensor.hpp:1480
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:958
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:1545
auto make_shared(T &&arg)
Returns a std::shared_ptr<T> object from arg.
Definition blocktensor.hpp:39
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:1265
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:1423
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:1573
auto frac(const BlockTensor< T, Dims... > &input)
Returns a new block tensor with the fractional portion of the elements of input.
Definition blocktensor.hpp:1520
Forward declaration of BlockTensor.
Definition blocktensor.hpp:47
constexpr auto operator+(deriv lhs, deriv rhs)
Adds two enumerators for specifying the derivative of B-spline evaluation.
Definition bspline.hpp:93
log
Enumerator for specifying the logging level.
Definition core.hpp:102
@ right
Definition boundary.hpp:35
@ left
Definition boundary.hpp:34
STL namespace.
Type trait checks if template argument is of type std::shared_ptr<T>
Definition blocktensor.hpp:28