diff options
Diffstat (limited to 'math/llsq/original_f/svdrs.f')
-rw-r--r-- | math/llsq/original_f/svdrs.f | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/math/llsq/original_f/svdrs.f b/math/llsq/original_f/svdrs.f new file mode 100644 index 00000000..66e488dc --- /dev/null +++ b/math/llsq/original_f/svdrs.f @@ -0,0 +1,205 @@ +c subroutine svdrs (a,mda,mm,nn,b,mdb,nb,s) +c c.l.lawson and r.j.hanson, jet propulsion laboratory, 1974 mar 1 +c to appear in 'solving least squares problems', prentice-hall, 1974 +c singular value decomposition also treating right side vector. +c +c the array s occupies 3*n cells. +c a occupies m*n cells +c b occupies m*nb cells. +c +c special singular value decomposition subroutine. +c we have the m x n matrix a and the system a*x=b to solve. +c either m .ge. n or m .lt. n is permitted. +c the singular value decomposition +c a = u*s*v**(t) is made in such a way that one gets +c (1) the matrix v in the first n rows and columns of a. +c (2) the diagonal matrix of ordered singular values in +c the first n cells of the array s(ip), ip .ge. 3*n. +c (3) the matrix product u**(t)*b=g gets placed back in b. +c (4) the user must complete the solution and do his own +c singular value analysis. +c ******* +c give special +c treatment to rows and columns which are entirely zero. this +c causes certain zero sing. vals. to appear as exact zeros rather +c than as about eta times the largest sing. val. it similarly +c cleans up the associated columns of u and v. +c method.. +c 1. exchange cols of a to pack nonzero cols to the left. +c set n = no. of nonzero cols. +c use locations a(1,nn),a(1,nn-1),...,a(1,n+1) to record the +c col permutations. +c 2. exchange rows of a to pack nonzero rows to the top. +c quit packing if find n nonzero rows. make same row exchanges +c in b. set m so that all nonzero rows of the permuted a +c are in first m rows. if m .le. n then all m rows are +c nonzero. if m .gt. n then the first n rows are known +c to be nonzero,and rows n+1 thru m may be zero or nonzero. +c 3. apply original algorithm to the m by n problem. +c 4. move permutation record from a(,) to s(i),i=n+1,...,nn. +c 5. build v up from n by n to nn by nn by placing ones on +c the diagonal and zeros elsewhere. this is only partly done +c explicitly. it is completed during step 6. +c 6. exchange rows of v to compensate for col exchanges of step 2. +c 7. place zeros in s(i),i=n+1,nn to represent zero sing vals. +c + subroutine svdrs (a,mda,mm,nn,b,mdb,nb,s) + dimension a(mda,nn),b(mdb,nb),s(nn,3) + zero=0. + one=1. +c +c begin.. special for zero rows and cols. +c +c pack the nonzero cols to the left +c + n=nn + if (n.le.0.or.mm.le.0) return + j=n + 10 continue + do 20 i=1,mm + if (a(i,j)) 50,20,50 + 20 continue +c +c col j is zero. exchange it with col n. +c + if (j.eq.n) go to 40 + do 30 i=1,mm + 30 a(i,j)=a(i,n) + 40 continue + a(1,n)=j + n=n-1 + 50 continue + j=j-1 + if (j.ge.1) go to 10 +c if n=0 then a is entirely zero and svd +c computation can be skipped + ns=0 + if (n.eq.0) go to 240 +c pack nonzero rows to the top +c quit packing if find n nonzero rows + i=1 + m=mm + 60 if (i.gt.n.or.i.ge.m) go to 150 + if (a(i,i)) 90,70,90 + 70 do 80 j=1,n + if (a(i,j)) 90,80,90 + 80 continue + go to 100 + 90 i=i+1 + go to 60 +c row i is zero +c exchange rows i and m + 100 if(nb.le.0) go to 115 + do 110 j=1,nb + t=b(i,j) + b(i,j)=b(m,j) + 110 b(m,j)=t + 115 do 120 j=1,n + 120 a(i,j)=a(m,j) + if (m.gt.n) go to 140 + do 130 j=1,n + 130 a(m,j)=zero + 140 continue +c exchange is finished + m=m-1 + go to 60 +c + 150 continue +c end.. special for zero rows and columns +c begin.. svd algorithm +c method.. +c (1) reduce the matrix to upper bidiagonal form with +c householder transformations. +c h(n)...h(1)aq(1)...q(n-2) = (d**t,0)**t +c where d is upper bidiagonal. +c +c (2) apply h(n)...h(1) to b. here h(n)...h(1)*b replaces b +c in storage. +c +c (3) the matrix product w= q(1)...q(n-2) overwrites the first +c n rows of a in storage. +c +c (4) an svd for d is computed. here k rotations ri and pi are +c computed so that +c rk...r1*d*p1**(t)...pk**(t) = diag(s1,...,sm) +c to working accuracy. the si are nonnegative and nonincreasing. +c here rk...r1*b overwrites b in storage while +c a*p1**(t)...pk**(t) overwrites a in storage. +c +c (5) it follows that,with the proper definitions, +c u**(t)*b overwrites b, while v overwrites the first n row and +c columns of a. +c + l=min0(m,n) +c the following loop reduces a to upper bidiagonal and +c also applies the premultiplying transformations to b. +c + do 170 j=1,l + if (j.ge.m) go to 160 + call h12 (1,j,j+1,m,a(1,j),1,t,a(1,j+1),1,mda,n-j) + call h12 (2,j,j+1,m,a(1,j),1,t,b,1,mdb,nb) + 160 if (j.ge.n-1) go to 170 + call h12 (1,j+1,j+2,n,a(j,1),mda,s(j,3),a(j+1,1),mda,1,m-j) + 170 continue +c +c copy the bidiagonal matrix into the array s() for qrbd. +c + if (n.eq.1) go to 190 + do 180 j=2,n + s(j,1)=a(j,j) + 180 s(j,2)=a(j-1,j) + 190 s(1,1)=a(1,1) +c + ns=n + if (m.ge.n) go to 200 + ns=m+1 + s(ns,1)=zero + s(ns,2)=a(m,m+1) + 200 continue +c +c construct the explicit n by n product matrix, w=q1*q2*...*ql*i +c in the array a(). +c + do 230 k=1,n + i=n+1-k + if(i.gt.min0(m,n-2)) go to 210 + call h12 (2,i+1,i+2,n,a(i,1),mda,s(i,3),a(1,i+1),1,mda,n-i) + 210 do 220 j=1,n + 220 a(i,j)=zero + 230 a(i,i)=one +c +c compute the svd of the bidiagonal matrix +c + call qrbd (ipass,s(1,1),s(1,2),ns,a,mda,n,b,mdb,nb) +c + go to (240,310), ipass + 240 continue + if (ns.ge.n) go to 260 + nsp1=ns+1 + do 250 j=nsp1,n + 250 s(j,1)=zero + 260 continue + if (n.eq.nn) return + np1=n+1 +c move record of permutations +c and store zeros + do 280 j=np1,nn + s(j,1)=a(1,j) + do 270 i=1,n + 270 a(i,j)=zero + 280 continue +c permute rows and set zero singular values. + do 300 k=np1,nn + i=s(k,1) + s(k,1)=zero + do 290 j=1,nn + a(k,j)=a(i,j) + 290 a(i,j)=zero + a(i,k)=one + 300 continue +c end.. special for zero rows and columns + return + 310 write (6,320) + stop + 320 format (49h convergence failure in qr bidiagonal svd routine) + end |