diff --git a/CSparse.Tests/Double/Factorization/SparseLUTest.cs b/CSparse.Tests/Double/Factorization/SparseLUTest.cs index 477a1e3..c940af3 100644 --- a/CSparse.Tests/Double/Factorization/SparseLUTest.cs +++ b/CSparse.Tests/Double/Factorization/SparseLUTest.cs @@ -111,6 +111,27 @@ public void TestRefactorize() Assert.Throws(() => lu.Refactorize(small, 1.0)); } + [Test] + public void TestRefactorize2() + { + const int N = 3; + + var A = CompressedColumnStorage.OfRowMajor(N, N, [0.001, -0.001, 1, -0.001, 10.001, 0, 1, 0, 0]); + + double[] b = { 0.0, 0.0049995, 5.0 }; + + double[] x1 = new double[N]; + double[] x2 = new double[N]; + + var lu = SparseLU.Create(A, ColumnOrdering.MinimumDegreeAtPlusA, 1e-8); + + lu.Solve(b, x1); + lu.Refactorize(A, 1e-8); + lu.Solve(b, x2); + + Assert.AreEqual(x1[0], x2[0]); + } + [Test] public void TestRefactorizeNoTrim() { diff --git a/CSparse/Complex/Factorization/SparseLU.cs b/CSparse/Complex/Factorization/SparseLU.cs index 4a7fe00..132cdd4 100644 --- a/CSparse/Complex/Factorization/SparseLU.cs +++ b/CSparse/Complex/Factorization/SparseLU.cs @@ -21,7 +21,8 @@ public class SparseLU : ISparseFactorization CompressedColumnStorage L, U; int[] pinv; // partial pivoting - Complex[] temp; // workspace + readonly Complex[] temp; // workspace (used for factorization and solve) + readonly int[] temp2; // workspace (used for factorization) #region Static methods @@ -99,7 +100,9 @@ public static SparseLU Create(CompressedColumnStorage A, int[] p, doubl private SparseLU(int n) { this.n = n; - this.temp = new Complex[n]; + + temp = new Complex[n]; + temp2 = new int[2 * n]; } /// @@ -137,6 +140,10 @@ public void Refactorize(CompressedColumnStorage A, double tol = 1.0) // Ensure tol is in range. tol = Math.Min(Math.Max(tol, 0.0), 1.0); + // Reset workspace + Array.Clear(temp, 0, n); + Array.Clear(temp2, 0, 2 * n); + // Reuse the cached symbolic ordering (S); recompute L, U and the pivoting. Factorize(A, tol, null); } @@ -224,8 +231,8 @@ private void Factorize(CompressedColumnStorage A, double tol, IProgress } // Workspace - var x = this.temp; - var xi = new int[2 * n]; + var x = temp; + var xi = temp2; for (i = 0; i < n; i++) { diff --git a/CSparse/Double/Factorization/SparseLU.cs b/CSparse/Double/Factorization/SparseLU.cs index 0854bf7..d568d65 100644 --- a/CSparse/Double/Factorization/SparseLU.cs +++ b/CSparse/Double/Factorization/SparseLU.cs @@ -20,8 +20,9 @@ public class SparseLU : ISparseFactorization CompressedColumnStorage L, U; int[] pinv; // partial pivoting - double[] temp; // workspace - + readonly double[] temp; // workspace (used for factorization and solve) + readonly int[] temp2; // workspace (used for factorization) + #region Static methods /// @@ -98,7 +99,9 @@ public static SparseLU Create(CompressedColumnStorage A, int[] p, double private SparseLU(int n) { this.n = n; - this.temp = new double[n]; + + temp = new double[n]; + temp2 = new int[2 * n]; } /// @@ -136,6 +139,10 @@ public void Refactorize(CompressedColumnStorage A, double tol = 1.0) // Ensure tol is in range. tol = Math.Min(Math.Max(tol, 0.0), 1.0); + // Reset workspace + Array.Clear(temp, 0, n); + Array.Clear(temp2, 0, 2 * n); + // Reuse the cached symbolic ordering (S); recompute L, U and the pivoting. Factorize(A, tol, null); } @@ -223,8 +230,8 @@ private void Factorize(CompressedColumnStorage A, double tol, IProgress< } // Workspace - var x = this.temp; - var xi = new int[2 * n]; + var x = temp; + var xi = temp2; for (i = 0; i < n; i++) {