27 template <
typename T,
int... n>
31 template <
typename T,
int m,
int... n>
32 struct tensor<T, m, n...> {
33 template <
typename i_type>
38 template <
typename i_type>
43 template <
typename i_type,
typename... jklm_type>
46 return data[i](jklm...);
48 template <
typename i_type,
typename... jklm_type>
51 return data[i](jklm...);
55 SMITH_HOST_DEVICE constexpr
const auto& operator[](
int i)
const {
return data[i]; }
60 template <
typename T,
int m>
62 template <
typename i_type>
67 template <
typename i_type>
73 SMITH_HOST_DEVICE constexpr
const auto& operator[](
int i)
const {
return data[i]; }
99 template <
typename T,
int n1>
110 template <
typename T,
int n1,
int n2>
127 template <
typename T,
int... n>
134 template <
typename... T>
141 template <
typename T>
149 template <
typename T>
160 template <
typename T>
167 template <
typename T>
182 template <
typename T>
189 template <
typename T>
201 template <
typename T>
208 template <
typename T>
215 template <
typename T>
222 template <
typename T>
225 static_assert(::detail::always_false<T>{},
"Error: Can't divide by zero!");
249 template <
typename T>
256 template <
typename T>
269 template <
typename T,
int n1,
int n2 = 1>
271 (n1 == 1 && n2 == 1),
double,
279 template <
typename T,
int... n>
296 template <
typename lambda_type>
299 using T = decltype(f());
315 template <
int n1,
typename lambda_type>
318 using T = decltype(f(n1));
320 for (
int i = 0; i < n1; i++) {
339 template <
int n1,
int n2,
typename lambda_type>
342 using T = decltype(f(n1, n2));
344 for (
int i = 0; i < n1; i++) {
345 for (
int j = 0; j < n2; j++) {
366 template <
int n1,
int n2,
int n3,
typename lambda_type>
369 using T = decltype(f(n1, n2, n3));
371 for (
int i = 0; i < n1; i++) {
372 for (
int j = 0; j < n2; j++) {
373 for (
int k = 0; k < n3; k++) {
374 A(i, j, k) = f(i, j, k);
396 template <
int n1,
int n2,
int n3,
int n4,
typename lambda_type>
399 using T = decltype(f(n1, n2, n3, n4));
401 for (
int i = 0; i < n1; i++) {
402 for (
int j = 0; j < n2; j++) {
403 for (
int k = 0; k < n3; k++) {
404 for (
int l = 0; l < n4; l++) {
405 A(i, j, k, l) = f(i, j, k, l);
421 template <
typename S,
typename T,
int m,
int... n>
424 tensor<decltype(S{} + T{}), m, n...> C{};
425 for (
int i = 0; i < m; i++) {
437 template <
typename T,
int m,
int... n>
441 for (
int i = 0; i < m; i++) {
455 template <
typename S,
typename T,
int m,
int... n>
458 tensor<decltype(S{} + T{}), m, n...> C{};
459 for (
int i = 0; i < m; i++) {
473 template <
typename S,
typename T,
int m,
int... n>
476 for (
int i = 0; i < m; i++) {
489 template <
typename T>
502 template <
typename T,
int n>
505 for (
int i = 0; i < n; i++) {
506 A.data[i][0] += B[i];
517 template <
typename T,
int n>
520 for (
int i = 0; i < n; i++) {
521 A.data[0][i] += B[i];
532 template <
typename T>
535 return A.data[0] += B;
544 template <
typename T>
547 return A.data[0][0] += B;
556 template <
typename T,
int... n>
570 template <
typename S,
typename T,
int m,
int... n>
573 for (
int i = 0; i < m; i++) {
585 template <
typename T,
int... n>
595 template <
typename T,
int n>
598 tensor<decltype(
double{} * T{}), n> AB{};
599 for (
int i = 0; i < n; i++) {
609 template <
typename T,
int m>
612 tensor<decltype(T{} *
double{}), m> AB{};
613 for (
int i = 0; i < m; i++) {
623 template <
typename T,
int n>
633 template <
typename T,
int n>
643 template <
typename S,
typename T,
int m,
int n>
646 tensor<decltype(S{} * T{}), m, n> AB{};
647 for (
int i = 0; i < m; i++) {
648 for (
int j = 0; j < n; j++) {
649 AB[i][j] = A[i] * B[j];
664 template <
typename S,
typename T,
int m,
int n>
667 decltype(S{} * T{}) sum{};
668 for (
int i = 0; i < m; i++) {
669 for (
int j = 0; j < n; j++) {
670 sum += A[i][j] * B[i][j];
680 template <
typename S,
typename T,
int m>
683 decltype(S{} * T{}) sum{};
684 for (
int i = 0; i < m; i++) {
702 template <
typename S,
int m,
int n>
712 template <
typename S,
int m>
730 template <
typename T,
int m,
int n>
740 template <
typename T,
int m>
760 template <
typename S,
typename T,
int m,
int n,
int p>
763 tensor<decltype(S{} * T{}), m, p> AB{};
764 for (
int i = 0; i < m; i++) {
765 for (
int j = 0; j < p; j++) {
766 for (
int k = 0; k < n; k++) {
767 AB[i][j] = AB[i][j] + A[i][k] * B[k][j];
778 template <
typename T,
int m>
788 template <
typename T,
int m>
798 template <
typename S,
typename T,
int m>
801 decltype(S{} * T{}) AB{};
802 for (
int i = 0; i < m; i++) {
803 AB = AB + A[i] * B[i];
812 template <
typename S,
typename T,
int m,
int n>
815 tensor<decltype(S{} * T{}), n> AB{};
816 for (
int i = 0; i < n; i++) {
817 for (
int j = 0; j < m; j++) {
818 AB[i] = AB[i] + A[j] * B[j][i];
828 template <
typename S,
typename T,
int m,
int n,
int p>
831 tensor<decltype(S{} * T{}), n, p> AB{};
832 for (
int j = 0; j < m; j++) {
833 AB = AB + A[j] * B[j];
848 template <
typename S,
typename T,
int m,
int n,
int p,
int q>
851 tensor<decltype(S{} * T{}), n, p, q> AB{};
852 for (
int j = 0; j < m; j++) {
853 AB = AB + A[j] * B[j];
862 template <
typename S,
typename T,
int m,
int n>
865 tensor<decltype(S{} * T{}), m> AB{};
866 for (
int i = 0; i < m; i++) {
867 for (
int j = 0; j < n; j++) {
868 AB[i] = AB[i] + A[i][j] * B[j];
878 template <
typename S,
typename T,
int m,
int n,
int p,
int q,
int r>
881 tensor<decltype(S{} * T{}), m, p, q, r> AB{};
882 for (
int i = 0; i < m; i++) {
883 for (
int j = 0; j < n; j++) {
884 AB[i] = AB[i] + A[i][j] * B[j];
894 template <
typename S,
typename T,
int m,
int n,
int p,
int q>
897 tensor<decltype(S{} * T{}), m, p, q> AB{};
898 for (
int i = 0; i < m; i++) {
899 for (
int j = 0; j < n; j++) {
900 AB[i] = AB[i] + A[i][j] * B[j];
910 template <
typename S,
typename T,
int m,
int n,
int p>
913 tensor<decltype(S{} * T{}), m, n> AB{};
914 for (
int i = 0; i < m; i++) {
915 for (
int j = 0; j < n; j++) {
916 for (
int k = 0; k < p; k++) {
917 AB[i][j] += A[i][j][k] * B[k];
928 template <
typename S,
typename T,
typename U,
int m,
int n>
931 decltype(S{} * T{} * U{}) uAv{};
932 for (
int i = 0; i < m; i++) {
933 for (
int j = 0; j < n; j++) {
934 uAv += u[i] * A[i][j] * v[j];
941 template <
typename S,
typename T,
int m,
int n,
int p,
int q>
944 tensor<decltype(S{} * T{}), m, n, p> AB{};
945 for (
int i = 0; i < m; i++) {
946 for (
int j = 0; j < n; j++) {
947 for (
int k = 0; k < p; k++) {
948 for (
int l = 0; l < q; l++) {
949 AB[i][j][k] += A[i][j][k][l] * B[l];
958 template <
typename T>
961 return tensor<T, 3>{A(1, 0) * A(2, 1) - A(2, 0) * A(1, 1), A(2, 0) * A(0, 1) - A(0, 0) * A(2, 1),
962 A(0, 0) * A(1, 1) - A(1, 0) * A(0, 1)};
966 template <
typename T>
973 template <
typename T>
980 template <
typename S,
typename T>
983 return tensor<decltype(S{} * T{}), 3>{u(1) * v(2) - u(2) * v(1), u(2) * v(0) - u(0) * v(2),
984 u(0) * v(1) - u(1) * v(0)};
998 template <
typename S,
typename T,
int m,
int n,
int p,
int q>
1001 tensor<decltype(S{} * T{}), m, n> AB{};
1002 for (
int i = 0; i < m; i++) {
1003 for (
int j = 0; j < n; j++) {
1004 for (
int k = 0; k < p; k++) {
1005 for (
int l = 0; l < q; l++) {
1006 AB[i][j] += A[i][j][k][l] * B[k][l];
1018 template <
typename S,
typename T,
int m,
int n,
int p>
1021 tensor<decltype(S{} * T{}), m> AB{};
1022 for (
int i = 0; i < m; i++) {
1023 for (
int j = 0; j < n; j++) {
1024 for (
int k = 0; k < p; k++) {
1025 AB[i] += A[i][j][k] * B[j][k];
1036 template <
typename S,
typename T,
int m,
int n>
1039 decltype(S{} * T{}) AB{};
1040 for (
int i = 0; i < m; i++) {
1041 for (
int j = 0; j < n; j++) {
1042 AB += A[i][j] * B[i][j];
1051 template <
typename S,
typename T,
int... m,
int... n>
1061 template <
typename T,
int m>
1065 for (
int i = 0; i < m; i++) {
1066 total += A[i] * A[i];
1072 template <
typename T,
int m,
int n>
1076 for (
int i = 0; i < m; i++) {
1077 for (
int j = 0; j < n; j++) {
1078 total += A[i][j] * A[i][j];
1085 template <
typename T,
int... n>
1089 for_constexpr<n...>([&](
auto... i) { total += A(i...) * A(i...); });
1097 template <
typename T,
int... n>
1114 template <
typename T,
int... n>
1125 template <
typename T>
1129 output[0][0] = A[0][0];
1130 output[0][1] = A[0][1];
1131 output[1][0] = A[1][0];
1132 output[1][1] = A[1][1];
1141 template <
typename T,
int n>
1145 for (
int i = 0; i < n; i++) {
1146 trA = trA + A[i][i];
1156 template <
typename T,
int n>
1160 for (
int i = 0; i < n; i++) {
1161 for (
int j = 0; j < n; j++) {
1162 symA[i][j] = 0.5 * (A[i][j] + A[j][i]);
1173 template <
typename T,
int n>
1177 for (
int i = 0; i < n; i++) {
1178 for (
int j = 0; j < n; j++) {
1179 antisymA[i][j] = 0.5 * (A[i][j] - A[j][i]);
1192 template <
typename T,
int n>
1197 for (
int i = 0; i < n; i++) {
1198 devA[i][i] -= trA / n;
1209 template <
typename T,
int n>
1213 for (
int i = 0; i < n; i++) {
1223 template <
typename T,
int n>
1227 for (
int i = 0; i < n; i++) {
1237 template <
typename T,
int n>
1241 for (
int i = 0; i < n; i++) {
1255 for (
int i = 0; i < dim; i++) {
1256 for (
int j = 0; j < dim; j++) {
1267 template <
typename T,
int m,
int n>
1271 for (
int i = 0; i < n; i++) {
1272 for (
int j = 0; j < m; j++) {
1283 template <
typename T>
1286 return +A[0][0] * A[1][1] + A[1][1] * A[2][2] + A[2][2] * A[0][0] - A[0][1] * A[1][0] - A[1][2] * A[2][1] -
1294 template <
typename T>
1297 return A[0][0] * A[1][1] - A[0][1] * A[1][0];
1301 template <
typename T>
1304 return A[0][0] * A[1][1] * A[2][2] + A[0][1] * A[1][2] * A[2][0] + A[0][2] * A[1][0] * A[2][1] -
1305 A[0][0] * A[1][2] * A[2][1] - A[0][1] * A[1][0] * A[2][2] - A[0][2] * A[1][1] * A[2][0];
1318 template <
typename T>
1327 return A(0, 0) - A(0, 1) * A(1, 0) + A(1, 1) + A(0, 0) * A(1, 1);
1331 template <
typename T>
1338 return A(0, 0) + A(1, 1) + A(2, 2)
1339 - A(0, 1) * A(1, 0) * (1 + A(2, 2))
1340 + A(0, 0) * A(1, 1) * (1 + A(2, 2))
1341 - A(0, 2) * A(2, 0) * (1 + A(1, 1))
1342 - A(1, 2) * A(2, 1) * (1 + A(0, 0))
1345 + A(0, 1) * A(1, 2) * A(2, 0)
1346 + A(0, 2) * A(1, 0) * A(2, 1);
1358 template <
typename T,
int dim>
1362 for (
int i = 0; i < 15; i++) {
1363 B = 0.5 * (B +
dot(A,
inv(B)));
1397 template <
int i1,
int i2,
typename S,
int m,
int... n,
typename T,
int p,
int q>
1400 constexpr
int Adims[] = {m, n...};
1401 constexpr
int Bdims[] = {p, q};
1402 static_assert(
sizeof...(n) < 3);
1403 static_assert(Adims[i1] == Bdims[i2],
"error: incompatible tensor dimensions");
1406 constexpr
int new_dim = (i2 == 0) ? q : p;
1407 constexpr
int d1 = (i1 == 0) ? new_dim : Adims[0];
1408 constexpr
int d2 = (i1 == 1) ? new_dim : Adims[1];
1409 constexpr
int d3 =
sizeof...(n) == 1 ? 0 : ((i1 == 2) ? new_dim : Adims[2]);
1412 using U = decltype(S{} * T{});
1419 if constexpr (d3 == 0) {
1420 for (
int i = 0; i < d1; i++) {
1421 for (
int j = 0; j < d2; j++) {
1423 for (
int k = 0; k < Adims[i1]; k++) {
1424 if constexpr (i1 == 0 && i2 == 0) sum += A(k, j) * B(k, i);
1425 if constexpr (i1 == 1 && i2 == 0) sum += A(i, k) * B(k, j);
1426 if constexpr (i1 == 0 && i2 == 1) sum += A(k, j) * B(i, k);
1427 if constexpr (i1 == 1 && i2 == 1) sum += A(i, k) * B(j, k);
1433 for (
int i = 0; i < d1; i++) {
1434 for (
int j = 0; j < d2; j++) {
1435 for (
int k = 0; k < d3; k++) {
1437 for (
int l = 0; l < Adims[i1]; l++) {
1438 if constexpr (i1 == 0 && i2 == 0) sum += A(l, j, k) * B(l, i);
1439 if constexpr (i1 == 1 && i2 == 0) sum += A(i, l, k) * B(l, j);
1440 if constexpr (i1 == 2 && i2 == 0) sum += A(i, j, l) * B(l, k);
1441 if constexpr (i1 == 0 && i2 == 1) sum += A(l, j, k) * B(i, l);
1442 if constexpr (i1 == 1 && i2 == 1) sum += A(i, l, k) * B(j, l);
1443 if constexpr (i1 == 2 && i2 == 1) sum += A(i, j, l) * B(k, l);
1455 template <
int i1,
int i2,
typename T>
1470 template <
typename T,
int... n>
1487 for (
int i = 0; i < n; ++i) {
1488 for (
int j = i + 1; j < n; ++j) {
1489 if (
std::abs(A(i, j) - A(j, i)) > tolerance) {
1510 if (A(0, 0) < 0.0) {
1527 auto subtensor = make_tensor<2, 2>([A](
int i,
int j) {
return A(i, j); });
1539 template <
typename T,
int n>
1560 template <
typename T,
int n,
int... m>
1565 for (
int i = 0; i < n; i++) {
1567 for (
int j = 0; j < i; j++) {
1568 c -= L[i][j] * y[j];
1579 template <
typename T,
int n,
int... m>
1600 template <
typename T,
int n,
int... m>
1604 for (
int i = n - 1; i >= 0; i--) {
1606 for (
int j = i + 1; j < n; j++) {
1607 c -= U[i][j] * x[j];
1618 template <
typename S,
typename T,
int n,
int... m>
1634 template <
typename T,
int n>
1647 double inv_detA(1.0 /
det(A));
1651 invA[0][0] = A[1][1] * inv_detA;
1652 invA[0][1] = -A[0][1] * inv_detA;
1653 invA[1][0] = -A[1][0] * inv_detA;
1654 invA[1][1] = A[0][0] * inv_detA;
1665 double inv_detA(1.0 /
det(A));
1669 invA[0][0] = (A[1][1] * A[2][2] - A[1][2] * A[2][1]) * inv_detA;
1670 invA[0][1] = (A[0][2] * A[2][1] - A[0][1] * A[2][2]) * inv_detA;
1671 invA[0][2] = (A[0][1] * A[1][2] - A[0][2] * A[1][1]) * inv_detA;
1672 invA[1][0] = (A[1][2] * A[2][0] - A[1][0] * A[2][2]) * inv_detA;
1673 invA[1][1] = (A[0][0] * A[2][2] - A[0][2] * A[2][0]) * inv_detA;
1674 invA[1][2] = (A[0][2] * A[1][0] - A[0][0] * A[1][2]) * inv_detA;
1675 invA[2][0] = (A[1][0] * A[2][1] - A[1][1] * A[2][0]) * inv_detA;
1676 invA[2][1] = (A[0][1] * A[2][0] - A[0][0] * A[2][1]) * inv_detA;
1677 invA[2][2] = (A[0][0] * A[1][1] - A[0][1] * A[1][0]) * inv_detA;
1686 template <
typename T,
int n>
1689 auto I = DenseIdentity<n>();
1701 template <
typename T,
int m,
int... n>
1705 for (
int i = 1; i < m; i++) {
1706 out <<
", " << A[i];
1734 template <
int m,
int... n>
1739 for (
int i = 1; i < m; i++) {
1754 for (
int i = 0; i < n; i++) {
1755 if (copy[i] * copy[i] < 1.0e-20) {
1763 template <
int m,
int n>
1767 for (
int i = 0; i < m; i++) {
1768 for (
int j = 0; j < n; j++) {
1769 if (copy[i][j] * copy[i][j] < 1.0e-20) {
1780 template <
typename T1,
typename T2>
1783 template <
int... m,
int... n>
1784 struct outer_prod<
tensor<double, m...>,
tensor<double, n...>> {
1789 struct outer_prod<double,
tensor<double, n...>> {
1794 struct outer_prod<
tensor<double, n...>, double> {
1799 struct outer_prod<double, double> {
1800 using type = tensor<double>;
1803 template <
typename T>
1804 struct outer_prod<zero, T> {
1808 template <
typename T>
1809 struct outer_prod<T, zero> {
1821 template <
typename T1,
typename T2>
1850 template <
typename T>
1860 template <
typename T>
1890 for_constexpr<n...>([&](
auto... i) { total += df_dx(i...) * dx(i...); });
1898 template <
int m,
int... n>
1902 for (
int i = 0; i < m; i++) {
1912 template <
int m,
int n,
int... p>
1916 for (
int i = 0; i < m; i++) {
1917 for (
int j = 0; j < n; j++) {
1931 template <
typename T,
int... n>
1934 return (n * ... * 1);
1954 template <
int i,
typename T,
int... n>
1957 constexpr
int dimensions[] = {n...};
1958 return dimensions[i];
1969 template <
typename T,
int m,
int... n>
1976 template <
typename T,
int... n>
1979 bool found_nan =
false;
1991 inline float angle_between(
const vec < 2 > & a,
const vec < 2 > & b) {
1995 inline float angle_between(
const vec < 3 > & a,
const vec < 3 > & b) {
2000 inline float angle_between(
const mat < 3, 3 > & U,
const mat < 3, 3 > & V) {
2004 inline mat < 2, 2 > rotation(
const float theta) {
2006 {
cos(theta), -
sin(theta)},
2007 {
sin(theta),
cos(theta) }
2011 inline mat < 3, 3 > axis_to_rotation(
const vec < 3 > & omega) {
2013 float norm_omega =
norm(omega);
2015 if (fabs(norm_omega) < 0.000001f) {
2021 vec3 u = omega / norm_omega;
2023 float c =
cos(norm_omega);
2024 float s =
sin(norm_omega);
2026 return mat < 3, 3 >{
2028 u[0]*u[0]*(1.0f - c) + c,
2029 u[0]*u[1]*(1.0f - c) - u[2]*s,
2030 u[0]*u[2]*(1.0f - c) + u[1]*s
2032 u[1]*u[0]*(1.0f - c) + u[2]*s,
2033 u[1]*u[1]*(1.0f - c) + c,
2034 u[1]*u[2]*(1.0f - c) - u[0]*s
2036 u[2]*u[0]*(1.0f - c) - u[1]*s,
2037 u[2]*u[1]*(1.0f - c) + u[0]*s,
2038 u[2]*u[2]*(1.0f - c) + c
2047 inline vec < 3 > rotation_to_axis(
const mat < 3, 3 > & R) {
2049 float theta =
acos(clip(0.5f * (
tr(R) - 1.0f), -1.0f, 1.0f));
2054 if (fabs(theta) < 0.00001f) {
2055 scale = 0.5f + theta * theta / 12.0f;
2058 scale = 0.5f * theta /
sin(theta);
2061 return vec3{ R(2,1) - R(1,2), R(0,2) - R(2,0), R(1,0) - R(0,1) } *scale;
2065 inline mat < 3, 3 > look_at(
const vec < 3 > & direction,
const vec < 3 > & up =
vec3{ 0.0f, 0.0f, 1.0f }) {
2077 inline mat < 2, 2 > look_at(
const vec < 2 > & direction) {
2087 inline mat < 3, 3 > R3_basis(
const vec3 & n) {
2088 float sign = (n[2] >= 0.0f) ? 1.0f : -1.0f;
2089 float a = -1.0f / (sign + n[2]);
2090 float b = n[0] * n[1] * a;
2092 return mat < 3, 3 >{
2094 1.0f + sign * n[0] * n[0] * a,
2099 sign + n[1] * n[1] * a,
2112 #include "smith/numerics/functional/tuple_tensor_dual_functions.hpp"
This file contains the interface used for initializing/terminating any hardware accelerator-related f...
#define SMITH_SUPPRESS_NVCC_HOSTDEVICE_WARNING
Macro to turn off specific nvcc warnings.
#define SMITH_HOST_DEVICE
Macro that evaluates to __host__ __device__ when compiling with nvcc and does nothing on a host compi...
Implementation of isotropic tensor classes.
Accelerator functionality.
SMITH_HOST_DEVICE bool is_symmetric(tensor< double, n, n > A, double tolerance=1.0e-8)
Return whether a square rank 2 tensor is symmetric.
SMITH_HOST_DEVICE auto acos(dual< gradient_type > a)
implementation of acos for dual numbers
SMITH_HOST_DEVICE bool is_symmetric_and_positive_definite(tensor< double, 3, 3 > A)
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr SMITH_HOST_DEVICE auto antisym(const tensor< T, n, n > &A)
Returns the antisymmetric part of a square matrix.
constexpr SMITH_HOST_DEVICE auto & operator+=(dual< gradient_type > &a, const dual< gradient_type > &b)
compound assignment (+) for dual numbers
constexpr SMITH_HOST_DEVICE auto & operator-=(tensor< T, n... > &A, zero)
compound assignment (-) between a tensor and zero (no-op)
SMITH_SUPPRESS_NVCC_HOSTDEVICE_WARNING constexpr SMITH_HOST_DEVICE auto make_tensor(lambda_type f)
Creates a tensor of requested dimension by subsequent calls to a functor Can be thought of as analogo...
constexpr T & get(variant< T0, T1 > &v)
Returns the variant member of specified type.
constexpr SMITH_HOST_DEVICE int size(zero)
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr SMITH_HOST_DEVICE auto det(const tensor< T, 3, 3 > &A)
This is an overloaded member function, provided for convenience. It differs from the above function o...
double relative_error(tensor< T, n... > A, tensor< T, n... > B)
computes the relative error (in the frobenius norm) between two tensors of the same shape
constexpr SMITH_HOST_DEVICE int leading_dimension(tensor< T, m, n... >)
a function for querying the first dimension of a tensor
constexpr SMITH_HOST_DEVICE auto operator*(const dual< gradient_type > &a, double b)
multiplication of a dual number and a non-dual number
constexpr SMITH_HOST_DEVICE auto get_gradient(const tensor< double, n... > &)
get the gradient of type tensor (note: since its stored type is not a dual number,...
constexpr SMITH_HOST_DEVICE auto operator*(const tensor< S, m... > &A, const tensor< T, n... > &B)
this is a shorthand for dot(A, B)
SMITH_HOST_DEVICE auto contract(const zero &, const T &)
This is an overloaded member function, provided for convenience. It differs from the above function o...
SMITH_HOST_DEVICE auto chain_rule(const tensor< double, m, n, p... > &df_dx, const tensor< double, p... > &dx)
constexpr SMITH_HOST_DEVICE auto I2(const tensor< T, 3, 3 > &A)
Returns the second invariant of a 3x3 matrix.
SMITH_HOST_DEVICE auto sqrt(dual< gradient_type > x)
implementation of square root for dual numbers
constexpr SMITH_HOST_DEVICE auto inner(zero, double)
constexpr SMITH_HOST_DEVICE auto type(const tuple< T... > &values)
a function intended to be used for extracting the ith type from a tuple.
constexpr SMITH_HOST_DEVICE auto solve_lower_triangular(const tensor< T, n, n > &L, const tensor< T, n, m... > &b)
constexpr SMITH_HOST_DEVICE auto norm(zero)
overload of Frobenius norm for zero type
constexpr SMITH_HOST_DEVICE auto operator+(dual< gradient_type > a, double b)
addition of a dual number and a non-dual number
constexpr SMITH_HOST_DEVICE auto squared_norm(const tensor< T, n... > &A)
This is an overloaded member function, provided for convenience. It differs from the above function o...
tensor< double, 3 > vec3
statically sized vector of 3 doubles
auto & operator<<(std::ostream &out, zero)
Write a zero out to an output stream.
SMITH_HOST_DEVICE auto cos(dual< gradient_type > a)
implementation of cosine for dual numbers
std::conditional_t<(n1==1 &&n2==1), double, std::conditional_t< n1==1, tensor< T, n2 >, std::conditional_t< n2==1, tensor< T, n1 >, tensor< T, n1, n2 > >> > reduced_tensor
Removes 1s from tensor dimensions For example, a tensor<T, 1, 10> is equivalent to a tensor<T,...
constexpr SMITH_HOST_DEVICE auto chop(const tensor< double, m, n > &A)
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr SMITH_HOST_DEVICE tensor< T, n > diag(const tensor< T, n, n > &D)
Returns an array containing the diagonal entries of a square matrix.
bool isnan(const zero &)
This is an overloaded member function, provided for convenience. It differs from the above function o...
tensor(const T(&data)[n1]) -> tensor< T, n1 >
class template argument deduction guide for type tensor.
constexpr auto double_dot(const tensor< S, m, n > &A, const tensor< T, m, n > &B)
constexpr SMITH_HOST_DEVICE auto inv(const tensor< T, n, n > &A)
auto cross(const tensor< S, 3 > &u, const tensor< T, 3 > &v)
compute the (right handed) cross product of two 3-vectors
constexpr SMITH_HOST_DEVICE auto dev(const tensor< T, n, n > &A)
Calculates the deviator of a matrix (rank-2 tensor)
auto matrix_sqrt(const tensor< T, dim, dim > &A)
compute the matrix square root of a square, real-valued, symmetric matrix i.e. given A,...
SMITH_HOST_DEVICE auto abs(dual< gradient_type > x)
Implementation of absolute value function for dual numbers.
tensor(const T(&data)[n1][n2]) -> tensor< T, n1, n2 >
class template argument deduction guide for type tensor.
SMITH_HOST_DEVICE tensor< T, 3, 3 > to_3x3(const tensor< T, 2, 2 > &A)
promotes a 2x2 matrix to a 3x3 matrix, by populating the upper left block, leaving zeroes in the thir...
SMITH_HOST_DEVICE void print(const tensor< double, m, n... > &A)
print a tensor using printf, so that it is suitable for use inside cuda kernels.
constexpr SMITH_HOST_DEVICE auto sym(const tensor< T, n, n > &A)
Returns the symmetric part of a square matrix.
typename detail::outer_prod< T1, T2 >::type outer_product_t
a type function that returns the tensor type of an outer product of two tensors
constexpr SMITH_HOST_DEVICE auto tensor_with_shape(std::integer_sequence< int, n... >)
Creates a tensor given the dimensions in a std::integer_sequence.
constexpr SMITH_HOST_DEVICE auto dot(const tensor< S, m, n, p, q > &A, const tensor< T, q > &B)
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr SMITH_HOST_DEVICE auto outer(const tensor< S, m > &A, const tensor< T, n > &B)
constexpr SMITH_HOST_DEVICE auto & operator+=(tensor< T, n... > &A, zero)
compound assignment (+) between a tensor and zero (no-op)
constexpr SMITH_HOST_DEVICE auto linear_solve(const LuFactorization< T, n > &, const zero)
tensor< double, 2 > vec2
statically sized vector of 2 doubles
constexpr SMITH_HOST_DEVICE int dimension(const tensor< T, n... > &)
a function for querying the ith dimension of a tensor
tensor< double, 2, 2 > mat2
statically sized 2x2 matrix of doubles
constexpr SMITH_HOST_DEVICE auto transpose(const tensor< T, m, n > &A)
Returns the transpose of the matrix.
constexpr SMITH_HOST_DEVICE tensor< double, dim, dim > DenseIdentity()
Obtains the identity matrix of the specified dimension.
constexpr SMITH_HOST_DEVICE auto & operator-=(dual< gradient_type > &a, const dual< gradient_type > &b)
compound assignment (-) for dual numbers
SMITH_HOST_DEVICE auto sin(dual< gradient_type > a)
implementation of sine for dual numbers
SMITH_HOST_DEVICE auto normalize(const tensor< T, n... > &A)
Normalizes the tensor Each element is divided by the Frobenius norm of the tensor,...
constexpr SMITH_HOST_DEVICE auto detApIm1(const tensor< T, 3, 3 > &A)
This is an overloaded member function, provided for convenience. It differs from the above function o...
constexpr SMITH_HOST_DEVICE auto tr(const tensor< T, n, n > &A)
Returns the trace of a square matrix.
constexpr SMITH_HOST_DEVICE auto dot(const isotropic_tensor< S, m, m > &I, const tensor< T, m, n... > &A)
dot product between an isotropic and (nonisotropic) tensor
constexpr SMITH_HOST_DEVICE auto operator-(const tensor< S, m, n... > &A, const tensor< T, m, n... > &B)
return the difference of two tensors
constexpr SMITH_HOST_DEVICE auto solve_upper_triangular(const tensor< T, n, n > &U, const tensor< T, n, m... > &y)
Solves an upper triangular system Ux = y.
constexpr SMITH_HOST_DEVICE auto operator/(const dual< gradient_type > &a, double b)
division of a dual number by a non-dual number
tensor< double, 3, 3 > mat3
statically sized 3x3 matrix of doubles
constexpr SMITH_HOST_DEVICE auto diagonal_matrix(const tensor< T, n, n > &A)
Returns a square matrix (rank-2 tensor) containing the diagonal entries of the input square matrix wi...
Domain operator-(const Domain &a, const Domain &b)
create a new domain that is the set difference of a and b
Representation of an LU factorization.
tensor< T, n, n > U
Upper triangular factor.
tensor< int, n > P
Row permutation indices due to partial pivoting.
tensor< T, n, n > L
Lower triangular factor. Has ones on diagonal.
Arbitrary-rank tensor class.
A sentinel struct for eliding no-op tensor operations.
SMITH_HOST_DEVICE auto operator()(T...) const
zero can be accessed like a multidimensional array
SMITH_HOST_DEVICE auto operator=(T)
anything assigned to zero does not change its value and returns zero