aboutsummaryrefslogtreecommitdiff
path: root/math/llsq/original_f/sva.f
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /math/llsq/original_f/sva.f
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'math/llsq/original_f/sva.f')
-rw-r--r--math/llsq/original_f/sva.f193
1 files changed, 193 insertions, 0 deletions
diff --git a/math/llsq/original_f/sva.f b/math/llsq/original_f/sva.f
new file mode 100644
index 00000000..469a90ef
--- /dev/null
+++ b/math/llsq/original_f/sva.f
@@ -0,0 +1,193 @@
+ subroutine sva (a,mda,m,n,mdata,b,sing,names,iscale,d)
+c c.l.lawson and r.j.hanson, jet propulsion laboratory, 1973 jun 12
+c to appear in 'solving least squares problems', prentice-hall, 1974
+c singular value analysis printout
+c
+c iscale set by user to 1, 2, or 3 to select column scaling
+c option.
+c 1 subr will use identity scaling and ignore the d()
+c array.
+c 2 subr will scale nonzero cols to have unit euclide
+c length and will store reciprocal lengths of
+c original nonzero cols in d().
+c 3 user supplies col scale factors in d(). subr
+c will mult col j by d(j) and remove the scaling
+c from the soln at the end.
+c
+ dimension a(mda,n), b(m), sing(01),d(n)
+c sing(3*n)
+ dimension names(n)
+ logical test
+ double precision sb, dzero
+ dzero=0.d0
+ one=1.
+ zero=0.
+ if (m.le.0 .or. n.le.0) return
+ np1=n+1
+ write (6,270)
+ write (6,260) m,n,mdata
+ go to (60,10,10), iscale
+c
+c apply column scaling to a
+c
+ 10 do 50 j=1,n
+ a1=d(j)
+ go to (20,20,40), iscale
+ 20 sb=dzero
+ do 30 i=1,m
+ 30 sb=sb+dble(a(i,j))**2
+ a1=dsqrt(sb)
+ if (a1.eq.zero) a1=one
+ a1=one/a1
+ d(j)=a1
+ 40 do 50 i=1,m
+ 50 a(i,j)=a(i,j)*a1
+ write (6,280) iscale,(d(j),j=1,n)
+ go to 70
+ 60 continue
+ write (6,290)
+ 70 continue
+c
+c obtain sing. value decomp. of scaled matrix.
+c
+c**********************************************************
+ call svdrs (a,mda,m,n,b,1,1,sing)
+c**********************************************************
+c
+c print the v matrix.
+c
+ call mfeout (a,mda,n,n,names,1)
+ if (iscale.eq.1) go to 90
+c
+c replace v by d*v in the array a()
+c
+ do 80 i=1,n
+ do 80 j=1,n
+ 80 a(i,j)=d(i)*a(i,j)
+c
+c g now in b array. v now in a array.
+c
+c
+c obtain summary output.
+c
+ 90 continue
+ write (6,220)
+c
+c compute cumulative sums of squares of components of
+c g and store them in sing(i), i=minmn+1,...,2*minmn+1
+c
+ sb=dzero
+ minmn=min0(m,n)
+ minmn1=minmn+1
+ if (m.eq.minmn) go to 110
+ do 100 i=minmn1,m
+ 100 sb=sb+dble(b(i))**2
+ 110 sing(2*minmn+1)=sb
+ do 120 jj=1,minmn
+ j=minmn+1-jj
+ sb=sb+dble(b(j))**2
+ js=minmn+j
+ 120 sing(js)=sb
+ a3=sing(minmn+1)
+ a4=sqrt(a3/float(max0(1,mdata)))
+ write (6,230) a3,a4
+c
+ nsol=0
+c
+c
+c
+ do 160 k=1,minmn
+ if (sing(k).eq.zero) go to 130
+ nsol=k
+ pi=b(k)/sing(k)
+ a1=one/sing(k)
+ a2=b(k)**2
+ a3=sing(minmn1+k)
+ a4=sqrt(a3/float(max0(1,mdata-k)))
+ test=sing(k).ge.100..or.sing(k).lt..001
+ if (test) write (6,240) k,sing(k),pi,a1,b(k),a2,a3,a4
+ if (.not.test) write (6,250) k,sing(k),pi,a1,b(k),a2,a3,a4
+ go to 140
+ 130 write (6,240) k,sing(k)
+ pi=zero
+ 140 do 150 i=1,n
+ a(i,k)=a(i,k)*pi
+ 150 if (k.gt.1) a(i,k)=a(i,k)+a(i,k-1)
+ 160 continue
+c
+c compute and print values of ynorm and rnorm.
+c
+ write (6,300)
+ j=0
+ ysq=zero
+ go to 180
+ 170 j=j+1
+ ysq=ysq+(b(j)/sing(j))**2
+ 180 ynorm=sqrt(ysq)
+ js=minmn1+j
+ rnorm=sqrt(sing(js))
+ yl=-1000.
+ if (ynorm.gt.0.) yl=alog10(ynorm)
+ rl=-1000.
+ if (rnorm.gt.0.) rl=alog10(rnorm)
+ write (6,310) j,ynorm,rnorm,yl,rl
+ if (j.lt.nsol) go to 170
+c
+c compute values of xnorm and rnorm for a sequence of values of
+c the levenberg-marquardt parameter.
+c
+ if (sing(1).eq.zero) go to 210
+ el=alog10(sing(1))+one
+ el2=alog10(sing(nsol))-one
+ del=(el2-el)/20.
+ ten=10.
+ aln10=alog(ten)
+ write (6,320)
+ do 200 ie=1,21
+c compute alamb=10.**el
+ alamb=exp(aln10*el)
+ ys=0.
+ js=minmn1+nsol
+ rs=sing(js)
+ do 190 i=1,minmn
+ sl=sing(i)**2+alamb**2
+ ys=ys+(b(i)*sing(i)/sl)**2
+ rs=rs+(b(i)*(alamb**2)/sl)**2
+ 190 continue
+ ynorm=sqrt(ys)
+ rnorm=sqrt(rs)
+ rl=-1000.
+ if (rnorm.gt.zero) rl=alog10(rnorm)
+ yl=-1000.
+ if (ynorm.gt.zero) yl=alog10(ynorm)
+ write (6,330) alamb,ynorm,rnorm,el,yl,rl
+ el=el+del
+ 200 continue
+c
+c print candidate solutions.
+c
+ 210 if (nsol.ge.1) call mfeout (a,mda,n,nsol,names,2)
+ return
+ 220 format (42h0 index sing. value p coef ,48hrecip. s.
+ 1v. g coef g**2 ,39h c.s.s.
+ 2 n.s.r.c.s.s.)
+ 230 format (1h ,5x,1h0,88x,1pe15.4,1pe17.4)
+ 240 format (1h ,i6,e12.4,1p(e15.4,4x,e15.4,4x,e15.4,4x,e15.4,4x,e15.4,
+ 12x,e15.4))
+ 250 format (1h ,i6,f12.4,1p(e15.4,4x,e15.4,4x,e15.4,4x,e15.4,4x,e15.4,
+ 12x,e15.4))
+ 260 format (5h0m = ,i6,8h, n = ,i4,12h, mdata = ,i8)
+ 270 format (45h0singular value analysis of the least squares,42h probl
+ 1em, a*x=b, scaled as (a*d)*y=b .)
+ 280 format (19h0scaling option no.,i2,18h. d is a diagonal,46h matrix
+ 1 with the following diagonal elements../(5x,10e12.4))
+ 290 format (50h0scaling option no. 1. d is the identity matrix./1x)
+ 300 format (6h0index,13x,28h ynorm rnorm,14x,28h log1
+ 10(ynorm) log10(rnorm)/1x)
+ 310 format (1h ,i4,14x,2e14.5,14x,2f14.5)
+ 320 format (54h0norms of solution and residual vectors for a range of,
+ 144h values of the levenberg-marquardt parameter,9h, lambda./1h0,4x
+ 2,42h lambda ynorm rnorm,42h log10(lambda)
+ 3log10(ynorm) log10(rnorm))
+ 330 format (5x,3e14.5,3f14.5)
+ end