8#ifndef META_OCEAN_MATH_SQUARE_MATRIX_4_H
9#define META_OCEAN_MATH_SQUARE_MATRIX_4_H
23template <
typename T>
class AnyCameraT;
26template <
typename T>
class HomogenousMatrixT4;
29template <
typename T>
class SquareMatrixT3;
32template <
typename T>
class SquareMatrixT4;
114 template <
typename U>
128 template <
typename U>
143 template <
typename U>
292 template <
typename U>
437 inline T
operator()(
const unsigned int row,
const unsigned int column)
const;
446 inline T&
operator()(
const unsigned int row,
const unsigned int column);
551 template <
typename U>
561 template <
typename U>
571 void swapRows(
const unsigned int row0,
const unsigned int row1);
586 void addRows(
const unsigned int targetRow,
const unsigned int sourceRow,
const T scalar);
604 for (
unsigned int n = 0u; n < 16u; ++n)
606 values[n] = T(matrix.
values[n]);
627 ocean_assert(arrayValues);
629 for (
unsigned int n = 0u; n < 16u; ++n)
631 values[n] = T(arrayValues[n]);
638 ocean_assert(arrayValues);
639 memcpy(values, arrayValues,
sizeof(T) * 16);
646 ocean_assert(arrayValues);
648 if (valuesRowAligned)
650 values[ 0] = T(arrayValues[ 0]);
651 values[ 1] = T(arrayValues[ 4]);
652 values[ 2] = T(arrayValues[ 8]);
653 values[ 3] = T(arrayValues[12]);
654 values[ 4] = T(arrayValues[ 1]);
655 values[ 5] = T(arrayValues[ 5]);
656 values[ 6] = T(arrayValues[ 9]);
657 values[ 7] = T(arrayValues[13]);
658 values[ 8] = T(arrayValues[ 2]);
659 values[ 9] = T(arrayValues[ 6]);
660 values[10] = T(arrayValues[10]);
661 values[11] = T(arrayValues[14]);
662 values[12] = T(arrayValues[ 3]);
663 values[13] = T(arrayValues[ 7]);
664 values[14] = T(arrayValues[11]);
665 values[15] = T(arrayValues[15]);
669 for (
unsigned int n = 0u; n < 16u; ++n)
671 values[n] = T(arrayValues[n]);
679 ocean_assert(arrayValues);
681 if (valuesRowAligned)
683 values[ 0] = arrayValues[ 0];
684 values[ 1] = arrayValues[ 4];
685 values[ 2] = arrayValues[ 8];
686 values[ 3] = arrayValues[12];
687 values[ 4] = arrayValues[ 1];
688 values[ 5] = arrayValues[ 5];
689 values[ 6] = arrayValues[ 9];
690 values[ 7] = arrayValues[13];
691 values[ 8] = arrayValues[ 2];
692 values[ 9] = arrayValues[ 6];
693 values[10] = arrayValues[10];
694 values[11] = arrayValues[14];
695 values[12] = arrayValues[ 3];
696 values[13] = arrayValues[ 7];
697 values[14] = arrayValues[11];
698 values[15] = arrayValues[15];
702 memcpy(values, arrayValues,
sizeof(T) * 16);
709 memcpy(values, transformation(),
sizeof(T) * 16);
723 memcpy(values, subMatrix(),
sizeof(T) * 3);
724 memcpy(values + 4, subMatrix() + 3,
sizeof(T) * 3);
725 memcpy(values + 8, subMatrix() + 6,
sizeof(T) * 3);
731 values[ 0] = diagonal[0];
736 values[ 5] = diagonal[1];
741 values[10] = diagonal[2];
746 values[15] = diagonal[3];
766 result.
values[1] = values[4];
767 result.
values[4] = values[1];
769 result.
values[2] = values[8];
770 result.
values[8] = values[2];
772 result.
values[3] = values[12];
773 result.
values[12] = values[3];
775 result.
values[6] = values[9];
776 result.
values[9] = values[6];
778 result.
values[7] = values[13];
779 result.
values[13] = values[7];
781 result.
values[11] = values[14];
782 result.
values[14] = values[11];
792 values[4] = tmp.
values[1];
793 values[1] = tmp.
values[4];
795 values[8] = tmp.
values[2];
796 values[2] = tmp.
values[8];
798 values[12] = tmp.
values[3];
799 values[3] = tmp.
values[12];
801 values[9] = tmp.
values[6];
802 values[6] = tmp.
values[9];
804 values[13] = tmp.
values[7];
805 values[7] = tmp.
values[13];
807 values[14] = tmp.
values[11];
808 values[11] = tmp.
values[14];
816 if (!invert(invertedMatrix))
818 ocean_assert(
false &&
"Could not invert matrix.");
822 return invertedMatrix;
830 if (!invert(invertedMatrix))
835 *
this = invertedMatrix;
848 for (
unsigned int col = 0; col < 4u; ++col)
853 unsigned int selectedRow = 0u;
855 for (
unsigned int row = col; row < 4u; ++row)
858 if (absolute < value)
873 if (selectedRow != col)
876 invertedMatrix.
swapRows(col, selectedRow);
882 const T divisor = T(1.0) / source(col, col);
883 ocean_assert(divisor != T(0.0));
890 for (
unsigned int row = 0; row < 4u; ++row)
894 const T value = -source(row, col);
896 source.
addRows(row, col, value);
897 invertedMatrix.
addRows(row, col, value);
908 const T v6_15 = values[6] * values[15];
909 const T v10_15 = values[10] * values[15];
910 const T v11_14 = values[11] * values[14];
911 const T v7_10 = values[7] * values[10];
912 const T v9_14 = values[9] * values[14];
913 const T v6_13 = values[6] * values[13];
914 const T v2_13 = values[2] * values[13];
915 const T v2_9 = values[2] * values[9];
916 const T v3_10 = values[3] * values[10];
917 const T v2_5 = values[2] * values[5];
919 return values[0] * (values[5] * v10_15 - values[13] * v7_10
920 + v9_14 * values[7] - values[5] * v11_14
921 + v6_13 * values[11] - values[9] * v6_15)
922 - values[4] * (v9_14 * values[3] - values[1] * v11_14
923 + v2_13 * values[11] - v2_9 * values[15]
924 + values[1] * v10_15 - values[13] * v3_10)
925 + values[8] * (values[1] * v6_15 - v6_13 * values[3]
926 + values[5] * values[14] * values[3] - values[1] * values[14] * values[7]
927 + v2_13 * values[7] - v2_5 * values[15])
928 - values[12] * (values[1] * values[6] * values[11] - values[9] * values[6] * values[3]
929 + values[5] * v3_10 - values[1] * v7_10
930 + v2_9 * values[7] - v2_5 * values[11]);
936 return values[0] + values[5] + values[10] + values[15];
963 for (
unsigned int n = 0u; n < 16u; ++n)
996 ocean_assert(epsilon >= T(0));
1002template <
typename T>
1015template <
typename T>
1018 ocean_assert(eigenValues !=
nullptr && eigenVectors !=
nullptr);
1045 const T a = values[0];
1046 const T e = values[1];
1047 const T i = values[2];
1048 const T m = values[3];
1050 const T b = values[4];
1051 const T f = values[5];
1052 const T j = values[6];
1053 const T n = values[7];
1055 const T c = values[8];
1056 const T g = values[9];
1057 const T k = values[10];
1058 const T o = values[11];
1060 const T d = values[12];
1061 const T h = values[13];
1062 const T l = values[14];
1063 const T p = values[15];
1066 const T a2 = -a - f - k - p;
1067 const T a3 = -b * e + a * f - c * i - g * j + a * k + f * k - d * m - h * n - l * o + a * p + f * p + k * p;
1068 const T a4 = c * f * i - b * g * i - c * e * j + a * g * j + b * e * k - a * f * k + d * f * m - b * h * m
1069 + d * k * m - c * l * m - d * e * n + a * h * n + h * k * n - g * l * n - d * i * o - h * j * o
1070 + a * l * o + f * l * o + b * e * p - a * f * p + c * i * p + g * j * p - a * k * p - f * k * p;
1071 const T a5 = d * g * j * m - c * h * j * m - d * f * k * m + b * h * k * m + c * f * l * m - b * g * l * m
1072 - d * g * i * n + c * h * i * n + d * e * k * n - a * h * k * n - c * e * l * n + a * g * l * n
1073 + d * f * i * o - b * h * i * o - d * e * j * o + a * h * j * o + b * e * l * o - a * f * l * o
1074 - c * f * i * p + b * g * i * p + c * e * j * p - a * g * j * p - b * e * k * p + a * f * k * p;
1081 if (solutions != 4u)
1086 for (
unsigned int iEigen = 0u; iEigen < solutions && iEigen < 4u; ++iEigen)
1088 eigenValues[iEigen] = T(x[iEigen]);
1091 for (
unsigned int iEigen = solutions; iEigen < 4u; ++iEigen)
1093 eigenValues[iEigen] = T(0);
1108 for (
unsigned int nSolution = 0u; nSolution < solutions; ++nSolution)
1110 const T lambda = eigenValues[nSolution];
1126 for (
unsigned int freeIndex = 0u; freeIndex < 4u; ++freeIndex)
1130 candidate[freeIndex] = T(1);
1134 unsigned int rowIndices[4] = {0, 1, 2, 3};
1137 for (
unsigned int rowNum = 0u; rowNum < 4u; ++rowNum)
1143 for (
unsigned int row = 0u; row < 3u; ++row)
1145 for (
unsigned int row2 = row + 1u; row2 < 4u; ++row2)
1147 if (rowScores[row2] > rowScores[row])
1149 std::swap(rowScores[row], rowScores[row2]);
1150 std::swap(rowIndices[row], rowIndices[row2]);
1157 T coeffMatrix[3][3];
1159 unsigned int unknownIndices[3];
1160 unsigned int idx = 0u;
1162 for (
unsigned int col = 0u; col < 4u; ++col)
1164 if (col != freeIndex)
1166 unknownIndices[idx++] = col;
1170 for (
unsigned int rowIdx = 0u; rowIdx < 3u; ++rowIdx)
1172 const VectorT4<T>& row = rows[rowIndices[rowIdx]];
1173 rhs[rowIdx] = -row[freeIndex];
1175 for (
unsigned int colIdx = 0u; colIdx < 3u; ++colIdx)
1177 coeffMatrix[rowIdx][colIdx] = row[unknownIndices[colIdx]];
1185 for (
unsigned int rowIdx = 0u; rowIdx < 3u; ++rowIdx)
1188 for (
unsigned int colIdx = 0u; colIdx < 3u; ++colIdx)
1190 augmented[rowIdx][colIdx] = coeffMatrix[rowIdx][colIdx];
1192 augmented[rowIdx][3] = rhs[rowIdx];
1196 for (
unsigned int colIdx = 0u; colIdx < 4u; ++colIdx)
1198 maxRowVal = std::max(maxRowVal,
NumericT<T>::abs(augmented[rowIdx][colIdx]));
1201 rowScales[rowIdx] = maxRowVal;
1206 const T scale = T(1) / maxRowVal;
1207 for (
unsigned int colIdx = 0u; colIdx < 4u; ++colIdx)
1209 augmented[rowIdx][colIdx] *= scale;
1215 for (
unsigned int pivot = 0u; pivot < 3u; ++pivot)
1218 unsigned int maxRow = pivot;
1221 for (
unsigned int rowIdx = pivot + 1u; rowIdx < 3u; ++rowIdx)
1232 if (maxRow != pivot)
1234 for (
unsigned int colIdx = 0u; colIdx < 4u; ++colIdx)
1236 std::swap(augmented[pivot][colIdx], augmented[maxRow][colIdx]);
1250 for (
unsigned int rowIdx = pivot + 1u; rowIdx < 3u; ++rowIdx)
1252 const T factor = augmented[rowIdx][pivot] / augmented[pivot][pivot];
1253 for (
unsigned int colIdx = pivot; colIdx < 4u; ++colIdx)
1255 augmented[rowIdx][colIdx] -= factor * augmented[pivot][colIdx];
1261 T solution[3] = {T(0), T(0), T(0)};
1263 for (
int rowIdx = 2; rowIdx >= 0; --rowIdx)
1265 T sum = augmented[rowIdx][3];
1267 for (
unsigned int colIdx = rowIdx + 1u; colIdx < 3u; ++colIdx)
1269 sum -= augmented[rowIdx][colIdx] * solution[colIdx];
1275 solution[rowIdx] = sum / augmented[rowIdx][rowIdx];
1281 for (
unsigned int idx2 = 0u; idx2 < 3u; ++idx2)
1283 candidate[unknownIndices[idx2]] = solution[idx2];
1289 const T residual = (Av - lambdaV).length();
1291 if (residual < bestResidual)
1293 bestResidual = residual;
1294 eigenvector = candidate;
1302 eigenvector =
VectorT4<T>(T(0), T(0), T(0), T(0));
1303 eigenvector[nSolution % 4u] = T(1);
1306 eigenVectors[nSolution] = eigenvector;
1312template <
typename T>
1313template <
typename U>
1316 ocean_assert(arrayValues !=
nullptr);
1318 for (
unsigned int n = 0u; n < 16u; ++n)
1320 arrayValues[n] = U(values[n]);
1324template <
typename T>
1327 ocean_assert(arrayValues !=
nullptr);
1329 memcpy(arrayValues, values,
sizeof(T) * 16);
1332template <
typename T>
1335 return !(*
this == matrix);
1338template <
typename T>
1341 *
this = *
this * matrix;
1345template <
typename T>
1348 *
this = *
this * matrix;
1352template <
typename T>
1355 ocean_assert(index < 16u);
1356 return values[index];
1359template <
typename T>
1362 ocean_assert(index < 16u);
1363 return values[index];
1366template <
typename T>
1369 ocean_assert(row < 4u && column < 4u);
1370 return values[(column << 2) + row];
1373template <
typename T>
1376 ocean_assert(row < 4u && column < 4u);
1377 return values[(column << 2) + row];
1380template <
typename T>
1383 ocean_assert(index < 16u);
1384 return values[index];
1387template <
typename T>
1390 ocean_assert(index < 16u);
1391 return values[index];
1394template <
typename T>
1400template <
typename T>
1406template <
typename T>
1409 size_t seed = std::hash<T>{}(matrix.
values[0]);
1411 for (
unsigned int n = 1u; n < 16u; ++n)
1413 seed ^= std::hash<T>{}(matrix.
values[n]) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1419template <
typename T>
1425template <
typename T>
1428 return isEqual(matrix);
1431template <
typename T>
1441template <
typename T>
1444 for (
unsigned int n = 0u; n < 16u; ++n)
1446 values[n] += matrix.
values[n];
1452template <
typename T>
1462template <
typename T>
1465 for (
unsigned int n = 0u; n < 16u; ++n)
1467 values[n] -= matrix.
values[n];
1473template <
typename T>
1478 for (
unsigned int n = 0u; n < 16u; ++n)
1480 result.
values[n] = -values[n];
1486template <
typename T>
1503 result.
values[10] = values[2] * matrix.
values[8] + values[6] * matrix.
values[9] + values[10] * matrix.
values[10] + values[14] * matrix.
values[11];
1504 result.
values[11] = values[3] * matrix.
values[8] + values[7] * matrix.
values[9] + values[11] * matrix.
values[10] + values[15] * matrix.
values[11];
1506 result.
values[12] = values[0] * matrix.
values[12] + values[4] * matrix.
values[13] + values[8] * matrix.
values[14] + values[12] * matrix.
values[15];
1507 result.
values[13] = values[1] * matrix.
values[12] + values[5] * matrix.
values[13] + values[9] * matrix.
values[14] + values[13] * matrix.
values[15];
1508 result.
values[14] = values[2] * matrix.
values[12] + values[6] * matrix.
values[13] + values[10] * matrix.
values[14] + values[14] * matrix.
values[15];
1509 result.
values[15] = values[3] * matrix.
values[12] + values[7] * matrix.
values[13] + values[11] * matrix.
values[14] + values[15] * matrix.
values[15];
1514#if defined(OCEAN_HARDWARE_AVX_VERSION) && OCEAN_HARDWARE_AVX_VERSION >= 10
1532 __m256d c0 = _mm256_loadu_pd(values + 0);
1533 __m256d c1 = _mm256_loadu_pd(values + 4);
1534 __m256d c2 = _mm256_loadu_pd(values + 8);
1535 __m256d c3 = _mm256_loadu_pd(values + 12);
1539 __m256d v0 = _mm256_broadcast_sd(matrix.
data() + 0);
1540 __m256d r0 = _mm256_mul_pd(c0, v0);
1542 __m256d v1 = _mm256_broadcast_sd(matrix.
data() + 1);
1543 __m256d r1 = _mm256_mul_pd(c1, v1);
1545 r0 = _mm256_add_pd(r0, r1);
1547 __m256d v2 = _mm256_broadcast_sd(matrix.
data() + 2);
1548 __m256d r2 = _mm256_mul_pd(c2, v2);
1550 r0 = _mm256_add_pd(r0, r2);
1552 __m256d v3 = _mm256_broadcast_sd(matrix.
data() + 3);
1553 __m256d r3 = _mm256_mul_pd(c3, v3);
1555 r0 = _mm256_add_pd(r0, r3);
1559 _mm256_storeu_pd(result.
data(), r0);
1563 __m256d v4 = _mm256_broadcast_sd(matrix.
data() + 4);
1564 __m256d r4 = _mm256_mul_pd(c0, v4);
1566 __m256d v5 = _mm256_broadcast_sd(matrix.
data() + 5);
1567 __m256d r5 = _mm256_mul_pd(c1, v5);
1569 r4 = _mm256_add_pd(r4, r5);
1571 __m256d v6 = _mm256_broadcast_sd(matrix.
data() + 6);
1572 __m256d r6 = _mm256_mul_pd(c2, v6);
1574 r4 = _mm256_add_pd(r4, r6);
1576 __m256d v7 = _mm256_broadcast_sd(matrix.
data() + 7);
1577 __m256d r7 = _mm256_mul_pd(c3, v7);
1579 r4 = _mm256_add_pd(r4, r7);
1581 _mm256_storeu_pd(result.
data() + 4, r4);
1585 __m256d v8 = _mm256_broadcast_sd(matrix.
data() + 8);
1586 __m256d r8 = _mm256_mul_pd(c0, v8);
1588 __m256d v9 = _mm256_broadcast_sd(matrix.
data() + 9);
1589 __m256d r9 = _mm256_mul_pd(c1, v9);
1591 r8 = _mm256_add_pd(r8, r9);
1593 __m256d v10 = _mm256_broadcast_sd(matrix.
data() + 10);
1594 __m256d r10 = _mm256_mul_pd(c2, v10);
1596 r8 = _mm256_add_pd(r8, r10);
1598 __m256d v11 = _mm256_broadcast_sd(matrix.
data() + 11);
1599 __m256d r11 = _mm256_mul_pd(c3, v11);
1601 r8 = _mm256_add_pd(r8, r11);
1603 _mm256_storeu_pd(result.
data() + 8, r8);
1607 __m256d v12 = _mm256_broadcast_sd(matrix.
data() + 12);
1608 __m256d r12 = _mm256_mul_pd(c0, v12);
1610 __m256d v13 = _mm256_broadcast_sd(matrix.
data() + 13);
1611 __m256d r13 = _mm256_mul_pd(c1, v13);
1613 r12 = _mm256_add_pd(r12, r13);
1615 __m256d v14 = _mm256_broadcast_sd(matrix.
data() + 14);
1616 __m256d r14 = _mm256_mul_pd(c2, v14);
1618 r12 = _mm256_add_pd(r12, r14);
1620 __m256d v15 = _mm256_broadcast_sd(matrix.
data() + 15);
1621 __m256d r15 = _mm256_mul_pd(c3, v15);
1623 r12 = _mm256_add_pd(r12, r15);
1625 _mm256_storeu_pd(result.
data() + 12, r12);
1639 __m256 c0 = _mm256_broadcast_ps((
const __m128*)values + 0);
1640 __m256 c1 = _mm256_broadcast_ps((
const __m128*)values + 1);
1641 __m256 c2 = _mm256_broadcast_ps((
const __m128*)values + 2);
1642 __m256 c3 = _mm256_broadcast_ps((
const __m128*)values + 3);
1644 __m256 m01 = _mm256_loadu_ps(matrix.
data() + 0);
1645 __m256 m23 = _mm256_loadu_ps(matrix.
data() + 8);
1649 __m256 v0_4 = _mm256_permute_ps(m01, 0x00);
1650 __m256 r0 = _mm256_mul_ps(c0, v0_4);
1652#ifdef OCEAN_COMPILER_MSC
1664 __m256 v1_5 = _mm256_permute_ps(m01, 0x55);
1665 __m256 r1 = _mm256_mul_ps(c1, v1_5);
1667#ifdef OCEAN_COMPILER_MSC
1679 r0 = _mm256_add_ps(r0, r1);
1682 __m256 v2_6 = _mm256_permute_ps(m01, 0xAA);
1683 __m256 r2 = _mm256_mul_ps(c2, v2_6);
1685 r0 = _mm256_add_ps(r0, r2);
1688 __m256 v3_7 = _mm256_permute_ps(m01, 0xFF);
1689 __m256 r3 = _mm256_mul_ps(c3, v3_7);
1691 r0 = _mm256_add_ps(r0, r3);
1695 _mm256_storeu_ps(result.
data(), r0);
1700 __m256 v8_12 = _mm256_permute_ps(m23, 0x00);
1701 __m256 r8 = _mm256_mul_ps(c0, v8_12);
1704 __m256 v9_13 = _mm256_permute_ps(m23, 0x55);
1705 __m256 r9 = _mm256_mul_ps(c1, v9_13);
1707 r8 = _mm256_add_ps(r8, r9);
1710 __m256 v10_14 = _mm256_permute_ps(m23, 0xAA);
1711 __m256 r10 = _mm256_mul_ps(c2, v10_14);
1713 r8 = _mm256_add_ps(r8, r10);
1716 __m256 v11_15 = _mm256_permute_ps(m23, 0xFF);
1717 __m256 r11 = _mm256_mul_ps(c3, v11_15);
1719 r8 = _mm256_add_ps(r8, r11);
1721 _mm256_storeu_ps(result.
data() + 8, r8);
1728#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 10
1746 __m128 c0 = _mm_loadu_ps(values + 0);
1747 __m128 c1 = _mm_loadu_ps(values + 4);
1748 __m128 c2 = _mm_loadu_ps(values + 8);
1749 __m128 c3 = _mm_loadu_ps(values + 12);
1753 __m128 v0 = _mm_load1_ps(matrix.
data() + 0);
1754 __m128 r0 = _mm_mul_ps(c0, v0);
1756 __m128 v1 = _mm_load1_ps(matrix.
data() + 1);
1757 __m128 r1 = _mm_mul_ps(c1, v1);
1759 r0 = _mm_add_ps(r0, r1);
1761 __m128 v2 = _mm_load1_ps(matrix.
data() + 2);
1762 __m128 r2 = _mm_mul_ps(c2, v2);
1764 r0 = _mm_add_ps(r0, r2);
1766 __m128 v3 = _mm_load1_ps(matrix.
data() + 3);
1767 __m128 r3 = _mm_mul_ps(c3, v3);
1769 r0 = _mm_add_ps(r0, r3);
1773 _mm_storeu_ps(result.
data(), r0);
1777 __m128 v4 = _mm_load1_ps(matrix.
data() + 4);
1778 __m128 r4 = _mm_mul_ps(c0, v4);
1780 __m128 v5 = _mm_load1_ps(matrix.
data() + 5);
1781 __m128 r5 = _mm_mul_ps(c1, v5);
1783 r4 = _mm_add_ps(r4, r5);
1785 __m128 v6 = _mm_load1_ps(matrix.
data() + 6);
1786 __m128 r6 = _mm_mul_ps(c2, v6);
1788 r4 = _mm_add_ps(r4, r6);
1790 __m128 v7 = _mm_load1_ps(matrix.
data() + 7);
1791 __m128 r7 = _mm_mul_ps(c3, v7);
1793 r4 = _mm_add_ps(r4, r7);
1795 _mm_storeu_ps(result.
data() + 4, r4);
1799 __m128 v8 = _mm_load1_ps(matrix.
data() + 8);
1800 __m128 r8 = _mm_mul_ps(c0, v8);
1802 __m128 v9 = _mm_load1_ps(matrix.
data() + 9);
1803 __m128 r9 = _mm_mul_ps(c1, v9);
1805 r8 = _mm_add_ps(r8, r9);
1807 __m128 v10 = _mm_load1_ps(matrix.
data() + 10);
1808 __m128 r10 = _mm_mul_ps(c2, v10);
1810 r8 = _mm_add_ps(r8, r10);
1812 __m128 v11 = _mm_load1_ps(matrix.
data() + 11);
1813 __m128 r11 = _mm_mul_ps(c3, v11);
1815 r8 = _mm_add_ps(r8, r11);
1817 _mm_storeu_ps(result.
data() + 8, r8);
1821 __m128 v12 = _mm_load1_ps(matrix.
data() + 12);
1822 __m128 r12 = _mm_mul_ps(c0, v12);
1824 __m128 v13 = _mm_load1_ps(matrix.
data() + 13);
1825 __m128 r13 = _mm_mul_ps(c1, v13);
1827 r12 = _mm_add_ps(r12, r13);
1829 __m128 v14 = _mm_load1_ps(matrix.
data() + 14);
1830 __m128 r14 = _mm_mul_ps(c2, v14);
1832 r12 = _mm_add_ps(r12, r14);
1834 __m128 v15 = _mm_load1_ps(matrix.
data() + 15);
1835 __m128 r15 = _mm_mul_ps(c3, v15);
1837 r12 = _mm_add_ps(r12, r15);
1839 _mm_storeu_ps(result.
data() + 12, r12);
1848template <
typename T>
1853 result.
values[0] = values[0] * matrix[0] + values[4] * matrix[1] + values[8] * matrix[2];
1854 result.
values[1] = values[1] * matrix[0] + values[5] * matrix[1] + values[9] * matrix[2];
1855 result.
values[2] = values[2] * matrix[0] + values[6] * matrix[1] + values[10] * matrix[2];
1856 result.
values[3] = values[3] * matrix[0] + values[7] * matrix[1] + values[11] * matrix[2];
1858 result.
values[4] = values[0] * matrix[4] + values[4] * matrix[5] + values[8] * matrix[6];
1859 result.
values[5] = values[1] * matrix[4] + values[5] * matrix[5] + values[9] * matrix[6];
1860 result.
values[6] = values[2] * matrix[4] + values[6] * matrix[5] + values[10] * matrix[6];
1861 result.
values[7] = values[3] * matrix[4] + values[7] * matrix[5] + values[11] * matrix[6];
1863 result.
values[8] = values[0] * matrix[8] + values[4] * matrix[9] + values[8] * matrix[10];
1864 result.
values[9] = values[1] * matrix[8] + values[5] * matrix[9] + values[9] * matrix[10];
1865 result.
values[10] = values[2] * matrix[8] + values[6] * matrix[9] + values[10] * matrix[10];
1866 result.
values[11] = values[3] * matrix[8] + values[7] * matrix[9] + values[11] * matrix[10];
1868 result.
values[12] = values[0] * matrix[12] + values[4] * matrix[13] + values[8] * matrix[14] + values[12];
1869 result.
values[13] = values[1] * matrix[12] + values[5] * matrix[13] + values[9] * matrix[14] + values[13];
1870 result.
values[14] = values[2] * matrix[12] + values[6] * matrix[13] + values[10] * matrix[14] + values[14];
1871 result.
values[15] = values[3] * matrix[12] + values[7] * matrix[13] + values[11] * matrix[14] + values[15];
1876template <
typename T>
1879 const T w = values[3] * vector[0] + values[7] * vector[1] + values[11] * vector[2] + values[15];
1882 const T factor = 1 / w;
1884 return VectorT3<T>((values[0] * vector[0] + values[4] * vector[1] + values[8] * vector[2] + values[12]) * factor,
1885 (values[1] * vector[0] + values[5] * vector[1] + values[9] * vector[2] + values[13]) * factor,
1886 (values[2] * vector[0] + values[6] * vector[1] + values[10] * vector[2] + values[14]) * factor);
1889template <
typename T>
1892 return VectorT4<T>(values[0] * vector[0] + values[4] * vector[1] + values[8] * vector[2] + values[12] * vector[3],
1893 values[1] * vector[0] + values[5] * vector[1] + values[9] * vector[2] + values[13] * vector[3],
1894 values[2] * vector[0] + values[6] * vector[1] + values[10] * vector[2] + values[14] * vector[3],
1895 values[3] * vector[0] + values[7] * vector[1] + values[11] * vector[2] + values[15] * vector[3]);
1898#if defined(OCEAN_HARDWARE_AVX_VERSION) && OCEAN_HARDWARE_AVX_VERSION >= 10
1900#ifdef OCEAN_USE_SLOWER_IMPLEMENTATION
1918 __m256d row0 = _mm256_loadu_pd(values + 0);
1919 __m256d row1 = _mm256_loadu_pd(values + 4);
1920 __m256d row2 = _mm256_loadu_pd(values + 8);
1921 __m256d row3 = _mm256_loadu_pd(values + 12);
1924 __m256d v = _mm256_loadu_pd(vector.
data());
1934 __m256d temp0 = _mm256_shuffle_pd(row0, row1, 0x00);
1936 __m256d temp2 = _mm256_shuffle_pd(row0, row1, 0x0F);
1938 __m256d temp1 = _mm256_shuffle_pd(row2, row3, 0x00);
1940 __m256d temp3 = _mm256_shuffle_pd(row2, row3, 0x0F);
1943 row0 = _mm256_permute2f128_pd(temp0, temp1, 0x20);
1945 row1 = _mm256_permute2f128_pd(temp2, temp3, 0x20);
1947 row2 = _mm256_permute2f128_pd(temp0, temp1, 0x31);
1949 row3 = _mm256_permute2f128_pd(temp2, temp3, 0x31);
1951#ifdef OCEAN_COMPILER_MSC
1952 ocean_assert(row0.m256d_f64[0] == values[0] && row0.m256d_f64[1] == values[4] && row0.m256d_f64[2] == values[ 8] && row0.m256d_f64[3] == values[12]);
1953 ocean_assert(row1.m256d_f64[0] == values[1] && row1.m256d_f64[1] == values[5] && row1.m256d_f64[2] == values[ 9] && row1.m256d_f64[3] == values[13]);
1954 ocean_assert(row2.m256d_f64[0] == values[2] && row2.m256d_f64[1] == values[6] && row2.m256d_f64[2] == values[10] && row2.m256d_f64[3] == values[14]);
1955 ocean_assert(row3.m256d_f64[0] == values[3] && row3.m256d_f64[1] == values[7] && row3.m256d_f64[2] == values[11] && row3.m256d_f64[3] == values[15]);
1960 __m256d r0v = _mm256_mul_pd(row0, v);
1961 __m256d r1v = _mm256_mul_pd(row1, v);
1962 __m256d r2v = _mm256_mul_pd(row2, v);
1963 __m256d r3v = _mm256_mul_pd(row3, v);
1966 __m256d sum_interleaved_r0_r1 = _mm256_hadd_pd(r0v, r1v);
1967 __m256d sum_interleaved_r2_r3 = _mm256_hadd_pd(r2v, r3v);
1970 __m256d sum_first = _mm256_permute2f128_pd(sum_interleaved_r0_r1, sum_interleaved_r2_r3, 0x20);
1971 __m256d sum_second = _mm256_permute2f128_pd(sum_interleaved_r0_r1, sum_interleaved_r2_r3, 0x31);
1974 __m256d sum = _mm256_add_pd(sum_first, sum_second);
1977 _mm256_storeu_pd(result.
data(), sum);
1979 ocean_assert(
NumericD::isEqual(result[0], values[0] * vector[0] + values[4] * vector[1] + values[ 8] * vector[2] + values[12] * vector[3],
NumericD::eps() * 100));
1980 ocean_assert(
NumericD::isEqual(result[1], values[1] * vector[0] + values[5] * vector[1] + values[ 9] * vector[2] + values[13] * vector[3],
NumericD::eps() * 100));
1981 ocean_assert(
NumericD::isEqual(result[2], values[2] * vector[0] + values[6] * vector[1] + values[10] * vector[2] + values[14] * vector[3],
NumericD::eps() * 100));
1982 ocean_assert(
NumericD::isEqual(result[3], values[3] * vector[0] + values[7] * vector[1] + values[11] * vector[2] + values[15] * vector[3],
NumericD::eps() * 100));
2004 __m256d v0 = _mm256_broadcast_sd(vector.
data() + 0);
2007 __m256d c0 = _mm256_loadu_pd(values + 0);
2010 __m256d r0 = _mm256_mul_pd(c0, v0);
2014 __m256d v1 = _mm256_broadcast_sd(vector.
data() + 1);
2015 __m256d c1 = _mm256_loadu_pd(values + 4);
2016 __m256d r1 = _mm256_mul_pd(c1, v1);
2019 r0 = _mm256_add_pd(r0, r1);
2023 __m256d v2 = _mm256_broadcast_sd(vector.
data() + 2);
2024 __m256d c2 = _mm256_loadu_pd(values + 8);
2025 __m256d r2 = _mm256_mul_pd(c2, v2);
2028 r0 = _mm256_add_pd(r0, r2);
2032 __m256d v3 = _mm256_broadcast_sd(vector.
data() + 3);
2033 __m256d c3 = _mm256_loadu_pd(values + 12);
2034 __m256d r3 = _mm256_mul_pd(c3, v3);
2037 r0 = _mm256_add_pd(r0, r3);
2042 _mm256_storeu_pd(result.
data(), r0);
2051#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 20
2076 __m128d v0 = _mm_load1_pd(vector.
data() + 0);
2079 __m128d c0a = _mm_loadu_pd(values + 0);
2080 __m128d c0b = _mm_loadu_pd(values + 2);
2083 __m128d r0a = _mm_mul_pd(c0a, v0);
2084 __m128d r0b = _mm_mul_pd(c0b, v0);
2088 __m128d v1 = _mm_load1_pd(vector.
data() + 1);
2090 __m128d c1a = _mm_loadu_pd(values + 4);
2091 __m128d c1b = _mm_loadu_pd(values + 6);
2093 __m128d r1a = _mm_mul_pd(c1a, v1);
2094 __m128d r1b = _mm_mul_pd(c1b, v1);
2097 r0a = _mm_add_pd(r0a, r1a);
2098 r0b = _mm_add_pd(r0b, r1b);
2102 __m128d v2 = _mm_load1_pd(vector.
data() + 2);
2104 __m128d c2a = _mm_loadu_pd(values + 8);
2105 __m128d c2b = _mm_loadu_pd(values + 10);
2107 __m128d r2a = _mm_mul_pd(c2a, v2);
2108 __m128d r2b = _mm_mul_pd(c2b, v2);
2111 r0a = _mm_add_pd(r0a, r2a);
2112 r0b = _mm_add_pd(r0b, r2b);
2116 __m128d v3 = _mm_load1_pd(vector.
data() + 3);
2118 __m128d c3a = _mm_loadu_pd(values + 12);
2119 __m128d c3b = _mm_loadu_pd(values + 14);
2121 __m128d r3a = _mm_mul_pd(c3a, v3);
2122 __m128d r3b = _mm_mul_pd(c3b, v3);
2125 r0a = _mm_add_pd(r0a, r3a);
2126 r0b = _mm_add_pd(r0b, r3b);
2131 _mm_storeu_pd(result.
data() + 0, r0a);
2132 _mm_storeu_pd(result.
data() + 2, r0b);
2141#ifdef OCEAN_USE_SLOWER_IMPLEMENTATION
2145#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
2162 __m128 row0 = _mm_loadu_ps(values + 0);
2163 __m128 row1 = _mm_loadu_ps(values + 4);
2164 __m128 row2 = _mm_loadu_ps(values + 8);
2165 __m128 row3 = _mm_loadu_ps(values + 12);
2168 __m128 v = _mm_loadu_ps(vector.
data());
2178 __m128 temp0 = _mm_shuffle_ps(row0, row1, 0x44);
2180 __m128 temp2 = _mm_shuffle_ps(row0, row1, 0xEE);
2182 __m128 temp1 = _mm_shuffle_ps(row2, row3, 0x44);
2184 __m128 temp3 = _mm_shuffle_ps(row2, row3, 0xEE);
2187 row0 = _mm_shuffle_ps(temp0, temp1, 0x88);
2189 row1 = _mm_shuffle_ps(temp0, temp1, 0xDD);
2191 row2 = _mm_shuffle_ps(temp2, temp3, 0x88);
2193 row3 = _mm_shuffle_ps(temp2, temp3, 0xDD);
2195#ifdef OCEAN_COMPILER_MSC
2196 ocean_assert(row0.m128_f32[0] == values[0] && row0.m128_f32[1] == values[4] && row0.m128_f32[2] == values[ 8] && row0.m128_f32[3] == values[12]);
2197 ocean_assert(row1.m128_f32[0] == values[1] && row1.m128_f32[1] == values[5] && row1.m128_f32[2] == values[ 9] && row1.m128_f32[3] == values[13]);
2198 ocean_assert(row2.m128_f32[0] == values[2] && row2.m128_f32[1] == values[6] && row2.m128_f32[2] == values[10] && row2.m128_f32[3] == values[14]);
2199 ocean_assert(row3.m128_f32[0] == values[3] && row3.m128_f32[1] == values[7] && row3.m128_f32[2] == values[11] && row3.m128_f32[3] == values[15]);
2203 row0 = _mm_dp_ps(row0, v, 0xF1);
2206 row1 = _mm_dp_ps(row1, v, 0xF2);
2207 row2 = _mm_dp_ps(row2, v, 0xF4);
2208 row3 = _mm_dp_ps(row3, v, 0xF8);
2211 __m128 result01 = _mm_or_ps(row0, row1);
2212 __m128 result23 = _mm_or_ps(row2, row3);
2213 __m128 result03 = _mm_or_ps(result01, result23);
2216 _mm_storeu_ps(result.
data(), result03);
2225#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 10
2251 __m128 v0 = _mm_load1_ps(vector.
data() + 0);
2254 __m128 c0 = _mm_loadu_ps(values + 0);
2257 __m128 r0 = _mm_mul_ps(c0, v0);
2261 __m128 v1 = _mm_load1_ps(vector.
data() + 1);
2262 __m128 c1 = _mm_loadu_ps(values + 4);
2263 __m128 r1 = _mm_mul_ps(c1, v1);
2266 r0 = _mm_add_ps(r0, r1);
2270 __m128 v2 = _mm_load1_ps(vector.
data() + 2);
2271 __m128 c2 = _mm_loadu_ps(values + 8);
2272 __m128 r2 = _mm_mul_ps(c2, v2);
2275 r0 = _mm_add_ps(r0, r2);
2279 __m128 v3 = _mm_load1_ps(vector.
data() + 3);
2280 __m128 c3 = _mm_loadu_ps(values + 12);
2281 __m128 r3 = _mm_mul_ps(c3, v3);
2284 r0 = _mm_add_ps(r0, r3);
2289 _mm_storeu_ps(result.
data(), r0);
2298#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
2318 float64x2_t v0 = vld1q_dup_f64(vector.
data() + 0);
2321 float64x2_t c0a = vld1q_f64(values + 0);
2322 float64x2_t c0b = vld1q_f64(values + 2);
2325 float64x2_t r0a = vmulq_f64(c0a, v0);
2326 float64x2_t r0b = vmulq_f64(c0b, v0);
2330 float64x2_t v1 = vld1q_dup_f64(vector.
data() + 1);
2332 float64x2_t c1a = vld1q_f64(values + 4);
2333 float64x2_t c1b = vld1q_f64(values + 6);
2335 float64x2_t r1a = vmulq_f64(c1a, v1);
2336 float64x2_t r1b = vmulq_f64(c1b, v1);
2339 r0a = vaddq_f64(r0a, r1a);
2340 r0b = vaddq_f64(r0b, r1b);
2344 float64x2_t v2 = vld1q_dup_f64(vector.
data() + 2);
2346 float64x2_t c2a = vld1q_f64(values + 8);
2347 float64x2_t c2b = vld1q_f64(values + 10);
2349 float64x2_t r2a = vmulq_f64(c2a, v2);
2350 float64x2_t r2b = vmulq_f64(c2b, v2);
2353 r0a = vaddq_f64(r0a, r2a);
2354 r0b = vaddq_f64(r0b, r2b);
2358 float64x2_t v3 = vld1q_dup_f64(vector.
data() + 3);
2360 float64x2_t c3a = vld1q_f64(values + 12);
2361 float64x2_t c3b = vld1q_f64(values + 14);
2363 float64x2_t r3a = vmulq_f64(c3a, v3);
2364 float64x2_t r3b = vmulq_f64(c3b, v3);
2367 r0a = vaddq_f64(r0a, r3a);
2368 r0b = vaddq_f64(r0b, r3b);
2373 vst1q_f64(result.
data() + 0, r0a);
2374 vst1q_f64(result.
data() + 2, r0b);
2397 float32x4_t v0 = vld1q_dup_f32(vector.
data() + 0);
2400 float32x4_t c0 = vld1q_f32(values + 0);
2403 float32x4_t r0 = vmulq_f32(c0, v0);
2407 float32x4_t v1 = vld1q_dup_f32(vector.
data() + 1);
2408 float32x4_t c1 = vld1q_f32(values + 4);
2409 float32x4_t r1 = vmulq_f32(c1, v1);
2412 r0 = vaddq_f32(r0, r1);
2416 float32x4_t v2 = vld1q_dup_f32(vector.
data() + 2);
2417 float32x4_t c2 = vld1q_f32(values + 8);
2418 float32x4_t r2 = vmulq_f32(c2, v2);
2421 r0 = vaddq_f32(r0, r2);
2425 float32x4_t v3 = vld1q_dup_f32(vector.
data() + 3);
2426 float32x4_t c3 = vld1q_f32(values + 12);
2427 float32x4_t r3 = vmulq_f32(c3, v3);
2430 r0 = vaddq_f32(r0, r3);
2435 vst1q_f32(result.
data(), r0);
2442template <
typename T>
2447 result.
values[0] *= value;
2448 result.
values[1] *= value;
2449 result.
values[2] *= value;
2450 result.
values[3] *= value;
2451 result.
values[4] *= value;
2452 result.
values[5] *= value;
2453 result.
values[6] *= value;
2454 result.
values[7] *= value;
2455 result.
values[8] *= value;
2456 result.
values[9] *= value;
2457 result.
values[10] *= value;
2458 result.
values[11] *= value;
2459 result.
values[12] *= value;
2460 result.
values[13] *= value;
2461 result.
values[14] *= value;
2462 result.
values[15] *= value;
2467template <
typename T>
2480 values[10] *= value;
2481 values[11] *= value;
2482 values[12] *= value;
2483 values[13] *= value;
2484 values[14] *= value;
2485 values[15] *= value;
2490template <
typename T>
2509 ocean_assert(aspectRatio > 0);
2510 ocean_assert(nearDistance > 0);
2511 ocean_assert(nearDistance < farDistance);
2516 ocean_assert(matrix(1, 0) == 0 && matrix(2, 0) == 0 && matrix(3, 0) == 0);
2517 ocean_assert(matrix(0, 1) == 0 && matrix(2, 1) == 0 && matrix(3, 1) == 0);
2518 ocean_assert(matrix(0, 2) == 0 && matrix(1, 2) == 0);
2519 ocean_assert(matrix(0, 3) == 0 && matrix(1, 3) == 0 && matrix(3, 3) == 0);
2524 const T factor = T(1.0) / (nearDistance - farDistance);
2526 matrix(0, 0) = f / aspectRatio;
2528 matrix(2, 2) = (farDistance + nearDistance) * factor;
2529 matrix(3, 2) = -T(1.0);
2530 matrix(2, 3) = (T(2.0) * farDistance * nearDistance) * factor;
2535template <
typename T>
2553 ocean_assert(anyCamera.
isValid());
2555 ocean_assert(nearDistance > 0);
2556 ocean_assert(nearDistance < farDistance);
2560 ocean_assert(fxPixel > T(1) && fyPixel > T(1));
2565 const T width_2 = T(anyCamera.
width()) / T(2);
2566 const T height_2 = T(anyCamera.
height()) / T(2);
2571 const T fx = fxPixel / width_2;
2572 const T fy = fyPixel / height_2;
2574 const T mx = (mxPixel - width_2) / width_2;
2575 const T my = (myPixel - height_2) / height_2;
2577 const T factor = T(1.0) / (nearDistance - farDistance);
2585 matrix(2, 2) = (farDistance + nearDistance) * factor;
2586 matrix(3, 2) = -T(1);
2587 matrix(2, 3) = (T(2) * farDistance * nearDistance) * factor;
2592template <
typename T>
2613 ocean_assert(matrix(1, 0) == 0 && matrix(2, 0) == 0 && matrix(3, 0) == 0);
2614 ocean_assert(matrix(0, 1) == 0 && matrix(2, 1) == 0 && matrix(3, 1) == 0);
2615 ocean_assert(matrix(0, 3) == 0 && matrix(1, 3) == 0 && matrix(3, 3) == 0);
2617 const T rightLeft = T(1.0) / (right - left);
2618 const T near2 = nearDistance * T(2.0);
2620 matrix(0, 0) = near2 * rightLeft;
2621 matrix(0, 2) = (right + left) * rightLeft;
2623 const T topBottom = T(1.0) / (top - bottom);
2625 matrix(1, 1) = near2 * topBottom;
2626 matrix(1, 2) = (top + bottom) * topBottom;
2628 const T farNear = T(1.0) / (farDistance - nearDistance);
2630 matrix(2, 2) = -(farDistance + nearDistance) * farNear;
2631 matrix(2, 3) = -T(2.0) * farDistance * nearDistance * farNear;
2633 matrix(3, 2) = -T(1.0);
2638template <
typename T>
2642 ocean_assert(nearDistance >=
NumericT<T>::eps() && farDistance > nearDistance);
2649 const VectorT3<T> leftTop(width * -T(0.5), height * T(0.5), 0);
2650 const VectorT3<T> rightBottom(width * T(0.5), height * -T(0.5), 0);
2652 const VectorT3<T> leftTopInCamera(inversedViewingMatrix * leftTop);
2653 const VectorT3<T> rightBottomInCamera(inversedViewingMatrix * rightBottom);
2655 const T factor = nearDistance / planeDistance;
2657 return frustumMatrix(factor * leftTopInCamera.
x(), factor * rightBottomInCamera.
x(), factor * leftTopInCamera.
y(), factor * rightBottomInCamera.
y(), nearDistance, farDistance);
2660template <
typename T>
2663 ocean_assert((vectors && results) || number == 0);
2665 for (
size_t n = 0; n < number; ++n)
2667 results[n] = matrix * vectors[n];
2671#if defined(OCEAN_HARDWARE_AVX_VERSION) && OCEAN_HARDWARE_AVX_VERSION >= 10
2687 __m256d c0 = _mm256_loadu_pd(matrix.
values + 0);
2688 __m256d c1 = _mm256_loadu_pd(matrix.
values + 4);
2689 __m256d c2 = _mm256_loadu_pd(matrix.
values + 8);
2690 __m256d c3 = _mm256_loadu_pd(matrix.
values + 12);
2692 for (
size_t n = 0; n < number; ++n)
2694 __m256d v0 = _mm256_broadcast_sd(vectors[n].data() + 0);
2695 __m256d r0 = _mm256_mul_pd(c0, v0);
2697 __m256d v1 = _mm256_broadcast_sd(vectors[n].data() + 1);
2698 __m256d r1 = _mm256_mul_pd(c1, v1);
2700 r0 = _mm256_add_pd(r0, r1);
2702 __m256d v2 = _mm256_broadcast_sd(vectors[n].data() + 2);
2703 __m256d r2 = _mm256_mul_pd(c2, v2);
2705 r0 = _mm256_add_pd(r0, r2);
2707 __m256d v3 = _mm256_broadcast_sd(vectors[n].data() + 3);
2708 __m256d r3 = _mm256_mul_pd(c3, v3);
2710 r0 = _mm256_add_pd(r0, r3);
2712 _mm256_storeu_pd(results[n].data(), r0);
2718#ifdef OCEAN_USE_SLOWER_IMPLEMENTATION
2722#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
2739 __m128 row0 = _mm_loadu_ps(matrix.
values + 0);
2740 __m128 row1 = _mm_loadu_ps(matrix.
values + 4);
2741 __m128 row2 = _mm_loadu_ps(matrix.
values + 8);
2742 __m128 row3 = _mm_loadu_ps(matrix.
values + 12);
2752 __m128 temp0 = _mm_shuffle_ps(row0, row1, 0x44);
2754 __m128 temp2 = _mm_shuffle_ps(row0, row1, 0xEE);
2756 __m128 temp1 = _mm_shuffle_ps(row2, row3, 0x44);
2758 __m128 temp3 = _mm_shuffle_ps(row2, row3, 0xEE);
2761 row0 = _mm_shuffle_ps(temp0, temp1, 0x88);
2763 row1 = _mm_shuffle_ps(temp0, temp1, 0xDD);
2765 row2 = _mm_shuffle_ps(temp2, temp3, 0x88);
2767 row3 = _mm_shuffle_ps(temp2, temp3, 0xDD);
2769#ifdef OCEAN_COMPILER_MSC
2770 ocean_assert(row0.m128_f32[0] == matrix.
values[0] && row0.m128_f32[1] == matrix.
values[4] && row0.m128_f32[2] == matrix.
values[ 8] && row0.m128_f32[3] == matrix.
values[12]);
2771 ocean_assert(row1.m128_f32[0] == matrix.
values[1] && row1.m128_f32[1] == matrix.
values[5] && row1.m128_f32[2] == matrix.
values[ 9] && row1.m128_f32[3] == matrix.
values[13]);
2772 ocean_assert(row2.m128_f32[0] == matrix.
values[2] && row2.m128_f32[1] == matrix.
values[6] && row2.m128_f32[2] == matrix.
values[10] && row2.m128_f32[3] == matrix.
values[14]);
2773 ocean_assert(row3.m128_f32[0] == matrix.
values[3] && row3.m128_f32[1] == matrix.
values[7] && row3.m128_f32[2] == matrix.
values[11] && row3.m128_f32[3] == matrix.
values[15]);
2776 for (
size_t n = 0u; n < number; ++n)
2779 __m128 v = _mm_loadu_ps(vectors[n].data());
2782 __m128 dot0 = _mm_dp_ps(row0, v, 0xF1);
2785 __m128 dot1 = _mm_dp_ps(row1, v, 0xF2);
2786 __m128 dot2 = _mm_dp_ps(row2, v, 0xF4);
2787 __m128 dot3 = _mm_dp_ps(row3, v, 0xF8);
2790 __m128 result01 = _mm_or_ps(dot0, dot1);
2791 __m128 result23 = _mm_or_ps(dot2, dot3);
2792 __m128 result03 = _mm_or_ps(result01, result23);
2794 _mm_storeu_ps(results[n].data(), result03);
2802#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 20
2817 __m128d c0a = _mm_loadu_pd(matrix.
values + 0);
2818 __m128d c0b = _mm_loadu_pd(matrix.
values + 2);
2819 __m128d c1a = _mm_loadu_pd(matrix.
values + 4);
2820 __m128d c1b = _mm_loadu_pd(matrix.
values + 6);
2821 __m128d c2a = _mm_loadu_pd(matrix.
values + 8);
2822 __m128d c2b = _mm_loadu_pd(matrix.
values + 10);
2823 __m128d c3a = _mm_loadu_pd(matrix.
values + 12);
2824 __m128d c3b = _mm_loadu_pd(matrix.
values + 14);
2826 for (
size_t n = 0u; n < number; ++n)
2828 __m128d v0 = _mm_load1_pd(vectors[n].data() + 0);
2829 __m128d v1 = _mm_load1_pd(vectors[n].data() + 1);
2830 __m128d v2 = _mm_load1_pd(vectors[n].data() + 2);
2831 __m128d v3 = _mm_load1_pd(vectors[n].data() + 3);
2834 __m128d r0a = _mm_mul_pd(c0a, v0);
2835 __m128d r0b = _mm_mul_pd(c0b, v0);
2838 __m128d r1a = _mm_mul_pd(c1a, v1);
2839 __m128d r1b = _mm_mul_pd(c1b, v1);
2841 r0a = _mm_add_pd(r0a, r1a);
2842 r0b = _mm_add_pd(r0b, r1b);
2845 __m128d r2a = _mm_mul_pd(c2a, v2);
2846 __m128d r2b = _mm_mul_pd(c2b, v2);
2847 r0a = _mm_add_pd(r0a, r2a);
2848 r0b = _mm_add_pd(r0b, r2b);
2851 __m128d r3a = _mm_mul_pd(c3a, v3);
2852 __m128d r3b = _mm_mul_pd(c3b, v3);
2853 r0a = _mm_add_pd(r0a, r3a);
2854 r0b = _mm_add_pd(r0b, r3b);
2856 _mm_storeu_pd(results[n].data() + 0, r0a);
2857 _mm_storeu_pd(results[n].data() + 2, r0b);
2863#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 10
2878 __m128 c0 = _mm_loadu_ps(matrix.
values + 0);
2879 __m128 c1 = _mm_loadu_ps(matrix.
values + 4);
2880 __m128 c2 = _mm_loadu_ps(matrix.
values + 8);
2881 __m128 c3 = _mm_loadu_ps(matrix.
values + 12);
2883 for (
size_t n = 0u; n < number; ++n)
2885 __m128 v0 = _mm_load1_ps(vectors[n].data() + 0);
2886 __m128 v1 = _mm_load1_ps(vectors[n].data() + 1);
2887 __m128 v2 = _mm_load1_ps(vectors[n].data() + 2);
2888 __m128 v3 = _mm_load1_ps(vectors[n].data() + 3);
2891 __m128 r0 = _mm_mul_ps(c0, v0);
2894 __m128 r1 = _mm_mul_ps(c1, v1);
2896 r0 = _mm_add_ps(r0, r1);
2899 __m128 r2 = _mm_mul_ps(c2, v2);
2900 r0 = _mm_add_ps(r0, r2);
2903 __m128 r3 = _mm_mul_ps(c3, v3);
2904 r0 = _mm_add_ps(r0, r3);
2906 _mm_storeu_ps(results[n].data(), r0);
2916#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
2926 float64x2_t c0a = vld1q_f64(matrix.
values + 0);
2927 float64x2_t c0b = vld1q_f64(matrix.
values + 2);
2928 float64x2_t c1a = vld1q_f64(matrix.
values + 4);
2929 float64x2_t c1b = vld1q_f64(matrix.
values + 6);
2930 float64x2_t c2a = vld1q_f64(matrix.
values + 8);
2931 float64x2_t c2b = vld1q_f64(matrix.
values + 10);
2932 float64x2_t c3a = vld1q_f64(matrix.
values + 12);
2933 float64x2_t c3b = vld1q_f64(matrix.
values + 14);
2935 for (
size_t n = 0u; n < number; ++n)
2937 float64x2_t v0 = vld1q_dup_f64(vectors[n].data() + 0);
2938 float64x2_t v1 = vld1q_dup_f64(vectors[n].data() + 1);
2939 float64x2_t v2 = vld1q_dup_f64(vectors[n].data() + 2);
2940 float64x2_t v3 = vld1q_dup_f64(vectors[n].data() + 3);
2942 float64x2_t r0a = vmulq_f64(c0a, v0);
2943 float64x2_t r0b = vmulq_f64(c0b, v0);
2945 float64x2_t r1a = vmulq_f64(c1a, v1);
2946 float64x2_t r1b = vmulq_f64(c1b, v1);
2948 r0a = vaddq_f64(r0a, r1a);
2949 r0b = vaddq_f64(r0b, r1b);
2951 float64x2_t r2a = vmulq_f64(c2a, v2);
2952 float64x2_t r2b = vmulq_f64(c2b, v2);
2954 r0a = vaddq_f64(r0a, r2a);
2955 r0b = vaddq_f64(r0b, r2b);
2957 float64x2_t r3a = vmulq_f64(c3a, v3);
2958 float64x2_t r3b = vmulq_f64(c3b, v3);
2960 r0a = vaddq_f64(r0a, r3a);
2961 r0b = vaddq_f64(r0b, r3b);
2963 vst1q_f64(results[n].data() + 0, r0a);
2964 vst1q_f64(results[n].data() + 2, r0b);
2976 float32x4_t c0 = vld1q_f32(matrix.
values + 0);
2977 float32x4_t c1 = vld1q_f32(matrix.
values + 4);
2978 float32x4_t c2 = vld1q_f32(matrix.
values + 8);
2979 float32x4_t c3 = vld1q_f32(matrix.
values + 12);
2981 for (
size_t n = 0u; n < number; ++n)
2983 float32x4_t v0 = vld1q_dup_f32(vectors[n].data() + 0);
2984 float32x4_t v1 = vld1q_dup_f32(vectors[n].data() + 1);
2985 float32x4_t v2 = vld1q_dup_f32(vectors[n].data() + 2);
2986 float32x4_t v3 = vld1q_dup_f32(vectors[n].data() + 3);
2989 float32x4_t r0 = vmulq_f32(c0, v0);
2992 float32x4_t r1 = vmulq_f32(c1, v1);
2994 r0 = vaddq_f32(r0, r1);
2997 float32x4_t r2 = vmulq_f32(c2, v2);
2999 r0 = vaddq_f32(r0, r2);
3002 float32x4_t r3 = vmulq_f32(c3, v3);
3004 r0 = vaddq_f32(r0, r3);
3006 vst1q_f32(results[n].data(), r0);
3012template <
typename T>
3013template <
typename U>
3016 std::vector< SquareMatrixT4<T> > result;
3017 result.reserve(matrices.size());
3019 for (
typename std::vector<
SquareMatrixT4<U> >::const_iterator i = matrices.begin(); i != matrices.end(); ++i)
3041template <
typename T>
3042template <
typename U>
3045 std::vector< SquareMatrixT4<T> > result;
3046 result.reserve(size);
3048 for (
size_t n = 0; n < size; ++n)
3056template <
typename T>
3059 ocean_assert(row0 < 4u && row1 < 4u);
3066 T* first = values + row0;
3067 T* second = values + row1;
3092template <
typename T>
3095 ocean_assert(row < 4u);
3097 T* element = values + row;
3108template <
typename T>
3111 ocean_assert(targetRow < 4u && sourceRow < 4u);
3112 ocean_assert(targetRow != sourceRow);
3114 T* target = values + targetRow;
3115 T* source = values + sourceRow;
3117 *target += *source * scalar;
3121 *target += *source * scalar;
3125 *target += *source * scalar;
3129 *target += *source * scalar;
3132template <
typename T>
3135 stream <<
"|" << matrix(0, 0) <<
", " << matrix(0, 1) <<
", " << matrix(0, 2) <<
", " << matrix(0, 3) <<
"|" << std::endl;
3136 stream <<
"|" << matrix(1, 0) <<
", " << matrix(1, 1) <<
", " << matrix(1, 2) <<
", " << matrix(1, 3) <<
"|" << std::endl;
3137 stream <<
"|" << matrix(2, 0) <<
", " << matrix(2, 1) <<
", " << matrix(2, 2) <<
", " << matrix(2, 3) <<
"|" << std::endl;
3138 stream <<
"|" << matrix(3, 0) <<
", " << matrix(3, 1) <<
", " << matrix(3, 2) <<
", " << matrix(3, 3) <<
"|";
3143template <
bool tActive,
typename T>
3144MessageObject<tActive>&
operator<<(MessageObject<tActive>& messageObject,
const SquareMatrixT4<T>& matrix)
3146 return messageObject <<
"|" << matrix(0, 0) <<
", " << matrix(0, 1) <<
", " << matrix(0, 2) <<
", " << matrix(0, 3) <<
"|\n|"
3147 << matrix(1, 0) <<
", " << matrix(1, 1) <<
", " << matrix(1, 2) <<
", " << matrix(1, 3) <<
"|\n|"
3148 << matrix(2, 0) <<
", " << matrix(2, 1) <<
", " << matrix(2, 2) <<
", " << matrix(2, 3) <<
"|\n|"
3149 << matrix(3, 0) <<
", " << matrix(3, 1) <<
", " << matrix(3, 2) <<
", " << matrix(3, 3) <<
"|";
3152template <
bool tActive,
typename T>
3153MessageObject<tActive>&
operator<<(MessageObject<tActive>&& messageObject,
const SquareMatrixT4<T>& matrix)
3155 return messageObject <<
"|" << matrix(0, 0) <<
", " << matrix(0, 1) <<
", " << matrix(0, 2) <<
", " << matrix(0, 3) <<
"|\n|"
3156 << matrix(1, 0) <<
", " << matrix(1, 1) <<
", " << matrix(1, 2) <<
", " << matrix(1, 3) <<
"|\n|"
3157 << matrix(2, 0) <<
", " << matrix(2, 1) <<
", " << matrix(2, 2) <<
", " << matrix(2, 3) <<
"|\n|"
3158 << matrix(3, 0) <<
", " << matrix(3, 1) <<
", " << matrix(3, 2) <<
", " << matrix(3, 3) <<
"|";
This class implements the abstract base class for all AnyCamera objects.
Definition AnyCamera.h:131
virtual unsigned int width() const =0
Returns the width of the camera image.
virtual T focalLengthX() const =0
Returns the horizontal focal length parameter.
virtual T focalLengthY() const =0
Returns the vertical focal length parameter.
virtual unsigned int height() const =0
Returns the height of the camera image.
virtual T principalPointY() const =0
Returns the y-value of the principal point of the camera image in the pixel domain.
virtual bool isValid() const =0
Returns whether this camera is valid.
virtual T principalPointX() const =0
Returns the x-value of the principal point of the camera image in the pixel domain.
static unsigned int solveQuartic(const T a, const T b, const T c, const T d, const T e, T *x, const bool refine=true)
Solves a quartic equation with the form:
Definition Equation.h:316
This class implements a 4x4 homogeneous transformation matrix using floating point values with the pr...
Definition HomogenousMatrix4.h:110
HomogenousMatrixT4< T > inverted() const noexcept
Returns the inverted of this matrix.
Definition HomogenousMatrix4.h:1569
VectorT3< T > translation() const
Returns the translation of the transformation.
Definition HomogenousMatrix4.h:1375
bool isValid() const
Returns whether this matrix is a valid homogeneous transformation.
Definition HomogenousMatrix4.h:1800
This class provides basic numeric functionalities.
Definition Numeric.h:57
static constexpr T weakEps()
Returns a weak epsilon.
static T atan(const T value)
Returns the arctangent of a given value.
Definition Numeric.h:1620
static T abs(const T value)
Returns the absolute value of a given value.
Definition Numeric.h:1220
static constexpr T eps()
Returns a small epsilon.
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition Numeric.h:2395
static T tan(const T value)
Returns the tangent of a given value.
Definition Numeric.h:1604
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2096
static constexpr T maxValue()
Returns the max scalar value.
Definition Numeric.h:3253
This class implements a 3x3 square matrix.
Definition SquareMatrix3.h:89
OCEAN_FORCE_INLINE SquareMatrixT4< T > & operator*=(const SquareMatrixT4< T > &matrix)
Multiplies and assigns two matrices.
Definition SquareMatrix4.h:1339
void copyElements(U *arrayValues) const
Copies the elements of this matrix to an array with floating point values of type U.
Definition SquareMatrix4.h:1314
SquareMatrixT4< T > & operator-=(const SquareMatrixT4< T > &matrix)
Subtracts and assigns two matrices.
Definition SquareMatrix4.h:1463
const T * data() const
Returns a pointer to the internal values.
Definition SquareMatrix4.h:750
T operator()(const unsigned int index) const
Element operator.
Definition SquareMatrix4.h:1381
SquareMatrixT4(const U *arrayValues, const bool valuesRowAligned)
Creates a new SquareMatrixT4 object by an array of at least sixteen elements of float type U.
Definition SquareMatrix4.h:644
static SquareMatrixT4< T > projectionMatrix(const T fovX, const T aspectRatio, const T nearDistance, const T farDistance)
Creates a projection matrix defined by the horizontal field of view, the aspect ratio and the near an...
Definition SquareMatrix4.h:2491
OCEAN_FORCE_INLINE VectorT3< T > operator*(const VectorT3< T > &vector) const
Multiply operator for a 3D vector.
Definition SquareMatrix4.h:1877
bool isIdentity() const
Returns whether this matrix is the identity matrix.
Definition SquareMatrix4.h:970
SquareMatrixT4(const U *arrayValues)
Creates a new SquareMatrixT4 object by an array of at least sixteen elements of float type U.
Definition SquareMatrix4.h:625
SquareMatrixT4(const SquareMatrixT4< U > &matrix)
Copy constructor for a matrix with difference element data type than T.
Definition SquareMatrix4.h:602
void transpose()
Transposes the matrix.
Definition SquareMatrix4.h:788
static SquareMatrixT4< T > projectionMatrix(const AnyCameraT< T > &anyCamera, const T nearDistance, const T farDistance)
Creates a projection matrix defined by a camera profile of a pinhole camera and the near and far clip...
Definition SquareMatrix4.h:2536
SquareMatrixT4< T > transposed() const
Returns the transposed of this matrix.
Definition SquareMatrix4.h:762
void swapRows(const unsigned int row0, const unsigned int row1)
Swaps two rows of this matrix.
Definition SquareMatrix4.h:3057
void copyElements(T *arrayValues) const
Copies the elements of this matrix to an array with floating point values.
Definition SquareMatrix4.h:1325
SquareMatrixT4< T > inverted() const
Returns the inverted matrix of this matrix.
Definition SquareMatrix4.h:812
bool invert(SquareMatrixT4< T > &invertedMatrix) const
Inverts the matrix and returns the result.
Definition SquareMatrix4.h:841
SquareMatrixT4< T > operator+(const SquareMatrixT4< T > &matrix) const
Adds two matrices.
Definition SquareMatrix4.h:1432
T operator[](const unsigned int index) const
Element operator.
Definition SquareMatrix4.h:1353
bool isSingular() const
Returns whether this matrix is singular (and thus cannot be inverted).
Definition SquareMatrix4.h:988
SquareMatrixT4()
Creates a new SquareMatrixT4 object with undefined elements.
Definition SquareMatrix4.h:595
SquareMatrixT4(const VectorT4< T > &diagonal)
Creates a new SquareMatrixT4 object by a given diagonal vector.
Definition SquareMatrix4.h:729
OCEAN_FORCE_INLINE SquareMatrixT4< T > operator*(const HomogenousMatrixT4< T > &matrix) const
Multiplies two matrices.
Definition SquareMatrix4.h:1849
friend class SquareMatrixT4
Definition SquareMatrix4.h:86
bool isSymmetric(const T epsilon=NumericT< T >::eps()) const
Returns whether this matrix is symmetric.
Definition SquareMatrix4.h:994
T values[16]
The sixteen values of the matrix.
Definition SquareMatrix4.h:591
T determinant() const
Returns the determinant of the matrix.
Definition SquareMatrix4.h:906
T * data()
Returns a pointer to the internal values.
Definition SquareMatrix4.h:756
T operator()(const unsigned int row, const unsigned int column) const
Element operator.
Definition SquareMatrix4.h:1367
bool isEqual(const SquareMatrixT4< T > &matrix, const T eps=NumericT< T >::eps()) const
Returns whether two matrices are almost identical up to a specified epsilon.
Definition SquareMatrix4.h:1003
void toNull()
Sets the matrix to a zero matrix.
Definition SquareMatrix4.h:961
bool operator==(const SquareMatrixT4< T > &matrix) const
Returns whether two matrices are identical up to a small epsilon.
Definition SquareMatrix4.h:1426
static size_t elements()
Returns the number of elements this matrix has.
Definition SquareMatrix4.h:1420
SquareMatrixT4< T > & operator+=(const SquareMatrixT4< T > &matrix)
Adds and assigns two matrices.
Definition SquareMatrix4.h:1442
const T * operator()() const
Access operator.
Definition SquareMatrix4.h:1395
SquareMatrixT4< T > & operator=(const SquareMatrixT4< T > &)=default
Default assign operator.
SquareMatrixT4(const T *arrayValues, const bool valuesRowAligned)
Creates a new SquareMatrixT4 object by an array of at least sixteen elements.
Definition SquareMatrix4.h:677
static void multiply(const SquareMatrixT4< T > &matrix, const VectorT4< T > *vectors, VectorT4< T > *results, const size_t number)
Multiplies several 4D vectors with a given matrix.
Definition SquareMatrix4.h:2661
SquareMatrixT4< T > operator-() const
Returns the negative matrix of this matrix (all matrix elements are multiplied by -1).
Definition SquareMatrix4.h:1474
bool isNull() const
Returns whether this matrix is a null matrix.
Definition SquareMatrix4.h:979
OCEAN_FORCE_INLINE SquareMatrixT4< T > & operator*=(const HomogenousMatrixT4< T > &matrix)
Multiplies and assigns two matrices.
Definition SquareMatrix4.h:1346
T Type
Definition of the used data type.
Definition SquareMatrix4.h:93
SquareMatrixT4(const SquareMatrixT3< T > &subMatrix)
Creates a new SquareMatrixT4 object by given 3x3 sub matrix.
Definition SquareMatrix4.h:713
SquareMatrixT4< T > operator-(const SquareMatrixT4< T > &matrix) const
Subtracts two matrices.
Definition SquareMatrix4.h:1453
void addRows(const unsigned int targetRow, const unsigned int sourceRow, const T scalar)
Multiplies elements from a specific row with a scalar and adds them to another row.
Definition SquareMatrix4.h:3109
static std::vector< SquareMatrixT4< T > > matrices2matrices(const std::vector< SquareMatrixT4< U > > &matrices)
Converts matrices with specific data type to matrices with different data type.
Definition SquareMatrix4.h:3014
static SquareMatrixT4< T > frustumMatrix(const T left, const T right, const T top, const T bottom, const T nearDistance, const T farDistance)
Creates a projection matrix defined by an asymmetric viewing frustum.
Definition SquareMatrix4.h:2593
T & operator()(const unsigned int index)
Element operator.
Definition SquareMatrix4.h:1388
SquareMatrixT4< T > operator*(const T value) const
Multiplies this matrix with a scalar value.
Definition SquareMatrix4.h:2443
bool invert()
Inverts this matrix in place.
Definition SquareMatrix4.h:826
bool operator!=(const SquareMatrixT4< T > &matrix) const
Returns whether two matrices are not identical up to a small epsilon.
Definition SquareMatrix4.h:1333
size_t operator()(const SquareMatrixT4< T > &matrix) const
Hash function.
Definition SquareMatrix4.h:1407
static std::vector< SquareMatrixT4< T > > matrices2matrices(const SquareMatrixT4< U > *matrices, const size_t size)
Converts matrices with specific data type to matrices with different data type.
Definition SquareMatrix4.h:3043
OCEAN_FORCE_INLINE SquareMatrixT4< T > operator*(const SquareMatrixT4< T > &matrix) const
Multiplies two matrices.
Definition SquareMatrix4.h:1487
T & operator()(const unsigned int row, const unsigned int column)
Element operator.
Definition SquareMatrix4.h:1374
T & operator[](const unsigned int index)
Element operator.
Definition SquareMatrix4.h:1360
bool eigenSystem(T *eigenValues, VectorT4< T > *eigenVectors) const
Performs an eigen value analysis.
Definition SquareMatrix4.h:1016
void multiplyRow(const unsigned int row, const T scalar)
Multiplies a row with a scalar value.
Definition SquareMatrix4.h:3093
T trace() const
Returns the trace of the matrix which is the sum of the diagonal elements.
Definition SquareMatrix4.h:934
SquareMatrixT4(const bool setToIdentity)
Creates a new SquareMatrixT4 object.
Definition SquareMatrix4.h:611
SquareMatrixT4(const HomogenousMatrixT4< T > &transformation)
Creates a new SquareMatrixT4 object by given transformation matrix.
Definition SquareMatrix4.h:707
OCEAN_FORCE_INLINE VectorT4< T > operator*(const VectorT4< T > &vector) const
Multiply operator for a 4D vector.
Definition SquareMatrix4.h:1890
T * operator()()
Access operator.
Definition SquareMatrix4.h:1401
static SquareMatrixT4< T > frustumMatrix(const T width, const T height, const HomogenousMatrixT4< T > &viewingMatrix, const T nearDistance, const T farDistance)
Creates a project matrix defined by an asymmetric viewing frustum.
Definition SquareMatrix4.h:2639
SquareMatrixT4< T > & operator*=(const T value)
Multiplies and assigns this matrix with a scalar value.
Definition SquareMatrix4.h:2468
void toIdentity()
Sets the matrix to the identity matrix.
Definition SquareMatrix4.h:940
SquareMatrixT4(const SquareMatrixT4< T > &matrix)=default
Copy constructor.
SquareMatrixT4(const T *arrayValues)
Creates a new SquareMatrixT4 object by an array of at least sixteen elements.
Definition SquareMatrix4.h:636
static void sortHighestToFront4(T &value0, T &value1, T &value2, T &value3)
Sorts four values so that the highest value will finally be the first value.
Definition base/Utilities.h:758
This class implements a vector with three elements.
Definition Vector3.h:97
const T & y() const noexcept
Returns the y value.
Definition Vector3.h:816
const T & x() const noexcept
Returns the x value.
Definition Vector3.h:804
This class implements a vector with four elements.
Definition Vector4.h:97
const T * data() const noexcept
Returns an pointer to the vector elements.
Definition Vector4.h:723
bool normalize()
Normalizes this vector.
Definition Vector4.h:596
std::vector< SquareMatrix4 > SquareMatrices4
Definition of a vector holding SquareMatrix4 objects.
Definition SquareMatrix4.h:68
std::vector< SquareMatrixT4< T > > SquareMatricesT4
Definition of a typename alias for vectors with SquareMatrixT4 objects.
Definition SquareMatrix4.h:61
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
std::ostream & operator<<(std::ostream &stream, const HighPerformanceStatistic &highPerformanceStatistic)
Definition HighPerformanceTimer.h:963