/************************************************************************* Copyright (c) 1992-2007 The University of Tennessee. All rights reserved. Contributors: * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to pseudocode. See subroutines comments for additional copyrights. >>> SOURCE LICENSE >>> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation (www.fsf.org); either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. A copy of the GNU General Public License is available at http://www.fsf.org/licensing/licenses >>> END OF LICENSE >>> *************************************************************************/ using System; namespace alglib { public class lu { public const int lunb = 8; /************************************************************************* LU decomposition of a general matrix of size MxN The subroutine calculates the LU decomposition of a rectangular general matrix with partial pivoting (with row permutations). Input parameters: A - matrix A whose indexes range within [0..M-1, 0..N-1]. M - number of rows in matrix A. N - number of columns in matrix A. Output parameters: A - matrices L and U in compact form (see below). Array whose indexes range within [0..M-1, 0..N-1]. Pivots - permutation matrix in compact form (see below). Array whose index ranges within [0..Min(M-1,N-1)]. Matrix A is represented as A = P * L * U, where P is a permutation matrix, matrix L - lower triangular (or lower trapezoid, if M>N) matrix, U - upper triangular (or upper trapezoid, if M=1, "RMatrixLU internal error"); nb = lunb; // // Decide what to use - blocked or unblocked code // if( n<=1 | Math.Min(m, n)<=nb | nb==1 ) { // // Unblocked code // rmatrixlu2(ref a, m, n, ref pivots); } else { // // Blocked code. // First, prepare temporary matrix and indices // b = new double[m-1+1, nb-1+1]; t = new double[n-1+1]; pivots = new int[Math.Min(m, n)-1+1]; minmn = Math.Min(m, n); j1 = 0; j2 = Math.Min(minmn, nb)-1; // // Main cycle // while( j1=0 & n>=0, "Error in LUDecomposition: incorrect function arguments"); // // Quick return if possible // if( m==0 | n==0 ) { return; } for(j=1; j<=Math.Min(m, n); j++) { // // Find pivot and test for singularity. // jp = j; for(i=j+1; i<=m; i++) { if( (double)(Math.Abs(a[i,j]))>(double)(Math.Abs(a[jp,j])) ) { jp = i; } } pivots[j] = jp; if( (double)(a[jp,j])!=(double)(0) ) { // //Apply the interchange to rows // if( jp!=j ) { for(i_=1; i_<=n;i_++) { t1[i_] = a[j,i_]; } for(i_=1; i_<=n;i_++) { a[j,i_] = a[jp,i_]; } for(i_=1; i_<=n;i_++) { a[jp,i_] = t1[i_]; } } // //Compute elements J+1:M of J-th column. // if( ji ) { l[i,j] = 0; } if( j==i ) { l[i,j] = 1; } if( j=i ) { u[i,j] = a[i,j]; } } } } /************************************************************************* Level 2 BLAS version of RMatrixLU -- LAPACK routine (version 3.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University June 30, 1992 *************************************************************************/ private static void rmatrixlu2(ref double[,] a, int m, int n, ref int[] pivots) { int i = 0; int j = 0; int jp = 0; double[] t1 = new double[0]; double s = 0; int i_ = 0; pivots = new int[Math.Min(m-1, n-1)+1]; t1 = new double[Math.Max(m-1, n-1)+1]; System.Diagnostics.Debug.Assert(m>=0 & n>=0, "Error in LUDecomposition: incorrect function arguments"); // // Quick return if possible // if( m==0 | n==0 ) { return; } for(j=0; j<=Math.Min(m-1, n-1); j++) { // // Find pivot and test for singularity. // jp = j; for(i=j+1; i<=m-1; i++) { if( (double)(Math.Abs(a[i,j]))>(double)(Math.Abs(a[jp,j])) ) { jp = i; } } pivots[j] = jp; if( (double)(a[jp,j])!=(double)(0) ) { // //Apply the interchange to rows // if( jp!=j ) { for(i_=0; i_<=n-1;i_++) { t1[i_] = a[j,i_]; } for(i_=0; i_<=n-1;i_++) { a[j,i_] = a[jp,i_]; } for(i_=0; i_<=n-1;i_++) { a[jp,i_] = t1[i_]; } } // //Compute elements J+1:M of J-th column. // if( j