this subroutine uses householder transformations with column pivoting (optional) to compute a qr factorization of the m by n matrix a. that is, qrfac determines an orthogonal matrix q, a permutation matrix p, and an upper trapezoidal matrix r with diagonal elements of nonincreasing magnitude, such that ap = qr. the householder transformation for column k, k = 1,2,...,min(m,n), is of the form
t
i - (1/u(k))*u*u
where u has zeros in the first k-1 positions. the form of this transformation and the method of pivoting first appeared in the corresponding linpack subroutine.
the subroutine statement is
subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa)
where
m is a positive integer input variable set to the number of rows of a.
n is a positive integer input variable set to the number of columns of a.
a is an m by n array. on input a contains the matrix for which the qr factorization is to be computed. on output the strict upper trapezoidal part of a contains the strict upper trapezoidal part of r, and the lower trapezoidal part of a contains a factored form of q (the non-trivial elements of the u vectors described above).
lda is a positive integer input variable not less than m which specifies the leading dimension of the array a.
pivot is a logical input variable. if pivot is set true, then column pivoting is enforced. if pivot is set false, then no column pivoting is done.
ipvt is an integer output array of length lipvt. ipvt defines the permutation matrix p such that ap = qr. column j of p is column ipvt(j) of the identity matrix. if pivot is false, ipvt is not referenced.
lipvt is a positive integer input variable. if pivot is false, then lipvt may be as small as 1. if pivot is true, then lipvt must be at least n.
rdiag is an output array of length n which contains the diagonal elements of r.
acnorm is an output array of length n which contains the norms of the corresponding columns of the input matrix a. if this information is not needed, then acnorm can coincide with rdiag.
wa is a work array of length n. if pivot is false, then wa can coincide with rdiag.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer | :: | m | ||||
integer | :: | n | ||||
real(kind=wp) | :: | a(lda,n) | ||||
integer | :: | lda | ||||
logical | :: | pivot | ||||
integer | :: | ipvt(lipvt) | ||||
integer | :: | lipvt | ||||
real(kind=wp) | :: | rdiag(n) | ||||
real(kind=wp) | :: | acnorm(n) | ||||
real(kind=wp) | :: | wa(n) |
subroutine qrfac(m,n,a,lda,pivot,ipvt,lipvt,rdiag,acnorm,wa) implicit none integer m , n , lda , lipvt integer ipvt(lipvt) logical pivot real(wp) a(lda,n) , rdiag(n) , acnorm(n) , wa(n) integer i , j , jp1 , k , kmax , minmn real(wp) ajnorm , epsmch , sum , temp real(wp),parameter :: p05 = 5.0e-2_wp epsmch = dpmpar(1) ! the machine precision ! ! compute the initial column norms and initialize several arrays. ! do j = 1 , n acnorm(j) = enorm(m,a(1,j)) rdiag(j) = acnorm(j) wa(j) = rdiag(j) if ( pivot ) ipvt(j) = j enddo ! ! reduce a to r with householder transformations. ! minmn = min(m,n) do j = 1 , minmn if ( pivot ) then ! ! bring the column of largest norm into the pivot position. ! kmax = j do k = j , n if ( rdiag(k)>rdiag(kmax) ) kmax = k enddo if ( kmax/=j ) then do i = 1 , m temp = a(i,j) a(i,j) = a(i,kmax) a(i,kmax) = temp enddo rdiag(kmax) = rdiag(j) wa(kmax) = wa(j) k = ipvt(j) ipvt(j) = ipvt(kmax) ipvt(kmax) = k endif endif ! ! compute the householder transformation to reduce the ! j-th column of a to a multiple of the j-th unit vector. ! ajnorm = enorm(m-j+1,a(j,j)) if ( ajnorm/=zero ) then if ( a(j,j)<zero ) ajnorm = -ajnorm do i = j , m a(i,j) = a(i,j)/ajnorm enddo a(j,j) = a(j,j) + one ! ! apply the transformation to the remaining columns ! and update the norms. ! jp1 = j + 1 if ( n>=jp1 ) then do k = jp1 , n sum = zero do i = j , m sum = sum + a(i,j)*a(i,k) enddo temp = sum/a(j,j) do i = j , m a(i,k) = a(i,k) - temp*a(i,j) enddo if ( .not.(.not.pivot .or. rdiag(k)==zero) ) then temp = a(j,k)/rdiag(k) rdiag(k) = rdiag(k)*sqrt(max(zero,one-temp**2)) if ( p05*(rdiag(k)/wa(k))**2<=epsmch ) then rdiag(k) = enorm(m-j,a(jp1,k)) wa(k) = rdiag(k) endif endif enddo endif endif rdiag(j) = -ajnorm enddo end subroutine qrfac