/// <summary> /// Solves a system of linear equations, <b>AX = B</b>, with A Cholesky factorized. /// </summary> /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param> /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param> public override void Solve(Matrix <Complex> input, Matrix <Complex> result) { if (input == null) { throw new ArgumentNullException("input"); } if (result == null) { throw new ArgumentNullException("result"); } // Check for proper dimensions. if (result.RowCount != input.RowCount) { throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension); } if (result.ColumnCount != input.ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension); } if (input.RowCount != CholeskyFactor.RowCount) { throw Matrix.DimensionsDontMatch <ArgumentException>(input, CholeskyFactor); } input.CopyTo(result); var order = CholeskyFactor.RowCount; for (var c = 0; c < result.ColumnCount; c++) { // Solve L*Y = B; Complex sum; for (var i = 0; i < order; i++) { sum = result.At(i, c); for (var k = i - 1; k >= 0; k--) { sum -= CholeskyFactor.At(i, k) * result.At(k, c); } result.At(i, c, sum / CholeskyFactor.At(i, i)); } // Solve L'*X = Y; for (var i = order - 1; i >= 0; i--) { sum = result.At(i, c); for (var k = i + 1; k < order; k++) { sum -= CholeskyFactor.At(k, i).Conjugate() * result.At(k, c); } result.At(i, c, sum / CholeskyFactor.At(i, i)); } } }
/// <summary> /// Solves a system of linear equations, <b>Ax = b</b>, with A Cholesky factorized. /// </summary> /// <param name="input">The right hand side vector, <b>b</b>.</param> /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param> public override void Solve(Vector <Complex> input, Vector <Complex> result) { // Check for proper arguments. if (input == null) { throw new ArgumentNullException("input"); } if (result == null) { throw new ArgumentNullException("result"); } // Check for proper dimensions. if (input.Count != result.Count) { throw new ArgumentException(Resources.ArgumentVectorsSameLength); } if (input.Count != CholeskyFactor.RowCount) { throw Matrix.DimensionsDontMatch <ArgumentException>(input, CholeskyFactor); } input.CopyTo(result); var order = CholeskyFactor.RowCount; // Solve L*Y = B; Complex sum; for (var i = 0; i < order; i++) { sum = result[i]; for (var k = i - 1; k >= 0; k--) { sum -= CholeskyFactor.At(i, k) * result[k]; } result[i] = sum / CholeskyFactor.At(i, i); } // Solve L'*X = Y; for (var i = order - 1; i >= 0; i--) { sum = result[i]; for (var k = i + 1; k < order; k++) { sum -= CholeskyFactor.At(k, i).Conjugate() * result[k]; } result[i] = sum / CholeskyFactor.At(i, i); } }
/// <summary> /// Initializes a new instance of the <see cref="UserCholesky"/> class. This object will compute the /// Cholesky factorization when the constructor is called and cache it's factorization. /// </summary> /// <param name="matrix">The matrix to factor.</param> /// <exception cref="ArgumentNullException">If <paramref name="matrix"/> is <c>null</c>.</exception> /// <exception cref="ArgumentException">If <paramref name="matrix"/> is not a square matrix.</exception> /// <exception cref="ArgumentException">If <paramref name="matrix"/> is not positive definite.</exception> public UserCholesky(Matrix <Complex> matrix) { if (matrix == null) { throw new ArgumentNullException("matrix"); } if (matrix.RowCount != matrix.ColumnCount) { throw new ArgumentException(Resources.ArgumentMatrixSquare); } // Create a new matrix for the Cholesky factor, then perform factorization (while overwriting). CholeskyFactor = matrix.Clone(); var tmpColumn = new Complex[CholeskyFactor.RowCount]; // Main loop - along the diagonal for (var ij = 0; ij < CholeskyFactor.RowCount; ij++) { // "Pivot" element var tmpVal = CholeskyFactor.At(ij, ij); if (tmpVal.Real > 0.0) { tmpVal = tmpVal.SquareRoot(); CholeskyFactor.At(ij, ij, tmpVal); tmpColumn[ij] = tmpVal; // Calculate multipliers and copy to local column // Current column, below the diagonal for (var i = ij + 1; i < CholeskyFactor.RowCount; i++) { CholeskyFactor.At(i, ij, CholeskyFactor.At(i, ij) / tmpVal); tmpColumn[i] = CholeskyFactor.At(i, ij); } // Remaining columns, below the diagonal DoCholeskyStep(CholeskyFactor, CholeskyFactor.RowCount, ij + 1, CholeskyFactor.RowCount, tmpColumn, Control.NumberOfParallelWorkerThreads); } else { throw new ArgumentException(Resources.ArgumentMatrixPositiveDefinite); } for (var i = ij + 1; i < CholeskyFactor.RowCount; i++) { CholeskyFactor.At(ij, i, Complex.Zero); } } }