! !$Author$ !$Date$ !$Revision$ !$HeadURL$ ! subroutine sgbfa (abd, lda, n, ml, mu, ipvt, info) !***BEGIN PROLOGUE SGBFA !***PURPOSE Factor a band matrix using Gaussian elimination. !***CATEGORY D2A2 !***TYPE SINGLE PRECISION (SGBFA-S, DGBFA-D, CGBFA-C) !***KEYWORDS BANDED, LINEAR ALGEBRA, LINPACK, MATRIX FACTORIZATION !***AUTHOR Moler, C. B., (U. of New Mexico) !***DESCRIPTION ! ! SGBFA factors a real band matrix by elimination. ! ! SGBFA is usually called by SBGCO, but it can be called ! directly with a saving in time if RCOND is not needed. ! ! On Entry ! ! abd real(lda, n) ! contains the matrix in band storage. the columns ! of the matrix are stored in the columns of abd and ! the diagonals of the matrix are stored in rows ! ml+1 through 2*ml+mu+1 of abd . ! see the comments below for details. ! ! lda integer ! the leading dimension of the array abd . ! lda must be .ge. 2*ml + mu + 1 . ! ! n integer ! the order of the original matrix. ! ! ml integer ! number of diagonals below the main diagonal. ! 0 .le. ml .lt. n . ! ! mu integer ! number of diagonals above the main diagonal. ! 0 .le. mu .lt. n . ! more efficient if ml .le. mu . ! On Return ! ! abd an upper triangular matrix in band storage and ! the multipliers which were used to obtain it. ! the factorization can be written a = l*u , where ! l is a product of permutation and unit lower ! triangular matrices and u is upper triangular. ! ! ipvt integer(n) ! an integer vector of pivot indices. ! ! info integer ! = 0 normal value. ! = k if u(k,k) .eq. 0.0 . this is not an error ! condition for this subroutine, but it does ! indicate that sgbsl will divide by zero if ! called. use rcond in sbgco for a reliable ! indication of singularity. ! ! Band Storage ! ! If A is a band matrix, the following program segment ! will set up the input. ! ! ml = (band width below the diagonal) ! mu = (band width above the diagonal) ! m = ml + mu + 1 ! do 20 j = 1, n ! i1 = max(1, j-mu) ! i2 = min(n, j+ml) ! do 10 i = i1, i2 ! k = i - j + m ! abd(k,j) = a(i,j) ! 10 continue ! 20 continue ! ! This uses rows ML+1 through 2*ML+MU+1 of ABD . ! In addition, the first ML rows in ABD are used for ! elements generated during the triangularization. ! The total number of rows needed in ABD is 2*ML+MU+1 . ! The ML+MU by ML+MU upper left triangle and the ! ML by ML lower right triangle are not referenced. ! !***REFERENCES J. J. Dongarra, J. R. Bunch, C. B. Moler, and G. W. ! Stewart, LINPACK Users' Guide, SIAM, 1979. !***ROUTINES CALLED ISAMAX, SAXPY, SSCAL !***REVISION HISTORY (YYMMDD) ! 780814 DATE WRITTEN ! 890531 Changed all specific intrinsics to generic. (WRB) ! 890831 Modified array declarations. (WRB) ! 890831 REVISION DATE from Version 3.2 ! 891214 Prologue converted to Version 4.0 format. (BAB) ! 900326 Removed duplicate information from DESCRIPTION section. ! (WRB) ! 920501 Reformatted the REFERENCES section. (WRB) !***END PROLOGUE SGBFA integer lda,n,ml,mu,ipvt(*),info real abd(lda,*) ! real t integer i,isamax,i0,j,ju,jz,j0,j1,k,kp1,l,lm,m,mm,nm1 ! !***first executable statement sgbfa m = ml + mu + 1 info = 0 ! ! zero initial fill-in columns ! j0 = mu + 2 j1 = min(n,m) - 1 if (j1 .lt. j0) go to 30 do 20 jz = j0, j1 i0 = m + 1 - jz do 10 i = i0, ml abd(i,jz) = 0.0e0 10 continue 20 continue 30 continue jz = j1 ju = 0 ! ! gaussian elimination with partial pivoting ! nm1 = n - 1 if (nm1 .lt. 1) go to 130 do 120 k = 1, nm1 kp1 = k + 1 ! ! zero next fill-in column ! jz = jz + 1 if (jz .gt. n) go to 50 if (ml .lt. 1) go to 50 do 40 i = 1, ml abd(i,jz) = 0.0e0 40 continue 50 continue ! ! find l = pivot index ! lm = min(ml,n-k) l = isamax(lm+1,abd(m,k),1) + m - 1 ipvt(k) = l + k - m ! ! zero pivot implies this column already triangularized ! if (abd(l,k) .eq. 0.0e0) go to 100 ! ! interchange if necessary ! if (l .eq. m) go to 60 t = abd(l,k) abd(l,k) = abd(m,k) abd(m,k) = t 60 continue ! ! compute multipliers ! t = -1.0e0/abd(m,k) call sscal(lm,t,abd(m+1,k),1) ! ! row elimination with column indexing ! ju = min(max(ju,mu+ipvt(k)),n) mm = m if (ju .lt. kp1) go to 90 do 80 j = kp1, ju l = l - 1 mm = mm - 1 t = abd(l,j) if (l .eq. mm) go to 70 abd(l,j) = abd(mm,j) abd(mm,j) = t 70 continue call saxpy(lm,t,abd(m+1,k),1,abd(mm+1,j),1) 80 continue 90 continue go to 110 100 continue info = k 110 continue 120 continue 130 continue ipvt(n) = n if (abd(m,n) .eq. 0.0e0) info = n return end