41 return std::forward<std::decay_t<T>>(arg);
43 return std::make_shared<std::decay_t<T>>(std::forward<T>(arg));
50template <
typename T, std::size_t... Dims>
55 std::array<std::shared_ptr<T>, (Dims * ...)>
data_;
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) {
71 return std::forward<D>(d);
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) {
86 return std::forward<D>(d);
94 template <
typename... Ts>
96 :
data_({make_shared<Ts>(std::forward<Ts>(
data))...}) {}
101 inline static constexpr auto dims() {
102 return std::array<std::size_t,
sizeof...(Dims)>({Dims...});
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...));
117 inline static constexpr std::size_t
size() {
return sizeof...(Dims); }
121 inline static constexpr std::size_t
entries() {
return (Dims * ...); }
125 inline const std::array<std::shared_ptr<T>, (Dims * ...)> &
data()
const {
131 inline std::array<std::shared_ptr<T>, (Dims * ...)> &
data() {
return data_; }
136 inline const std::shared_ptr<T> &
operator[](std::size_t idx)
const {
137 assert(idx < (Dims * ...));
145 assert(idx < (Dims * ...));
152 assert(idx < (Dims * ...));
159 assert(idx < (Dims * ...));
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));
176 inline void pretty_print(std::ostream &os)
const noexcept override = 0;
185template <
typename T, std::size_t... Dims>
193template <
typename T, std::
size_t Rows>
203 inline static constexpr std::size_t
rows() {
return Rows; }
208 os << Base::name() <<
"\n";
209 for (std::size_t row = 0; row < Rows; ++row)
210 os <<
"[" << row <<
"] = \n" << *Base::data_[row] <<
"\n";
219template <
typename T, std::
size_t Rows, std::
size_t Cols>
229 inline static constexpr std::size_t
rows() {
return Rows; }
233 inline static constexpr std::size_t
cols() {
return Cols; }
235 using Base::operator();
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];
247 assert(row < Rows && col < Cols);
248 return *Base::data_[Cols * row + col];
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];
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];
283 if constexpr (Rows == 1 && Cols == 1) {
284 auto result = *Base::data_[0];
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]);
290 }
else if constexpr (Rows == 3 && Cols == 3) {
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]));
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])));
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])));
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])));
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])));
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);
349 throw std::runtime_error(
"Unsupported block tensor dimension");
360 auto det_ = this->det();
362 if constexpr (Rows == 1 && Cols == 1) {
364 result[0] = std::make_shared<T>(torch::reciprocal(*Base::data_[0]));
366 }
else if constexpr (Rows == 2 && Cols == 2) {
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_));
374 }
else if constexpr (Rows == 3 && Cols == 3) {
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]);
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_));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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_));
585 throw std::runtime_error(
"Unsupported block tensor dimension");
599 if constexpr (Rows == Cols)
603 return (this->tr() * (*this)).inv() * this->tr();
614 auto det_ = this->det();
616 if constexpr (Rows == 1 && Cols == 1) {
618 result[0] = std::make_shared<T>(torch::reciprocal(*Base::data_[0]));
620 }
else if constexpr (Rows == 2 && Cols == 2) {
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_));
628 }
else if constexpr (Rows == 3 && Cols == 3) {
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]);
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_));
660 }
else if constexpr (Rows == 4 && Cols == 4) {
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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])));
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_));
841 throw std::runtime_error(
"Unsupported block tensor dimension");
857 if constexpr (Rows == Cols)
858 return this->invtr();
861 return (*
this) * (this->tr() * (*this)).invtr();
867 static_assert(Rows == Cols,
"trace(.) requires square block tensor");
869 if constexpr (Rows == 1)
872 else if constexpr (Rows == 2)
875 else if constexpr (Rows == 3)
879 else if constexpr (Rows == 4)
881 *Base::data_[10] + *Base::data_[15]);
884 throw std::runtime_error(
"Unsupported block tensor dimension");
889 template <std::size_t... Is>
890 inline auto norm_(std::index_sequence<Is...>)
const {
892 std::apply([](
const auto &...tensors) {
return (tensors + ...); },
893 std::make_tuple(std::get<Is>(Base::data_)->
square()...)));
901 std::make_shared<T>(norm_(std::make_index_sequence<Rows * Cols>{})));
906 template <std::size_t... Is>
907 inline auto normalize_(std::index_sequence<Is...> is)
const {
910 std::make_shared<T>(*std::get<Is>(Base::data_) / n_)...);
917 return normalize_(std::make_index_sequence<Rows * Cols>{});
922 template <std::size_t... Is>
923 inline auto dot_(std::index_sequence<Is...>,
926 [](
const auto &...tensors) {
return (tensors + ...); },
927 std::make_tuple(torch::mul(*std::get<Is>(Base::data_),
928 *std::get<Is>(other.data_))...));
937 dot_(std::make_index_sequence<Rows * Cols>{}, other)));
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";
956template <
typename T,
typename U, std::size_t Rows, std::size_t Common,
961 for (std::size_t row = 0; row < Rows; ++row)
962 for (std::size_t col = 0; col < Cols; ++col) {
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);
989template <
typename T, std::
size_t Rows, std::
size_t Cols, std::
size_t Slices>
1000 inline static constexpr std::size_t
rows() {
return Rows; }
1004 inline static constexpr std::size_t
cols() {
return Cols; }
1008 inline static constexpr std::size_t
slices() {
return Slices; }
1010 using Base::operator();
1015 std::size_t slice)
const {
1016 assert(row < Rows && col < Cols && slice < Slices);
1017 return *Base::data_[Rows * Cols * slice + Cols * row + col];
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];
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];
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];
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];
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];
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];
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];
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";
1127template <
typename T,
typename U, std::size_t Rows, std::size_t Common,
1128 std::size_t Cols, std::size_t Slices>
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) {
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)
1147 (lhs[Common * row]->dim() > rhs[Rows * Cols * slice + col]->dim()
1149 *lhs[Common * row + idx],
1150 rhs[Rows * Cols * slice + Cols * idx + col]->unsqueeze(
1152 : (lhs[Common * row]->dim() <
1153 rhs[Rows * Cols * slice + col]->dim()
1155 lhs[Common * row + idx]->unsqueeze(-1),
1156 *rhs[Rows * Cols * slice + Cols * idx + col])
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);
1171template <
typename T,
typename U, std::size_t Rows, std::size_t Common,
1172 std::size_t Cols, std::size_t Slices>
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);
1198#define blocktensor_unary_op(name) \
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])); \
1213#define blocktensor_unary_special_op(name) \
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])); \
1228#define blocktensor_binary_op(name) \
\
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) \
1241 std::make_shared<T>(torch::name(*input[idx], *other[idx])); \
1247#define blocktensor_binary_special_op(name) \
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) \
1260 std::make_shared<T>(torch::special::name(*input[idx], *other[idx])); \
1290template <
typename T,
typename U,
typename V, std::size_t... Dims>
1300 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1302 std::make_shared<T>(torch::add(*input[idx], *other[idx], alpha));
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));
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));
1337template <
typename T,
typename U,
typename V,
typename W, std::size_t... Dims>
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));
1352template <
typename T,
typename U,
typename V,
typename W, std::size_t... Dims>
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));
1400#if TORCH_VERSION_MAJOR >= 1 && TORCH_VERSION_MINOR >= 11 || \
1401 TORCH_VERSION_MAJOR >= 2
1438template <
typename T,
typename U, std::size_t... Dims>
1441 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1442 result[idx] = std::make_shared<T>(torch::clamp(*input[idx], min, max));
1447template <
typename T,
typename U, std::size_t... Dims>
1450 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1451 result[idx] = std::make_shared<T>(torch::clip(*input[idx], min, max));
1488template <
typename T, std::
size_t Rows, std::
size_t Cols>
1491 return input.dot(tensor);
1708template <typename T, typename U, typename V,
std::
size_t... Dims>
1710 const
BlockTensor<U, Dims...> &other, V alpha = 1.0) {
1712 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1714 std::make_shared<T>(torch::sub(*input[idx], *other[idx], alpha));
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)
1725 std::make_shared<T>(torch::sub(*input[idx], *other[idx], alpha));
1751template <
typename T,
typename U, std::size_t... Dims>
1760 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1761 result[idx] = std::make_shared<T>(*lhs[idx] + *rhs[idx]);
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);
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]);
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]);
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);
1825template <
typename T,
typename U, std::size_t... Dims>
1834 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1835 result[idx] = std::make_shared<T>(*lhs[idx] - *rhs[idx]);
1841template <
typename T,
typename U, std::size_t... Dims>
1844 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1845 result[idx] = std::make_shared<T>(*lhs[idx] - rhs);
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]);
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]);
1880template <
typename T,
typename U, std::size_t... Dims>
1882 for (std::size_t idx = 0; idx < (Dims * ...); ++idx)
1883 lhs[idx] = std::make_shared<T>(*lhs[idx] - rhs);
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);
1903 (lhs[idx]->dim() > rhs.dim()
1904 ? std::make_shared<T>(*lhs[idx] * rhs.unsqueeze(-1))
1905 : (lhs[idx]->dim() < rhs.dim()
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]);
1928 (lhs.dim() > rhs[idx]->dim()
1929 ? std::make_shared<U>(lhs * rhs[idx]->unsqueeze(-1))
1930 : (lhs.dim() < rhs[idx]->dim()
1942template <
typename T,
typename U, std::size_t... TDims, std::size_t... UDims>
1945 if constexpr ((
sizeof...(TDims) !=
sizeof...(UDims)) ||
1946 ((TDims != UDims) || ...))
1950 for (std::size_t idx = 0; idx < (TDims * ...); ++idx)
1951 result = result && torch::equal(*lhs[idx], *rhs[idx]);
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);
#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
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
Type trait checks if template argument is of type std::shared_ptr<T>
Definition blocktensor.hpp:28