123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551 |
- #pragma once
- #include <Mathematics/Matrix.h>
- #include <Mathematics/GMatrix.h>
- namespace WwiseGTE
- {
-
- template <typename Real, int N = 0>
- class CholeskyDecomposition
- {
- public:
-
- CholeskyDecomposition()
- {
- static_assert(N > 0, "Invalid size in CholeskyDecomposition constructor.");
- }
-
- CholeskyDecomposition(CholeskyDecomposition const&) = delete;
- CholeskyDecomposition& operator=(CholeskyDecomposition const&) = delete;
- CholeskyDecomposition(CholeskyDecomposition&&) = delete;
- CholeskyDecomposition& operator=(CholeskyDecomposition&&) = delete;
-
-
-
- bool Factor(Matrix<N, N, Real>& A)
- {
- for (int c = 0; c < N; ++c)
- {
- if (A(c, c) <= (Real)0)
- {
- return false;
- }
- A(c, c) = std::sqrt(A(c, c));
- for (int r = c + 1; r < N; ++r)
- {
- A(r, c) /= A(c, c);
- }
- for (int k = c + 1; k < N; ++k)
- {
- for (int r = k; r < N; ++r)
- {
- A(r, k) -= A(r, c) * A(k, c);
- }
- }
- }
- return true;
- }
-
-
- void SolveLower(Matrix<N, N, Real> const& L, Vector<N, Real>& Y)
- {
- for (int r = 0; r < N; ++r)
- {
- for (int c = 0; c < r; ++c)
- {
- Y[r] -= L(r, c) * Y[c];
- }
- Y[r] /= L(r, r);
- }
- }
-
-
-
- void SolveUpper(Matrix<N, N, Real> const& L, Vector<N, Real>& X)
- {
- for (int r = N - 1; r >= 0; --r)
- {
- for (int c = r + 1; c < N; ++c)
- {
- X[r] -= L(c, r) * X[c];
- }
- X[r] /= L(r, r);
- }
- }
- };
-
- template <typename Real>
- class CholeskyDecomposition<Real, 0>
- {
- public:
- int const N;
-
- CholeskyDecomposition(int n)
- :
- N(n)
- {
- }
-
-
- CholeskyDecomposition(CholeskyDecomposition const&) = delete;
- CholeskyDecomposition& operator=(CholeskyDecomposition const&) = delete;
- CholeskyDecomposition(CholeskyDecomposition&&) = delete;
- CholeskyDecomposition& operator=(CholeskyDecomposition&&) = delete;
-
-
-
- bool Factor(GMatrix<Real>& A)
- {
- if (A.GetNumRows() == N && A.GetNumCols() == N)
- {
- for (int c = 0; c < N; ++c)
- {
- if (A(c, c) <= (Real)0)
- {
- return false;
- }
- A(c, c) = std::sqrt(A(c, c));
- for (int r = c + 1; r < N; ++r)
- {
- A(r, c) /= A(c, c);
- }
- for (int k = c + 1; k < N; ++k)
- {
- for (int r = k; r < N; ++r)
- {
- A(r, k) -= A(r, c) * A(k, c);
- }
- }
- }
- return true;
- }
- LogError("Matrix must be square.");
- }
-
-
- void SolveLower(GMatrix<Real> const& L, GVector<Real>& Y)
- {
- if (L.GetNumRows() == N && L.GetNumCols() == N && Y.GetSize() == N)
- {
- for (int r = 0; r < N; ++r)
- {
- for (int c = 0; c < r; ++c)
- {
- Y[r] -= L(r, c) * Y[c];
- }
- Y[r] /= L(r, r);
- }
- return;
- }
- LogError("Invalid size.");
- }
-
-
-
- void SolveUpper(GMatrix<Real> const& L, GVector<Real>& X)
- {
- if (L.GetNumRows() == N && L.GetNumCols() == N && X.GetSize() == N)
- {
- for (int r = N - 1; r >= 0; --r)
- {
- for (int c = r + 1; c < N; ++c)
- {
- X[r] -= L(c, r) * X[c];
- }
- X[r] /= L(r, r);
- }
- }
- else
- {
- LogError("Invalid size.");
- }
- }
- };
-
- template <typename Real, int BlockSize = 0, int NumBlocks = 0>
- class BlockCholeskyDecomposition
- {
- public:
-
-
-
-
- enum
- {
- NumDimensions = NumBlocks * BlockSize
- };
- typedef std::array<Vector<BlockSize, Real>, NumBlocks> BlockVector;
- typedef std::array<std::array<Matrix<BlockSize, BlockSize, Real>, NumBlocks>, NumBlocks> BlockMatrix;
-
- BlockCholeskyDecomposition()
- {
- static_assert(BlockSize > 0 && NumBlocks > 0, "Invalid size in BlockCholeskyDecomposition constructor.");
- }
-
- BlockCholeskyDecomposition(BlockCholeskyDecomposition const&) = delete;
- BlockCholeskyDecomposition& operator=(BlockCholeskyDecomposition const&) = delete;
- BlockCholeskyDecomposition(BlockCholeskyDecomposition&&) = delete;
- BlockCholeskyDecomposition& operator=(BlockCholeskyDecomposition&&) = delete;
-
-
-
- Real Get(BlockMatrix const& M, int row, int col)
- {
- int b0 = col / BlockSize, b1 = row / BlockSize;
- int i0 = col % BlockSize, i1 = row % BlockSize;
- auto const& block = M[b1][b0];
- return block(i1, i0);
- }
- void Set(BlockMatrix& M, int row, int col, Real value)
- {
- int b0 = col / BlockSize, b1 = row / BlockSize;
- int i0 = col % BlockSize, i1 = row % BlockSize;
- auto& block = M[b1][b0];
- block(i1, i0) = value;
- }
- bool Factor(BlockMatrix& A)
- {
- for (int c = 0; c < NumBlocks; ++c)
- {
- if (!mDecomposer.Factor(A[c][c]))
- {
- return false;
- }
- for (int r = c + 1; r < NumBlocks; ++r)
- {
- LowerTriangularSolver(r, c, A);
- }
- for (int k = c + 1; k < NumBlocks; ++k)
- {
- for (int r = k; r < NumBlocks; ++r)
- {
- SubtractiveUpdate(r, k, c, A);
- }
- }
- }
- return true;
- }
-
-
-
-
- void SolveLower(BlockMatrix const& L, BlockVector& Y)
- {
- for (int r = 0; r < NumBlocks; ++r)
- {
- auto& Yr = Y[r];
- for (int c = 0; c < r; ++c)
- {
- auto const& Lrc = L[r][c];
- auto const& Yc = Y[c];
- for (int i = 0; i < BlockSize; ++i)
- {
- for (int j = 0; j < BlockSize; ++j)
- {
- Yr[i] -= Lrc(i, j) * Yc[j];
- }
- }
- }
- mDecomposer.SolveLower(L[r][r], Yr);
- }
- }
-
-
-
-
- void SolveUpper(BlockMatrix const& L, BlockVector& X)
- {
- for (int r = NumBlocks - 1; r >= 0; --r)
- {
- auto& Xr = X[r];
- for (int c = r + 1; c < NumBlocks; ++c)
- {
- auto const& Lcr = L[c][r];
- auto const& Xc = X[c];
- for (int i = 0; i < BlockSize; ++i)
- {
- for (int j = 0; j < BlockSize; ++j)
- {
- Xr[i] -= Lcr(j, i) * Xc[j];
- }
- }
- }
- mDecomposer.SolveUpper(L[r][r], Xr);
- }
- }
- private:
-
-
-
-
- void LowerTriangularSolver(int r, int c, BlockMatrix& A)
- {
- auto const& Acc = A[c][c];
- auto& Arc = A[r][c];
- for (int j = 0; j < BlockSize; ++j)
- {
- for (int i = 0; i < j; ++i)
- {
- Real Lji = Acc(j, i);
- for (int k = 0; k < BlockSize; ++k)
- {
- Arc(k, j) -= Lji * Arc(k, i);
- }
- }
- Real Ljj = Acc(j, j);
- for (int k = 0; k < BlockSize; ++k)
- {
- Arc(k, j) /= Ljj;
- }
- }
- }
- void SubtractiveUpdate(int r, int k, int c, BlockMatrix& A)
- {
- auto const& Arc = A[r][c];
- auto const& Akc = A[k][c];
- auto& Ark = A[r][k];
- for (int j = 0; j < BlockSize; ++j)
- {
- for (int i = 0; i < BlockSize; ++i)
- {
- for (int m = 0; m < BlockSize; ++m)
- {
- Ark(j, i) -= Arc(j, m) * Akc(i, m);
- }
- }
- }
- }
- CholeskyDecomposition<Real, BlockSize> mDecomposer;
- };
-
- template <typename Real>
- class BlockCholeskyDecomposition<Real, 0, 0>
- {
- public:
-
-
-
-
- int const BlockSize;
- int const NumBlocks;
- int const NumDimensions;
-
-
- typedef std::vector<GVector<Real>> BlockVector;
-
-
-
-
-
-
- typedef std::vector<GMatrix<Real>> BlockMatrix;
-
- BlockCholeskyDecomposition(int blockSize, int numBlocks)
- :
- BlockSize(blockSize),
- NumBlocks(numBlocks),
- NumDimensions(numBlocks * blockSize),
- mDecomposer(blockSize)
- {
- LogAssert(blockSize > 0 && numBlocks > 0, "Invalid input.");
- }
-
-
- BlockCholeskyDecomposition(BlockCholeskyDecomposition const&) = delete;
- BlockCholeskyDecomposition& operator=(BlockCholeskyDecomposition const&) = delete;
- BlockCholeskyDecomposition(BlockCholeskyDecomposition&&) = delete;
- BlockCholeskyDecomposition& operator=(BlockCholeskyDecomposition&&) = delete;
-
-
-
- Real Get(BlockMatrix const& M, int row, int col)
- {
- int b0 = col / BlockSize, b1 = row / BlockSize;
- int i0 = col % BlockSize, i1 = row % BlockSize;
- auto const& block = M[GetIndex(b1, b0)];
- return block(i1, i0);
- }
- void Set(BlockMatrix& M, int row, int col, Real value)
- {
- int b0 = col / BlockSize, b1 = row / BlockSize;
- int i0 = col % BlockSize, i1 = row % BlockSize;
- auto& block = M[GetIndex(b1, b0)];
- block(i1, i0) = value;
- }
- bool Factor(BlockMatrix& A)
- {
- for (int c = 0; c < NumBlocks; ++c)
- {
- if (!mDecomposer.Factor(A[GetIndex(c, c)]))
- {
- return false;
- }
- for (int r = c + 1; r < NumBlocks; ++r)
- {
- LowerTriangularSolver(r, c, A);
- }
- for (int k = c + 1; k < NumBlocks; ++k)
- {
- for (int r = k; r < NumBlocks; ++r)
- {
- SubtractiveUpdate(r, k, c, A);
- }
- }
- }
- return true;
- }
-
-
-
-
- void SolveLower(BlockMatrix const& L, BlockVector& Y)
- {
- for (int r = 0; r < NumBlocks; ++r)
- {
- auto& Yr = Y[r];
- for (int c = 0; c < r; ++c)
- {
- auto const& Lrc = L[GetIndex(r, c)];
- auto const& Yc = Y[c];
- for (int i = 0; i < NumBlocks; ++i)
- {
- for (int j = 0; j < NumBlocks; ++j)
- {
- Yr[i] -= Lrc[GetIndex(i, j)] * Yc[j];
- }
- }
- }
- mDecomposer.SolveLower(L[GetIndex(r, r)], Yr);
- }
- }
-
-
-
-
- void SolveUpper(BlockMatrix const& L, BlockVector& X)
- {
- for (int r = NumBlocks - 1; r >= 0; --r)
- {
- auto& Xr = X[r];
- for (int c = r + 1; c < NumBlocks; ++c)
- {
- auto const& Lcr = L[GetIndex(c, r)];
- auto const& Xc = X[c];
- for (int i = 0; i < BlockSize; ++i)
- {
- for (int j = 0; j < BlockSize; ++j)
- {
- Xr[i] -= Lcr[GetIndex(j, i)] * Xc[j];
- }
- }
- }
- mDecomposer.SolveUpper(L[GetIndex(r, r)], Xr);
- }
- }
- private:
-
-
- inline int GetIndex(int row, int col) const
- {
- return col + row * NumBlocks;
- }
-
-
-
-
- void LowerTriangularSolver(int r, int c, BlockMatrix& A)
- {
- auto const& Acc = A[GetIndex(c, c)];
- auto& Arc = A[GetIndex(r, c)];
- for (int j = 0; j < BlockSize; ++j)
- {
- for (int i = 0; i < j; ++i)
- {
- Real Lji = Acc[GetIndex(j, i)];
- for (int k = 0; k < BlockSize; ++k)
- {
- Arc[GetIndex(k, j)] -= Lji * Arc[GetIndex(k, i)];
- }
- }
- Real Ljj = Acc[GetIndex(j, j)];
- for (int k = 0; k < BlockSize; ++k)
- {
- Arc[GetIndex(k, j)] /= Ljj;
- }
- }
- }
- void SubtractiveUpdate(int r, int k, int c, BlockMatrix& A)
- {
- auto const& Arc = A[GetIndex(r, c)];
- auto const& Akc = A[GetIndex(k, c)];
- auto& Ark = A[GetIndex(r, k)];
- for (int j = 0; j < BlockSize; ++j)
- {
- for (int i = 0; i < BlockSize; ++i)
- {
- for (int m = 0; m < BlockSize; ++m)
- {
- Ark[GetIndex(j, i)] -= Arc[GetIndex(j, m)] * Akc[GetIndex(i, m)];
- }
- }
- }
- }
-
- CholeskyDecomposition<Real> mDecomposer;
- };
- }
|