Grangeat-based 2D/3D image registration
Loading...
Searching...
No Matches
Vec.h
Go to the documentation of this file.
1#pragma once
2
3#include "Global.h"
4
5#include <array>
6
7namespace reg23 {
8
21template <typename T, std::size_t N> class Vec : public std::array<T, N> {
22public:
23 static_assert(N > 0, "Vec size must be greater than 0");
24
25 using ElementType = T;
26 static constexpr std::size_t dimensionality = N;
27
28 using Base = std::array<T, N>;
29
34 for (T &e : *this) {
35 e = T{};
36 }
37 }
38
43 : Base(
45 cuda::
46#endif
47 std::move(array)) {
48 }
49
53 __host__ __device__ Vec(std::initializer_list<T> l) : Base() {
54 int i = 0;
55 for (const T &e : l) {
56 (*this)[i] = e;
57 ++i;
58 }
59 }
60
64 __host__ __device__ static constexpr Vec Full(const T &value) {
65 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
66 return {{(indices, value)...}};
67 }(std::make_index_sequence<N>{});
68 }
69
73 __host__ __device__ static constexpr Vec Range(const T &start = T{0}, const T &step = T{1}) {
74 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
75 return {{start + static_cast<T>(indices) * step...}};
76 }(std::make_index_sequence<N>{});
77 }
78
82 __host__ __device__ static constexpr Vec FromIntArrayRef(const at::IntArrayRef &v) {
83 assert(v.size() == N);
84 Vec ret{};
85 int index = 0;
86 for (int64_t e : v) {
87 ret[index++] = static_cast<T>(e);
88 }
89 return ret;
90 }
91
98 __host__ static Vec FromTensor(const at::Tensor &t) {
99 assert(t.sizes() == at::IntArrayRef({N}));
100 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
101 return {{t[indices].item().template to<T>()...}};
102 }(std::make_index_sequence<N>{});
103 }
104
112 __host__ static constexpr Vec Identity() {
113 static_assert(std::is_same_v<std::remove_const_t<decltype(T::dimensionality)>, std::size_t>);
114 static_assert(T::dimensionality == N);
115 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
116 return {{[&]() -> T {
117 T ret = T::Full(0);
118 ret[indices] = typename T::ElementType{1};
119 return ret;
120 }()...}};
121 }(std::make_index_sequence<N>{});
122 }
123
132 __host__ static Vec FromTensor2D(const at::Tensor &t) {
133 static_assert(std::is_same_v<std::remove_const_t<decltype(T::dimensionality)>, std::size_t>);
134 assert(t.sizes() == at::IntArrayRef({N, T::dimensionality}));
135 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
136 return {{T::FromTensor(t.slice(1, indices, indices + 1).squeeze(1))...}};
137 }(std::make_index_sequence<N>{});
138 }
139
143 __host__ __device__ [[nodiscard]] constexpr at::IntArrayRef ToIntArrayRef() const {
144 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> at::IntArrayRef {
145 return at::IntArrayRef({(*this)[indices]...});
146 }(std::make_index_sequence<N>{});
147 }
148
152 __host__ [[nodiscard]] at::Tensor ToTensor(at::TensorOptions options = {}, bool nonOwning = false) const {
153 const at::Tensor retNonOwning = torch::from_blob(this->data(), {this->size()}, options);
154 return nonOwning ? retNonOwning : retNonOwning.clone();
155 }
156
161 __host__ __device__ [[nodiscard]] constexpr Vec Flipped() const {
162 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
163 return {{(*this)[N - 1 - indices]...}};
164 }(std::make_index_sequence<N>{});
165 }
166
171 __host__ __device__ [[nodiscard]] constexpr T Sum() const {
172 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> T {
173 return ((*this)[indices] + ...);
174 }(std::make_index_sequence<N>{});
175 }
176
181 __host__ __device__ [[nodiscard]] constexpr T Min() const {
182 T ret = (*this)[0];
183 [&]<std::size_t... indices>(std::index_sequence<indices...>) -> void {
184 ([&] {
185 if ((*this)[indices + 1] < ret) ret = (*this)[indices + 1];
186 }(), ...);
187 }(std::make_index_sequence<N - 1>{});
188 return ret;
189 }
190
195 __host__ __device__ [[nodiscard]] constexpr T Max() const {
196 T ret = (*this)[0];
197 [&]<std::size_t... indices>(std::index_sequence<indices...>) -> void {
198 ([&] {
199 if ((*this)[indices + 1] > ret) ret = (*this)[indices + 1];
200 }(), ...);
201 }(std::make_index_sequence<N - 1>{});
202 return ret;
203 }
204
210 __host__ __device__ [[nodiscard]] constexpr std::pair<T, T> MinMax() const {
211 std::pair<T, T> ret = {(*this)[0], (*this)[0]};
212 [&]<std::size_t... indices>(std::index_sequence<indices...>) -> void {
213 ([&] {
214 if ((*this)[indices + 1] < ret.first) ret.first = (*this)[indices + 1];
215 if ((*this)[indices + 1] > ret.second) ret.second = (*this)[indices + 1];
216 }(), ...);
217 }(std::make_index_sequence<N - 1>{});
218 return ret;
219 }
220
228 static_assert(std::is_floating_point_v<T>, "Can only de-homogenise floating-point vectors");
229 static_assert(N == 4, "Can only de-homogenise 4-length vectors");
230 return Vec<T, 3>{X(), Y(), Z()} / W();
231 }
232
237 template <typename newT> __host__ __device__ [[nodiscard]] constexpr Vec<newT, N> StaticCast() const {
238 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<newT, N> {
239 return {{static_cast<newT>((*this)[indices])...}};
240 }(std::make_index_sequence<N>{});
241 }
242
247 __host__ __device__ [[nodiscard]] constexpr T Length() const {
248 return sqrt(Apply(&Square<T>).Sum());
249 }
250
257 __host__ __device__ [[nodiscard]] constexpr bool BooleanAll() const {
258 static_assert(std::is_integral_v<T>, "Only integral types are supported for boolean 'all' operation");
259 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> bool {
260 return ((*this)[indices] && ...);
261 }(std::make_index_sequence<N>{});
262 }
263
270 __host__ __device__ [[nodiscard]] constexpr bool BooleanAny() const {
271 static_assert(std::is_integral_v<T>, "Only integral types are supported for boolean 'any' operation");
272 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> bool {
273 return ((*this)[indices] || ...);
274 }(std::make_index_sequence<N>{});
275 }
276
277 // Element-wise function:
278
285 template <typename newT> __host__ __device__ [[nodiscard]] constexpr Vec<newT, N> Apply(
286 const std::function<newT(T)> &f) const {
287 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<newT, N> {
288 return {{f((*this)[indices])...}};
289 }(std::make_index_sequence<N>{});
290 }
291
298 template <typename newT> __host__ __device__ [[nodiscard]] constexpr Vec<newT, N> Apply(
299 const std::function<newT(const T &)> &f) const {
300 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<newT, N> {
301 return {{f((*this)[indices])...}};
302 }(std::make_index_sequence<N>{});
303 }
304
311 template <typename newT> __host__ __device__ [[nodiscard]] constexpr Vec<newT, N> Apply(newT (*f)(T)) const {
312 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<newT, N> {
313 return {{f((*this)[indices])...}};
314 }(std::make_index_sequence<N>{});
315 }
316
323 template <typename newT> __host__ __device__ [[nodiscard]] constexpr Vec<newT, N>
324 Apply(newT (*f)(const T &)) const {
325 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<newT, N> {
326 return {{f((*this)[indices])...}};
327 }(std::make_index_sequence<N>{});
328 }
329
330 // Modification in place
331
336 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
337 ([&] { (*this)[indices] += other[indices]; }(), ...);
338 }(std::make_index_sequence<N>{});
339 return *this;
340 }
341
345 template <typename scalar_t> __host__ __device__ Vec &operator+=(const scalar_t &scalar) {
346 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
347 ([&] { (*this)[indices] += scalar; }(), ...);
348 }(std::make_index_sequence<N>{});
349 return *this;
350 }
351
356 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
357 ([&] { (*this)[indices] -= other[indices]; }(), ...);
358 }(std::make_index_sequence<N>{});
359 return *this;
360 }
361
365 template <typename scalar_t> __host__ __device__ Vec &operator-=(const scalar_t &scalar) {
366 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
367 ([&] { (*this)[indices] -= scalar; }(), ...);
368 }(std::make_index_sequence<N>{});
369 return *this;
370 }
371
376 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
377 ([&] { (*this)[indices] *= other[indices]; }(), ...);
378 }(std::make_index_sequence<N>{});
379 return *this;
380 }
381
385 template <typename scalar_t> __host__ __device__ Vec &operator*=(const scalar_t &scalar) {
386 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
387 ([&] { (*this)[indices] *= scalar; }(), ...);
388 }(std::make_index_sequence<N>{});
389 return *this;
390 }
391
396 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
397 ([&] { (*this)[indices] /= other[indices]; }(), ...);
398 }(std::make_index_sequence<N>{});
399 return *this;
400 }
401
405 template <typename scalar_t> __host__ __device__ Vec &operator/=(const scalar_t &scalar) {
406 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
407 ([&] { (*this)[indices] /= scalar; }(), ...);
408 }(std::make_index_sequence<N>{});
409 return *this;
410 }
411
412 // Named member accessors
413
417 __host__ __device__ [[nodiscard]] constexpr const T &X() const { return (*this)[0]; }
418
422 __host__ __device__ [[nodiscard]] constexpr T &X() { return (*this)[0]; }
423
427 __host__ __device__ [[nodiscard]] constexpr const T &Y() const {
428 static_assert(N > 1, "Vec size must be greater than 1 to access element Y");
429 return (*this)[1];
430 }
431
435 __host__ __device__ [[nodiscard]] constexpr T &Y() {
436 static_assert(N > 1, "Vec size must be greater than 1 to access element Y");
437 return (*this)[1];
438 }
439
443 __host__ __device__ [[nodiscard]] constexpr const T &Z() const {
444 static_assert(N > 2, "Vec size must be greater than 2 to access element Z");
445 return (*this)[2];
446 }
447
451 __host__ __device__ [[nodiscard]] constexpr T &Z() {
452 static_assert(N > 2, "Vec size must be greater than 2 to access element Z");
453 return (*this)[2];
454 }
455
459 __host__ __device__ [[nodiscard]] constexpr const T &W() const {
460 static_assert(N > 3, "Vec size must be greater than 3 to access element W");
461 return (*this)[3];
462 }
463
467 __host__ __device__ [[nodiscard]] constexpr T &W() {
468 static_assert(N > 3, "Vec size must be greater than 3 to access element W");
469 return (*this)[3];
470 }
471
475 __host__ __device__ [[nodiscard]] constexpr Vec<T, 2> XY() const { return {X(), Y()}; }
476
480 __host__ __device__ [[nodiscard]] constexpr Vec<T, 3> XYZ() const { return {X(), Y(), Z()}; }
481};
482
483// Element-wise addition: +
484
489template <typename T, std::size_t N> __host__ __device__ constexpr Vec<T, N> operator+(
490 const Vec<T, N> &lhs, const Vec<T, N> &rhs) {
491 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
492 return {{(lhs[indices] + rhs[indices])...}};
493 }(std::make_index_sequence<N>{});
494}
495
500template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator+(
501 const Vec<T, N> &lhs, const scalar_t &rhs) {
502 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
503 return {{(lhs[indices] + rhs)...}};
504 }(std::make_index_sequence<N>{});
505}
506
511template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator+(
512 const scalar_t &lhs, const Vec<T, N> &rhs) {
513 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
514 return {{(lhs + rhs[indices])...}};
515 }(std::make_index_sequence<N>{});
516}
517
518// Element-wise subtraction: -
519
524template <typename T, std::size_t N> __host__ __device__ constexpr Vec<T, N> operator-(
525 const Vec<T, N> &lhs, const Vec<T, N> &rhs) {
526 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
527 return {{(lhs[indices] - rhs[indices])...}};
528 }(std::make_index_sequence<N>{});
529}
530
535template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator-(
536 const Vec<T, N> &lhs, const scalar_t &rhs) {
537 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
538 return {{(lhs[indices] - rhs)...}};
539 }(std::make_index_sequence<N>{});
540}
541
546template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator-(
547 const scalar_t &lhs, const Vec<T, N> &rhs) {
548 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
549 return {{(lhs - rhs[indices])...}};
550 }(std::make_index_sequence<N>{});
551}
552
553// Element-wise multiplication: *
554
559template <typename T, std::size_t N> __host__ __device__ constexpr Vec<T, N> operator*(
560 const Vec<T, N> &lhs, const Vec<T, N> &rhs) {
561 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
562 return {{(lhs[indices] * rhs[indices])...}};
563 }(std::make_index_sequence<N>{});
564}
565
570template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator*(
571 const Vec<T, N> &lhs, const scalar_t &rhs) {
572 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
573 return {{(lhs[indices] * rhs)...}};
574 }(std::make_index_sequence<N>{});
575}
576
581template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator*(
582 const scalar_t &lhs, const Vec<T, N> &rhs) {
583 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
584 return {{(lhs * rhs[indices])...}};
585 }(std::make_index_sequence<N>{});
586}
587
588// Element-wise division: /
589
594template <typename T, std::size_t N> __host__ __device__ constexpr Vec<T, N> operator/(
595 const Vec<T, N> &lhs, const Vec<T, N> &rhs) {
596 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
597 return {{(lhs[indices] / rhs[indices])...}};
598 }(std::make_index_sequence<N>{});
599}
600
605template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator/(
606 const Vec<T, N> &lhs, const scalar_t &rhs) {
607 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
608 return {{(lhs[indices] / rhs)...}};
609 }(std::make_index_sequence<N>{});
610}
611
616template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator/(
617 const scalar_t &lhs, const Vec<T, N> &rhs) {
618 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
619 return {{(lhs / rhs[indices])...}};
620 }(std::make_index_sequence<N>{});
621}
622
623
624// Element-wise modulo: %
625
630template <typename T, std::size_t N> __host__ __device__ constexpr Vec<T, N> operator%(
631 const Vec<T, N> &lhs, const Vec<T, N> &rhs) {
632 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
633 return {{(lhs[indices] % rhs[indices])...}};
634 }(std::make_index_sequence<N>{});
635}
636
641template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator%(
642 const Vec<T, N> &lhs, const scalar_t &rhs) {
643 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
644 return {{(lhs[indices] % rhs)...}};
645 }(std::make_index_sequence<N>{});
646}
647
652template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<T, N> operator%(
653 const scalar_t &lhs, const Vec<T, N> &rhs) {
654 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<T, N> {
655 return {{(lhs % rhs[indices])...}};
656 }(std::make_index_sequence<N>{});
657}
658
659
660// Dot product
661
666template <typename T, std::size_t N> __host__ __device__ constexpr T
668 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> T {
669 return ((lhs[indices] * rhs[indices]) + ...);
670 }(std::make_index_sequence<N>{});
671}
672
673
674// Outer product
675
682template <typename T, std::size_t N1, std::size_t N2> __host__ __device__ constexpr Vec<Vec<T, N1>, N2> VecOuter(
683 const Vec<T, N1> &lhs, const Vec<T, N2> &rhs) {
684 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<Vec<T, N1>, N2> {
685 return {{rhs[indices] * lhs...}};
686 }(std::make_index_sequence<N2>{});
687}
688
689
690// Element-wise greater-than: >
691
697template <typename T, std::size_t N> __host__ __device__ constexpr Vec<bool, N> operator>(
698 const Vec<T, N> &lhs, const Vec<T, N> &rhs) {
699 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
700 return {{(lhs[indices] > rhs[indices])...}};
701 }(std::make_index_sequence<N>{});
702}
703
708template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<bool, N> operator>(
709 const Vec<T, N> &lhs, const scalar_t &rhs) {
710 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
711 return {{(lhs[indices] > rhs)...}};
712 }(std::make_index_sequence<N>{});
713}
714
719template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<bool, N> operator>(
720 const scalar_t &lhs, const Vec<T, N> &rhs) {
721 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
722 return {{(lhs > rhs[indices])...}};
723 }(std::make_index_sequence<N>{});
724}
725
726// Element-wise greater-or-equal-than: >=
727
732template <typename T, std::size_t N> __host__ __device__ constexpr Vec<bool, N> operator>=(
733 const Vec<T, N> &lhs, const Vec<T, N> &rhs) {
734 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
735 return {{(lhs[indices] >= rhs[indices])...}};
736 }(std::make_index_sequence<N>{});
737}
738
743template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<bool, N> operator>=(
744 const Vec<T, N> &lhs, const scalar_t &rhs) {
745 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
746 return {{(lhs[indices] >= rhs)...}};
747 }(std::make_index_sequence<N>{});
748}
749
754template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<bool, N> operator>=(
755 const scalar_t &lhs, const Vec<T, N> &rhs) {
756 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
757 return {{(lhs >= rhs[indices])...}};
758 }(std::make_index_sequence<N>{});
759}
760
761// Element-wise less-than: <
762
767template <typename T, std::size_t N> __host__ __device__ constexpr Vec<bool, N> operator<(
768 const Vec<T, N> &lhs, const Vec<T, N> &rhs) {
769 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
770 return {{(lhs[indices] < rhs[indices])...}};
771 }(std::make_index_sequence<N>{});
772}
773
774
779template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<bool, N> operator<(
780 const Vec<T, N> &lhs, const scalar_t &rhs) {
781 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
782 return {{(lhs[indices] < rhs)...}};
783 }(std::make_index_sequence<N>{});
784}
785
786
791template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<bool, N> operator<(
792 const scalar_t &lhs, const Vec<T, N> &rhs) {
793 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
794 return {{(lhs < rhs[indices])...}};
795 }(std::make_index_sequence<N>{});
796}
797
798// Element-wise less--or-equal-than: <=
799
804template <typename T, std::size_t N> __host__ __device__ constexpr Vec<bool, N> operator<=(
805 const Vec<T, N> &lhs, const Vec<T, N> &rhs) {
806 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
807 return {{(lhs[indices] <= rhs[indices])...}};
808 }(std::make_index_sequence<N>{});
809}
810
811
816template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<bool, N> operator<=(
817 const Vec<T, N> &lhs, const scalar_t &rhs) {
818 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
819 return {{(lhs[indices] <= rhs)...}};
820 }(std::make_index_sequence<N>{});
821}
822
823
828template <typename T, std::size_t N, typename scalar_t> __host__ __device__ constexpr Vec<bool, N> operator<=(
829 const scalar_t &lhs, const Vec<T, N> &rhs) {
830 return [&]<std::size_t... indices>(std::index_sequence<indices...>) -> std::array<bool, N> {
831 return {{(lhs <= rhs[indices])...}};
832 }(std::make_index_sequence<N>{});
833}
834
835// Concatenation
836
841template <typename T, std::size_t... Ns> __host__ __device__ constexpr Vec<T, (Ns + ...)> VecCat(
842 const Vec<T, Ns> &... vecs) {
843 Vec<T, (Ns + ...)> ret;
844 std::size_t startIndex = 0;
845 ([&] {
846 [&ret, startIndex]<std::size_t N, std::size_t... indices >(std::index_sequence<indices...>,
847 const Vec<T, N> &vec) {
848 ([&] { ret[startIndex + indices] = vec[indices]; }(), ...);
849 }(std::make_index_sequence<Ns>{}, vecs);
850 startIndex += Ns;
851 }(), ...);
852 return ret;
853}
854
859template <typename T, std::size_t N> __host__ __device__ constexpr Vec<T, N + 1> VecCat(
860 const Vec<T, N> &lhs, const T &rhs) {
862 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
863 ([&] { ret[indices] = lhs[indices]; }(), ...);
864 }(std::make_index_sequence<N>{});
865 ret[N] = rhs;
866 return ret;
867}
868
873template <typename T, std::size_t N> __host__ __device__ constexpr Vec<T, N + 1> VecCat(
874 const T &lhs, const Vec<T, N> &rhs) {
876 ret[0] = lhs;
877 [&]<std::size_t... indices>(std::index_sequence<indices...>) {
878 ([&] { ret[1 + indices] = rhs[indices]; }(), ...);
879 }(std::make_index_sequence<N>{});
880 return ret;
881}
882
894template <typename T, std::size_t R, std::size_t C> __host__ __device__ constexpr Vec<T, R> MatMul(
895 const Vec<Vec<T, R>, C> &lhs, const Vec<T, C> &rhs) {
896 constexpr auto rowDotProduct = []<std::size_t row>(const Vec<Vec<T, R>, C> &mat, const Vec<T, C> &vec) -> T {
897 return [&]<std::size_t... cols>(std::index_sequence<cols...>) -> T {
898 return ((mat[cols][row] * vec[cols]) + ...);
899 }(std::make_index_sequence<C>{});
900 };
901 return [&]<std::size_t... rows>(std::index_sequence<rows...>) -> std::array<T, R> {
902 return {{rowDotProduct.template operator()<rows>(lhs, rhs)...}};
903 }(std::make_index_sequence<R>{});
904}
905
906} // namespace reg23
General tools.
#define __host__
Definition Global.h:17
#define __device__
Definition Global.h:22
A simple vector class derived from std::array<T, N>, providing overrides for all useful operators.
Definition Vec.h:21
__host__ __device__ constexpr Vec< newT, N > Apply(newT(*f)(const T &)) const
Map all elements with a common C-style mapping function.
Definition Vec.h:324
__host__ __device__ constexpr Vec< newT, N > StaticCast() const
Construct a Vec with the elements form this one cast to a new type.
Definition Vec.h:237
__host__ __device__ constexpr Vec< newT, N > Apply(const std::function< newT(T)> &f) const
Map all elements with a common std::function mapping function.
Definition Vec.h:285
__host__ __device__ Vec & operator*=(const Vec &other)
Element-wise multiplication by another Vec.
Definition Vec.h:375
__host__ __device__ constexpr T & Z()
Get the third element.
Definition Vec.h:451
__host__ static __device__ constexpr Vec FromIntArrayRef(const at::IntArrayRef &v)
Construct a Vec from an at::IntArrayRef (this is the type of at::Tensor::sizes())
Definition Vec.h:82
__host__ static __device__ constexpr Vec Range(const T &start=T{0}, const T &step=T{1})
Construct a Vec where the ith element is start + i * step
Definition Vec.h:73
__host__ __device__ constexpr at::IntArrayRef ToIntArrayRef() const
Convert to an at::IntArrayRef (this is the type of at::Tensor::sizes())
Definition Vec.h:143
__host__ __device__ Vec & operator*=(const scalar_t &scalar)
Element-wise multiplication by a scalar.
Definition Vec.h:385
__host__ __device__ constexpr T Max() const
Find the largest element.
Definition Vec.h:195
__host__ __device__ Vec & operator-=(const Vec &other)
Element-wise subtraction of another Vec.
Definition Vec.h:355
__host__ __device__ constexpr const T & X() const
Get a constant reference to the first element.
Definition Vec.h:417
__host__ __device__ Vec & operator+=(const Vec &other)
Element-wise addition of another Vec.
Definition Vec.h:335
__host__ __device__ constexpr const T & Z() const
Get a constant reference to the third element.
Definition Vec.h:443
static __host__ Vec FromTensor(const at::Tensor &t)
Construct a Vec from a 1D PyTorch tensor.
Definition Vec.h:98
__host__ __device__ constexpr const T & Y() const
Get a constant reference to the second element.
Definition Vec.h:427
static constexpr std::size_t dimensionality
Definition Vec.h:26
__host__ __device__ constexpr Vec< T, 3 > DeHomogenise() const
Compute the 3-vector for this homogeneous vector, = (x, y, z) / w.
Definition Vec.h:227
__host__ __device__ constexpr const T & W() const
Get a constant reference to the fourth element.
Definition Vec.h:459
__host__ __device__ constexpr T & Y()
Get the second element.
Definition Vec.h:435
__host__ __device__ constexpr T & X()
Get the first element.
Definition Vec.h:422
static __host__ constexpr Vec Identity()
Construct an identity matrix.
Definition Vec.h:112
__host__ __device__ Vec()
Default construct all elements.
Definition Vec.h:33
__host__ __device__ Vec & operator/=(const scalar_t &scalar)
Element-wise division by a scalar.
Definition Vec.h:405
__host__ __device__ constexpr Vec< newT, N > Apply(newT(*f)(T)) const
Map all elements with a common C-style mapping function.
Definition Vec.h:311
__host__ __device__ constexpr T Length() const
Compute the L^2 norm.
Definition Vec.h:247
T ElementType
Definition Vec.h:25
__host__ __device__ constexpr T Sum() const
Compute the sum of all elements.
Definition Vec.h:171
std::array< T, N > Base
Definition Vec.h:28
__host__ __device__ Vec & operator-=(const scalar_t &scalar)
Element-wise subtraction of a scalar.
Definition Vec.h:365
static __host__ Vec FromTensor2D(const at::Tensor &t)
Construct a matrix from a 2D PyTorch tensor.
Definition Vec.h:132
__host__ static __device__ constexpr Vec Full(const T &value)
Construct a Vec, copying the given value into every element.
Definition Vec.h:64
__host__ __device__ constexpr Vec Flipped() const
Construct a Vec with the same elements, but in the reverse order.
Definition Vec.h:161
__host__ __device__ constexpr bool BooleanAny() const
Compute the combination of all elements using the OR operator.
Definition Vec.h:270
__host__ __device__ Vec & operator/=(const Vec &other)
Element-wise division by another Vec.
Definition Vec.h:395
__host__ __device__ Vec & operator+=(const scalar_t &scalar)
Element-wise addition of a scalar.
Definition Vec.h:345
__host__ __device__ constexpr std::pair< T, T > MinMax() const
Find the smallest and largest elements.
Definition Vec.h:210
__host__ __device__ constexpr T Min() const
Find the smallest element.
Definition Vec.h:181
__host__ __device__ Vec(std::initializer_list< T > l)
Construct from a series of values.
Definition Vec.h:53
__host__ at::Tensor ToTensor(at::TensorOptions options={}, bool nonOwning=false) const
Convert to an at::Tensor
Definition Vec.h:152
__host__ __device__ constexpr Vec< T, 3 > XYZ() const
Construct a Vec from the first three elements.
Definition Vec.h:480
__host__ __device__ constexpr Vec< T, 2 > XY() const
Construct a Vec from the first two elements.
Definition Vec.h:475
__host__ __device__ Vec(Base array)
Construct from a std::array (this is the base class of Vec)
Definition Vec.h:42
__host__ __device__ constexpr T & W()
Get the fourth element.
Definition Vec.h:467
__host__ __device__ constexpr Vec< newT, N > Apply(const std::function< newT(const T &)> &f) const
Map all elements with a common std::function mapping function.
Definition Vec.h:298
__host__ __device__ constexpr bool BooleanAll() const
Compute the combination of all elements using the AND operator.
Definition Vec.h:257
__host__ __device__ constexpr Vec< T, N > operator-(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec element-wise subtraction
Definition Vec.h:524
__host__ __device__ constexpr Vec< T, N > operator/(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec element-wise division
Definition Vec.h:594
__host__ __device__ constexpr Vec< bool, N > operator>=(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec element-wise greater-than-or-equal-to
Definition Vec.h:732
__host__ __device__ constexpr Vec< T,(Ns+...)> VecCat(const Vec< T, Ns > &... vecs)
reg23::Vec concatenation of any number of vectors
Definition Vec.h:841
__host__ __device__ constexpr Vec< T, N > operator*(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec element-wise multiplication
Definition Vec.h:559
__host__ __device__ constexpr Vec< bool, N > operator<=(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec element-wise less-than-or-equal-to
Definition Vec.h:804
__host__ __device__ constexpr Vec< bool, N > operator>(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec element-wise greater-than
Definition Vec.h:697
__host__ __device__ constexpr Vec< bool, N > operator<(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec element-wise less-than
Definition Vec.h:767
__host__ __device__ constexpr Vec< T, N > operator%(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec element-wise modulo
Definition Vec.h:630
__host__ __device__ constexpr T VecDot(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec dot product
Definition Vec.h:667
__host__ __device__ constexpr Vec< Vec< T, N1 >, N2 > VecOuter(const Vec< T, N1 > &lhs, const Vec< T, N2 > &rhs)
reg23::Vec outer product; returns a column major matrix of size N1 x N2.
Definition Vec.h:682
__host__ __device__ constexpr Vec< T, R > MatMul(const Vec< Vec< T, R >, C > &lhs, const Vec< T, C > &rhs)
Matrix-vector multiplication of the Vec struct.
Definition Vec.h:894
__host__ __device__ constexpr Vec< T, N > operator+(const Vec< T, N > &lhs, const Vec< T, N > &rhs)
reg23::Vec element-wise addition
Definition Vec.h:489
Vec< TextureAddressMode, DIMENSIONALITY > StringsToAddressModes(const std::array< std::string_view, DIMENSIONALITY > &strings)
Definition Texture.h:44
Definition GridSample3DCPU.cpp:6