Browse Source

Adjust GaussianEliminationSolver, replace generic type with float

pull/2748/head
Socolin 2 years ago
parent
commit
e244efa77a
  1. 21
      src/ImageSharp/Common/Helpers/GaussianEliminationSolver.cs
  2. 2
      src/ImageSharp/Common/Helpers/QuadDistortionHelper.cs
  3. 2
      tests/ImageSharp.Tests/Common/GaussianEliminationSolverTest.cs

21
src/ImageSharp/Common/Helpers/GaussianEliminationSolver.cs

@ -1,6 +1,5 @@
// Copyright (c) Six Labors. // Copyright (c) Six Labors.
// Licensed under the Six Labors Split License. // Licensed under the Six Labors Split License.
using System.Numerics;
namespace SixLabors.ImageSharp.Common.Helpers; namespace SixLabors.ImageSharp.Common.Helpers;
@ -9,9 +8,7 @@ namespace SixLabors.ImageSharp.Common.Helpers;
/// This class applies Gaussian Elimination to transform the matrix into row echelon form and then performs back substitution to find the solution vector. /// This class applies Gaussian Elimination to transform the matrix into row echelon form and then performs back substitution to find the solution vector.
/// This implementation is based on: https://www.algorithm-archive.org/contents/gaussian_elimination/gaussian_elimination.html /// This implementation is based on: https://www.algorithm-archive.org/contents/gaussian_elimination/gaussian_elimination.html
/// </summary> /// </summary>
/// <typeparam name="TNumber">The type of numbers used in the matrix and solution vector. Must implement the <see cref="INumber{TNumber}"/> interface.</typeparam> internal static class GaussianEliminationSolver
internal static class GaussianEliminationSolver<TNumber>
where TNumber : INumber<TNumber>
{ {
/// <summary> /// <summary>
/// Solves the system of linear equations represented by the given matrix and result vector using Gaussian Elimination. /// Solves the system of linear equations represented by the given matrix and result vector using Gaussian Elimination.
@ -23,24 +20,24 @@ internal static class GaussianEliminationSolver<TNumber>
/// The matrix passed to this method must be a square matrix. /// The matrix passed to this method must be a square matrix.
/// If the matrix is singular (i.e., has no unique solution), an <see cref="NotSupportedException"/> will be thrown. /// If the matrix is singular (i.e., has no unique solution), an <see cref="NotSupportedException"/> will be thrown.
/// </remarks> /// </remarks>
public static void Solve(TNumber[][] matrix, TNumber[] result) public static void Solve(float[][] matrix, float[] result)
{ {
TransformToRowEchelonForm(matrix, result); TransformToRowEchelonForm(matrix, result);
ApplyBackSubstitution(matrix, result); ApplyBackSubstitution(matrix, result);
} }
private static void TransformToRowEchelonForm(TNumber[][] matrix, TNumber[] result) private static void TransformToRowEchelonForm(float[][] matrix, float[] result)
{ {
int colCount = matrix.Length; int colCount = matrix.Length;
int rowCount = matrix[0].Length; int rowCount = matrix[0].Length;
int pivotRow = 0; int pivotRow = 0;
for (int pivotCol = 0; pivotCol < colCount; pivotCol++) for (int pivotCol = 0; pivotCol < colCount; pivotCol++)
{ {
TNumber maxValue = TNumber.Abs(matrix[pivotRow][pivotCol]); float maxValue = float.Abs(matrix[pivotRow][pivotCol]);
int maxIndex = pivotRow; int maxIndex = pivotRow;
for (int r = pivotRow + 1; r < rowCount; r++) for (int r = pivotRow + 1; r < rowCount; r++)
{ {
TNumber value = TNumber.Abs(matrix[r][pivotCol]); float value = float.Abs(matrix[r][pivotCol]);
if (value > maxValue) if (value > maxValue)
{ {
maxIndex = r; maxIndex = r;
@ -48,7 +45,7 @@ internal static class GaussianEliminationSolver<TNumber>
} }
} }
if (matrix[maxIndex][pivotCol] == TNumber.Zero) if (matrix[maxIndex][pivotCol] == 0)
{ {
throw new NotSupportedException("Matrix is singular and cannot be solve"); throw new NotSupportedException("Matrix is singular and cannot be solve");
} }
@ -58,21 +55,21 @@ internal static class GaussianEliminationSolver<TNumber>
for (int r = pivotRow + 1; r < rowCount; r++) for (int r = pivotRow + 1; r < rowCount; r++)
{ {
TNumber fraction = matrix[r][pivotCol] / matrix[pivotRow][pivotCol]; float fraction = matrix[r][pivotCol] / matrix[pivotRow][pivotCol];
for (int c = pivotCol + 1; c < colCount; c++) for (int c = pivotCol + 1; c < colCount; c++)
{ {
matrix[r][c] -= matrix[pivotRow][c] * fraction; matrix[r][c] -= matrix[pivotRow][c] * fraction;
} }
result[r] -= result[pivotRow] * fraction; result[r] -= result[pivotRow] * fraction;
matrix[r][pivotCol] = TNumber.Zero; matrix[r][pivotCol] = 0;
} }
pivotRow++; pivotRow++;
} }
} }
private static void ApplyBackSubstitution(TNumber[][] matrix, TNumber[] result) private static void ApplyBackSubstitution(float[][] matrix, float[] result)
{ {
int rowCount = matrix[0].Length; int rowCount = matrix[0].Length;

2
src/ImageSharp/Common/Helpers/QuadDistortionHelper.cs

@ -60,7 +60,7 @@ internal static class QuadDistortionHelper
q4.Y, q4.Y,
]; ];
GaussianEliminationSolver<float>.Solve(matrixData, b); GaussianEliminationSolver.Solve(matrixData, b);
#pragma warning disable SA1117 #pragma warning disable SA1117
Matrix4x4 projectionMatrix = new( Matrix4x4 projectionMatrix = new(

2
tests/ImageSharp.Tests/Common/GaussianEliminationSolverTest.cs

@ -11,7 +11,7 @@ public class GaussianEliminationSolverTest
[MemberData(nameof(MatrixTestData))] [MemberData(nameof(MatrixTestData))]
public void CanSolve(float[][] matrix, float[] result, float[] expected) public void CanSolve(float[][] matrix, float[] result, float[] expected)
{ {
GaussianEliminationSolver<float>.Solve(matrix, result); GaussianEliminationSolver.Solve(matrix, result);
for (int i = 0; i < expected.Length; i++) for (int i = 0; i < expected.Length; i++)
{ {

Loading…
Cancel
Save