ISCE_INSAR/components/mroipac/fitoff/src/fitoff.F

1088 lines
28 KiB
Fortran

subroutine fitoff
use fortranUtils
use fitoffState
!c Define variables for main program; n = columns, m = rows
IMPLICIT NONE
integer n,i, mmax
integer k, iter
real*8 threshx,threshy
real*8 numerator, denominator, per_soln_length
real*8 per_soln_length_last, delta_length
logical change
!!Arrays needed for processing
double precision, allocatable, dimension(:,:) :: a,a_old
double precision, allocatable, dimension(:) :: resx,resy
double precision, allocatable, dimension(:) :: b_old,b
double precision, allocatable, dimension(:) :: data,c,e
double precision, allocatable, dimension(:,:) :: u
integer, allocatable, dimension(:) :: s
integer m, np, mp
real*8 v(nmax,nmax),w(nmax),x_prev(nmax)
integer n2,m2
real*8 toler
integer p
real*8 rmsx,rmsy,xsdev,ysdev,sdev
real*8 d(2),f(2),r_rotang,r_rtod,pi
real*8 r_u(2),r_u2,r_rot(2,2),r_aff(2,2),r_scale1,r_scale2,r_skew
logical sing
pi = getPI()
r_rtod = 180.d0/pi
change = .true.
per_soln_length = 0.
!!Save initial number of lines in mmax
mmax = 2*(imax+2)
do i=1,imax
x2o(i) = x1o(i) + dx(i)
y2o(i) = y1o(i) + dy(i)
!! print *, x1o(i), dx(i), y1o(i), dy(i), snr(i), r_covac(i), r_covdn(i),r_covx(i)
enddo
!! print *,'Params: ', nsig, maxrms, minpoint, l1norm
!! print *, 'Iters:', miniter, maxiter
if(imax .lt. 2) then
print *,'fitoff.F: Need at least 2 points'
goto 105
endif
!!!Allocate the arrays
allocate(a(mmax,nmax))
allocate(a_old(mmax, nmax))
allocate(b(mmax))
allocate(b_old(mmax))
allocate(c(mmax))
allocate(resx(mmax))
allocate(resy(mmax))
allocate(e(mmax))
allocate(u(mmax,nmax))
allocate(s(mmax))
allocate(data(mmax))
!c now setup matrices to solve overdetermined system of equations:
!c [x2] [m1 m2] [x1] [m5]
!c [ ] = [ ] x [ ] + [ ]
!c [y2] [m3 m4] [y1] [m6]
!c
!c ^ ^ ^ ^
!c | | X = solution vector |
!c B A = affine translation
!c vector transformation matrix vector
do iter =1,maxiter+1
do k = 1,(2*imax)
if (k.le.imax) then
!matrix B
b(k) = x2o(k)
!Matrix A
a(k,1)=x1o(k)
a(k,2)=y1o(k)
a(k,3)=0.0d0
a(k,4)=0.0d0
a(k,5)=1.0
a(k,6)=0.0d0
else
!matrix B
b(k) = y2o(k-imax)
!matrix A
a(k,1)=0.0d0
a(k,2)=0.0d0
a(k,3)=x1o(k-imax)
a(k,4)=y1o(k-imax)
a(k,5)=0.0d0
a(k,6)=1.0
endif
end do
np = nmax
mp = mmax
if (.not.(l1norm)) then
!c use L2 Norm to compute M matrix, from Numerical Recipes (p. 57)
!c n = number of columns, m = number of rows
n = 6
m = 2*imax
!c save the A matrix before using svdcmp, because it will be destroyed
do k = 1,np
do i = 1, m
a_old(i,k) = a(i,k)
end do
end do
do k = 1,m
b_old(k) = b(k)
end do
call dsvdcmp(a,m,n,mp,np,w,v)
do k = 1,n
do i = 1, m
u(i,k) = a(i,k)
end do
end do
call dsvbksb(u,w,v,m,n,mp,np,b,x)
endif
!c use L1 norm to compute M matrix
if (l1norm) then
n = 6
m = 2*imax
n2 = n + 2
m2 = m + 2
toler = 1.0d-20
!c save b and a arrays since they are destroyed in subroutines
do k = 1,n
do i = 1, m
a_old(i,k) = a(i,k)
end do
end do
do k = 1,m
b_old(k) = b(k)
end do
call L1(M,N,M2,N2,A,B,TOLER,X,E,S,nmax,mmax)
endif
!c multiple A and X together and compute residues
call mmul(M,N,A_OLD,X,C,nmax,mmax)
do k = 1,imax
resx(k) = c(k) - b_old(k)
resy(k) = c(k+imax) - b_old(k+imax)
end do
p = imax
rmsy = 0.0d0
rmsx = 0.0d0
!c compute statistics for x coordinates: standard deviation, mean, & rms
do k = 1,imax
data(k)= resx(k)
rmsx = rmsx + resx(k)**2.
end do
call dmoment(data,p,sdev)
rmsx = sqrt(rmsx/imax)
xsdev = sdev
! print *, 'Sdev1 :', sdev
!c compute statistics for y coordinates
do k = 1,(imax)
data(k)= resy(k)
rmsy = rmsy + resy(k)**2.
end do
call dmoment(data,p,sdev)
rmsy = sqrt(rmsy/imax)
ysdev = sdev
if (rmsx.gt.maxrms) then
threshx = nsig*xsdev
else
threshx = 99999
endif
if (rmsy.gt.maxrms) then
threshy = nsig*ysdev
else
threshy = 99999
endif
! print *, 'Threshs: ', threshx, threshy, sdev
!c determine whether to remove points for next iteration
if ((rmsx.gt.maxrms).or.(rmsy.gt.maxrms)) then
!c determine which points to save for next iteration
i = 0
do k = 1,imax
if ((abs(resx(k)).lt.threshx)
> .and.(abs(resy(k)).lt.threshy)) then
i = i + 1
x2o(i) = x2o(k)
x1o(i) = x1o(k)
y2o(i) = y2o(k)
y1o(i) = y1o(k)
snr(i) = snr(k)
r_covac(i) = r_covac(k)
r_covdn(i) = r_covdn(k)
r_covx(i) = r_covx(k)
endif
end do
imax = i
endif
!c if fewer than minpoints, quit and output warning
if (imax.le.minpoint) goto 97
!c if rms fit is good enough, then quit program
if ((rmsx.lt.maxrms).and.(rmsy.lt.maxrms)) goto 99
if (iter.gt.1) then
numerator = 0.0d0
denominator = 0.0d0
!c if the soln. length does not change between iterations, and solution fit
!c doesn't match specified parameters, then quit
do k = 1,6
numerator = numerator + (x(k) - x_prev(k))**2.
denominator = (x_prev(k))**2. + denominator
end do
per_soln_length = sqrt(numerator/denominator)*100.
end if
if (iter.ge.miniter) then
delta_length = (per_soln_length -
> per_soln_length_last)
if ((delta_length.eq.0).and.
> ((rmsx.gt.maxrms).or.(rmsy.gt.maxrms))) then
change = .false.
goto 96
endif
endif
per_soln_length_last = per_soln_length
do k = 1,6
x_prev(k) = x(k)
end do
end do
!c exceeded maximum number of iterations, output garbage
print *,'WARNING: Exceeded maximum number of iterations.'
!c solution length not changing and fit parameters not achieved
96 if (.not.change) then
print *,'WARNING: Solution length is not changing,'
print *,'but does not meet fit criteria'
endif
!c Fewer than minimum number of points, output garbage
97 if (imax.le.minpoint) then
print *, 'WARNING: Fewer than minimum points, there are only'
> ,imax
endif
99 print *,' '
if (((iter.lt.maxiter).and.(imax.gt.minpoint)).and.
> (change)) then
print *, ' << Fitoff Program >> '
print *, ' '
print *, 'Number of points remaining =', imax
print *, ' '
print *, 'RMS in X = ', rmsx, ' RMS in Y = ', rmsy
print *, ' '
!c Decompose matrix and examine residuals
print *, ' '
print *, ' Matrix Analysis '
print *, ' '
print *, ' Affine Matrix '
print *, ' '
print *, x(1), x(2)
print *, x(3), x(4)
101 format(1x,f15.10,1x,f15.10)
print *, ' '
print *, 'Translation Vector'
print *, ' '
print *, x(5),x(6)
102 format(1x,f11.3,1x,f11.3,1x)
!c decompose affine matrix to find rotation matrix using QR decomposition
!c R is an upper triangular matrix and Q is an orthogonal matrix such
!c that A = QR. For our 2 X 2 matrix we can consider
!c T
!c Q A = R, where Q is a Housholder matrix, which is also a rotation matrix
!c Subroutine qrdcmp ( Numerical recipes, pg 92) returns the u vectors
!c used to compute Q1 in r_aff(1,1). r_aff(1,2), d(1) and d(2) are
!c the diagonal terms of the R matrix, while r_aff(1,2) is the other
!c point in the R matrix and these can be used to find the scale and
!c skew terms
r_aff(1,1) = x(1)
r_aff(1,2) = x(2)
r_aff(2,1) = x(3)
r_aff(2,2) = x(4)
call qrdcmp(r_aff,2,2,f,d,sing)
r_u(1) = r_aff(1,1)
r_u(2) = r_aff(2,1)
r_u2 = .5d0*(r_u(1)**2 + r_u(2)**2)
r_rot(1,1) = (1.d0 - (r_u(1)**2/r_u2))
r_rot(1,2) = -(r_u(1)*r_u(2))/r_u2
r_rot(2,1) = -(r_u(1)*r_u(2))/r_u2
r_rot(2,2) = (1.d0 - (r_u(2)**2/r_u2))
if(d(1) .lt. 0)then
r_rot(1,1) = -r_rot(1,1)
r_rot(2,1) = -r_rot(2,1)
d(1) = -d(1)
r_aff(1,2) = -r_aff(1,2)
elseif(d(2) .lt. 0)then
r_rot(1,2) = -r_rot(1,2)
r_rot(2,2) = -r_rot(2,2)
d(2) = -d(2)
endif
r_scale1 = abs(d(1))
r_scale2 = abs(d(2))
r_skew = r_aff(1,2)/d(1)
r_rotang = atan2(r_rot(2,1),r_rot(1,1))
print *, ' '
print *, ' Rotation Matrix '
print *, ' '
print *, r_rot(1,1),r_rot(1,2)
print *, r_rot(2,1),r_rot(2,2)
print *, ' '
print *, 'Rotation Angle (deg) = ',r_rotang*r_rtod
print *, ' '
print *, ' Axis Scale Factors'
print *, ' '
print *, r_scale1,r_scale2
103 format(1x,f11.7,1x,f11.7)
print *,' '
print *,' Skew Term'
print *, ' '
print *, r_skew
104 format(1x,f11.7)
endif
!!Deallocate arrays
deallocate(a,a_old)
deallocate(b,b_old)
deallocate(c,resx,resy)
deallocate(e,u,s,data)
105 end
!C ALGORITHM 478 COLLECTED ALGORITHMS FROM ACM.
!C ALGORITHM APPEARED IN COMM. ACM, VOL. 17, NO. 06,
!C P. 319.
!C NOTE: this version is modified to allow double precision
SUBROUTINE L1(M,N,M2,N2,A,B,TOLER,X,E,S,NMAX,MMAX)
!C THIS SUBROUTINE USES A MODIFICATION OF THE SIMPLEX METHOD
!C OF LINEAR PROGRAMMING TO CALCULATE AN L1 SOLUTION TO AN
!C OVER-DETERMINED SYSTEM OF LINEAR EQUATIONS.
!C DESCRIPTION OF PARAMETERS.
!C M NUMBER OF EQUATIONS.
!C N NUMBER OF UNKNOWNS (M.GE.N).
!C M2 SET EQUAL TO M+2 FOR ADJUSTABLE DIMENSIONS.
!C N2 SET EQUAL TO N+2 FOR ADJUSTABLE DIMENSIONS.
!C A TWO DIMENSIONAL REAL ARRAY OF SIZE (M2,N2).
!C ON ENTRY, THE COEFFICIENTS OF THE MATRIX MUST BE
!C STORED IN THE FIRST M ROWS AND N COLUMNS OF A.
!C THESE VALUES ARE DESTROYED BY THE SUBROUTINE.
!C B ONE DIMENSIONAL REAL ARRAY OF SIZE M. ON ENTRY, B
!C MUST CONTAIN THE RIGHT HAND SIDE OF THE EQUATIONS.
!C THESE VALUES ARE DESTROYED BY THE SUBROUTINE.
!C TOLER A SMALL POSITIVE TOLERANCE. EMPIRICAL EVIDENCE
!C SUGGESTS TOLER=10**(-D*2/3) WHERE D REPRESENTS
!C THE NUMBER OF DECIMAL DIGITS OF ACCURACY AVALABLE
!C (SEE DESCRIPTION).
!C X ONE DIMENSIONAL REAL ARRAY OF SIZE N. ON EXIT, THIS
!C ARRAY CONTAINS A SOLUTION TO THE L1 PROBLEM.
!C E ONE DIMENSIONAL REAL ARRAY OF SIZE M. ON EXIT, THIS
!C ARRAY CONTAINS THE RESIDUALS IN THE EQUATIONS.
!C S INTEGER ARRAY OF SIZE M USED FOR WORKSPACE.
!C ON EXIT FROM THE SUBROUTINE, THE ARRAY A CONTAINS THE
!C FOLLOWING INFORMATION.
!C A(M+1,N+1) THE MINIMUM SUM OF THE ABSOLUTE VALUES OF
!C THE RESIDUALS.
!C A(M+1,N+2) THE RANK OF THE MATRIX OF COEFFICIENTS.
!C A(M+2,N+1) EXIT CODE WITH VALUES.
!C 0 - OPTIMAL SOLUTION WHICH IS PROBABLY NON-
!C UNIQUE (SEE DESCRIPTION).
!C 1 - UNIQUE OPTIMAL SOLUTION.
!C 2 - CALCULATIONS TERMINATED PREMATURELY DUE TO
!C ROUNDING ERRORS.
!C A(M+2,N+2) NUMBER OF SIMPLEX ITERATIONS PERFORMED.
Implicit None
INTEGER m,m1,m2,n,n1,n2,NMAX,MMAX
double precision SUM, MIN, MAX
double precision :: A(Mmax,Nmax)
double precision :: X(Nmax), E(Mmax), B(Mmax)
!! REAL*8 MIN, MAX, A(Mmax,Nmax), X(Nmax), E(Mmax), B(Mmax)
integer :: S(Mmax)
INTEGER OUT
LOGICAL STAGE, TEST
!c define variables in program whose type were assumed implicitly
integer i,j,kr,k,kl,kount,in,l
double precision d, pivot,toler,big
!C BIG MUST BE SET EQUAL TO ANY VERY LARGE REAL CONSTANT.
!C ITS VALUE HERE IS APPROPRIATE FOR THE IBM 370.
!c DATA BIG/1.E75/
!C ITS VALUE HERE IS APPROPRIATE FOR SGI
DATA BIG/1.E38/
!C INITIALIZATION.
M1 = M + 1
N1 = N + 1
DO 10 J=1,N
A(M2,J) = J
X(J) = 0.0d0
10 CONTINUE
DO 40 I=1,M
A(I,N2) = N + I
A(I,N1) = B(I)
IF (B(I).GE.0.0d0) GO TO 30
DO 20 J=1,N2
A(I,J) = -A(I,J)
20 CONTINUE
30 E(I) = 0.0d0
40 CONTINUE
!C COMPUTE THE MARGINAL COSTS.
DO 60 J=1,N1
SUM = 0.0D0
DO 50 I=1,M
SUM = SUM + A(I,J)
50 CONTINUE
A(M1,J) = SUM
60 CONTINUE
!C STAGE I.
!C DETERMINE THE VECTOR TO ENTER THE BASIS.
STAGE = .TRUE.
KOUNT = 0
KR = 1
KL = 1
70 MAX = -1.
DO 80 J=KR,N
IF (ABS(A(M2,J)).GT.N) GO TO 80
D = ABS(A(M1,J))
IF (D.LE.MAX) GO TO 80
MAX = D
IN = J
80 CONTINUE
IF (A(M1,IN).GE.0.0d0) GO TO 100
DO 90 I=1,M2
A(I,IN) = -A(I,IN)
90 CONTINUE
!C DETERMINE THE VECTOR TO LEAVE THE BASIS.
100 K = 0
DO 110 I=KL,M
D = A(I,IN)
IF (D.LE.TOLER) GO TO 110
K = K + 1
B(K) = A(I,N1)/D
S(K) = I
TEST = .TRUE.
110 CONTINUE
120 IF (K.GT.0) GO TO 130
TEST = .FALSE.
GO TO 150
130 MIN = BIG
DO 140 I=1,K
IF (B(I).GE.MIN) GO TO 140
J = I
MIN = B(I)
OUT = S(I)
140 CONTINUE
B(J) = B(K)
S(J) = S(K)
K = K - 1
!C CHECK FOR LINEAR DEPENDENCE IN STAGE I.
150 IF (TEST .OR. .NOT.STAGE) GO TO 170
DO 160 I=1,M2
D = A(I,KR)
A(I,KR) = A(I,IN)
A(I,IN) = D
160 CONTINUE
KR = KR + 1
GO TO 260
170 IF (TEST) GO TO 180
A(M2,N1) = 2.
GO TO 350
180 PIVOT = A(OUT,IN)
IF (A(M1,IN)-PIVOT-PIVOT.LE.TOLER) GO TO 200
DO 190 J=KR,N1
D = A(OUT,J)
A(M1,J) = A(M1,J) - D - D
A(OUT,J) = -D
190 CONTINUE
A(OUT,N2) = -A(OUT,N2)
GO TO 120
!C PIVOT ON A(OUT,IN).
200 DO 210 J=KR,N1
IF (J.EQ.IN) GO TO 210
A(OUT,J) = A(OUT,J)/PIVOT
210 CONTINUE
!c DO 230 I=1,M1
!c IF (I.EQ.OUT) GO TO 230
!c D = A(I,IN)
!c DO 220 J=KR,N1
!c IF (J.EQ.IN) GO TO 220
!c A(I,J) = A(I,J) - D*A(OUT,J)
!c 220 CONTINUE
!c 230 CONTINUE
!c impliment time saving change suggested in Barrodale and Roberts - collected
!c algorithms from CACM
DO 220 J = KR,N1
IF (J.EQ.IN) GO TO 220
CALL COL(A(1,J),A(1,IN),A(OUT,J),M1,OUT)
220 CONTINUE
DO 240 I=1,M1
IF (I.EQ.OUT) GO TO 240
A(I,IN) = -A(I,IN)/PIVOT
240 CONTINUE
A(OUT,IN) = 1./PIVOT
D = A(OUT,N2)
A(OUT,N2) = A(M2,IN)
A(M2,IN) = D
KOUNT = KOUNT + 1
IF (.NOT.STAGE) GO TO 270
!C INTERCHANGE ROWS IN STAGE I.
KL = KL + 1
DO 250 J=KR,N2
D = A(OUT,J)
A(OUT,J) = A(KOUNT,J)
A(KOUNT,J) = D
250 CONTINUE
260 IF (KOUNT+KR.NE.N1) GO TO 70
!C STAGE II.
STAGE = .FALSE.
!C DETERMINE THE VECTOR TO ENTER THE BASIS.
270 MAX = -BIG
DO 290 J=KR,N
D = A(M1,J)
IF (D.GE.0.0d0) GO TO 280
IF (D.GT.(-2.)) GO TO 290
D = -D - 2.
280 IF (D.LE.MAX) GO TO 290
MAX = D
IN = J
290 CONTINUE
IF (MAX.LE.TOLER) GO TO 310
IF (A(M1,IN).GT.0.0d0) GO TO 100
DO 300 I=1,M2
A(I,IN) = -A(I,IN)
300 CONTINUE
A(M1,IN) = A(M1,IN) - 2.
GO TO 100
!C PREPARE OUTPUT.
310 L = KL - 1
DO 330 I=1,L
IF (A(I,N1).GE.0.0d0) GO TO 330
DO 320 J=KR,N2
A(I,J) = -A(I,J)
320 CONTINUE
330 CONTINUE
A(M2,N1) = 0.0d0
IF (KR.NE.1) GO TO 350
DO 340 J=1,N
D = ABS(A(M1,J))
IF (D.LE.TOLER .OR. 2.-D.LE.TOLER) GO TO 350
340 CONTINUE
A(M2,N1) = 1.
350 DO 380 I=1,M
K = A(I,N2)
D = A(I,N1)
IF (K.GT.0) GO TO 360
K = -K
D = -D
360 IF (I.GE.KL) GO TO 370
X(K) = D
GO TO 380
370 K = K - N
E(K) = D
380 CONTINUE
A(M2,N2) = KOUNT
A(M1,N2) = N1 - KR
SUM = 0.0D0
DO 390 I=KL,M
SUM = SUM + A(I,N1)
390 CONTINUE
A(M1,N1) = SUM
RETURN
END
SUBROUTINE COL(V1,V2,MLT,M1,IOUT)
IMPLICIT NONE
INTEGER M1,I,IOUT
REAL*8 V1(M1),V2(M1),MLT
DO 1 I = 1,M1
IF (I.EQ.IOUT) GO TO 1
V1(I)=V1(I)-V2(I)*MLT
1 CONTINUE
RETURN
END
!c The following three programs are used to find the L2 norm
SUBROUTINE dsvbksb(u,w,v,m,n,mp,np,b,x)
Implicit None
INTEGER m,mp,n,np
!! REAL*8 b(mmax),u(mmax,nmax),v(nmax,nmax),w(nmax),x(nmax)
double precision :: b(mp),w(np),x(np)
double precision :: u(mp,np),v(np,np)
INTEGER i,j,jj
DOUBLE PRECISION s,tmp(np)
do 12 j=1,n
s=0.0d0
if(w(j).ne.0.0d0)then
do 11 i=1,m
s=s+u(i,j)*b(i)
11 continue
s=s/w(j)
endif
tmp(j)=s
12 continue
do 14 j=1,n
s=0.0d0
do 13 jj=1,n
s=s+v(j,jj)*tmp(jj)
13 continue
x(j)=s
14 continue
return
END
SUBROUTINE dsvdcmp(a,m,n,mp,np,w,v)
Implicit None
INTEGER m,mp,n,np
!c DOUBLE PRECISION a(mp,np),v(np,np),w(np)
!! REAL*8 a(mmax,nmax),v(nmax,nmax),w(nmax)
double precision :: w(np)
double precision :: a(mp,np),v(np,np)
double precision :: rv1(np)
!CU USES dpythag
INTEGER i,its,j,jj,k,l,nm
DOUBLE PRECISION anorm,c,f,g,h,s,scale,x,y,z,dpythag
g=0.0d0
scale=0.0d0
anorm=0.0d0
do 25 i=1,n
l=i+1
rv1(i)=scale*g
g=0.0d0
s=0.0d0
scale=0.0d0
if(i.le.m)then
do 11 k=i,m
scale=scale+abs(a(k,i))
11 continue
if(scale.ne.0.0d0)then
do 12 k=i,m
a(k,i)=a(k,i)/scale
s=s+a(k,i)*a(k,i)
12 continue
f=a(i,i)
g=-sign(sqrt(s),f)
h=f*g-s
a(i,i)=f-g
do 15 j=l,n
s=0.0d0
do 13 k=i,m
s=s+a(k,i)*a(k,j)
13 continue
f=s/h
do 14 k=i,m
a(k,j)=a(k,j)+f*a(k,i)
14 continue
15 continue
do 16 k=i,m
a(k,i)=scale*a(k,i)
16 continue
endif
endif
w(i)=scale *g
g=0.0d0
s=0.0d0
scale=0.0d0
if((i.le.m).and.(i.ne.n))then
do 17 k=l,n
scale=scale+abs(a(i,k))
17 continue
if(scale.ne.0.0d0)then
do 18 k=l,n
a(i,k)=a(i,k)/scale
s=s+a(i,k)*a(i,k)
18 continue
f=a(i,l)
g=-sign(sqrt(s),f)
h=f*g-s
a(i,l)=f-g
do 19 k=l,n
rv1(k)=a(i,k)/h
19 continue
do 23 j=l,m
s=0.0d0
do 21 k=l,n
s=s+a(j,k)*a(i,k)
21 continue
do 22 k=l,n
a(j,k)=a(j,k)+s*rv1(k)
22 continue
23 continue
do 24 k=l,n
a(i,k)=scale*a(i,k)
24 continue
endif
endif
anorm=max(anorm,(abs(w(i))+abs(rv1(i))))
25 continue
do 32 i=n,1,-1
if(i.lt.n)then
if(g.ne.0.0d0)then
do 26 j=l,n
v(j,i)=(a(i,j)/a(i,l))/g
26 continue
do 29 j=l,n
s=0.0d0
do 27 k=l,n
s=s+a(i,k)*v(k,j)
27 continue
do 28 k=l,n
v(k,j)=v(k,j)+s*v(k,i)
28 continue
29 continue
endif
do 31 j=l,n
v(i,j)=0.0d0
v(j,i)=0.0d0
31 continue
endif
v(i,i)=1.0d0
g=rv1(i)
l=i
32 continue
do 39 i=min(m,n),1,-1
l=i+1
g=w(i)
do 33 j=l,n
a(i,j)=0.0d0
33 continue
if(g.ne.0.0d0)then
g=1.0d0/g
do 36 j=l,n
s=0.0d0
do 34 k=l,m
s=s+a(k,i)*a(k,j)
34 continue
f=(s/a(i,i))*g
do 35 k=i,m
a(k,j)=a(k,j)+f*a(k,i)
35 continue
36 continue
do 37 j=i,m
a(j,i)=a(j,i)*g
37 continue
else
do 38 j= i,m
a(j,i)=0.0d0
38 continue
endif
a(i,i)=a(i,i)+1.0d0
39 continue
do 49 k=n,1,-1
do 48 its=1,30
do 41 l=k,1,-1
nm=l-1
if((abs(rv1(l))+anorm).eq.anorm) goto 2
if((abs(w(nm))+anorm).eq.anorm) goto 1
41 continue
1 c=0.0d0
s=1.0d0
do 43 i=l,k
f=s*rv1(i)
rv1(i)=c*rv1(i)
if((abs(f)+anorm).eq.anorm) goto 2
g=w(i)
h=dpythag(f,g)
w(i)=h
h=1.0d0/h
c= (g*h)
s=-(f*h)
do 42 j=1,m
y=a(j,nm)
z=a(j,i)
a(j,nm)=(y*c)+(z*s)
a(j,i)=-(y*s)+(z*c)
42 continue
43 continue
2 z=w(k)
if(l.eq.k)then
if(z.lt.0.0d0)then
w(k)=-z
do 44 j=1,n
v(j,k)=-v(j,k)
44 continue
endif
goto 3
endif
! if(its.eq.30) pause 'no convergence in svdcmp'
if(its.eq.30) then
write (6,*) 'fitoff: no convergence in svdcmp, quitting'
stop
endif
x=w(l)
nm=k-1
y=w(nm)
g=rv1(nm)
h=rv1(k)
f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0d0*h*y)
g=dpythag(f,1.0d0)
f=((x-z)*(x+z)+h*((y/(f+sign(g,f)))-h))/x
c=1.0d0
s=1.0d0
do 47 j=l,nm
i=j+1
g=rv1(i)
y=w(i)
h=s*g
g=c*g
z=dpythag(f,h)
rv1(j)=z
c=f/z
s=h/z
f= (x*c)+(g*s)
g=-(x*s)+(g*c)
h=y*s
y=y*c
do 45 jj=1,n
x=v(jj,j)
z=v(jj,i)
v(jj,j)= (x*c)+(z*s)
v(jj,i)=-(x*s)+(z*c)
45 continue
z=dpythag(f,h)
w(j)=z
if(z.ne.0.0d0)then
z=1.0d0/z
c=f*z
s=h*z
endif
f= (c*g)+(s*y)
x=-(s*g)+(c*y)
do 46 jj=1,m
y=a(jj,j)
z=a(jj,i)
a(jj,j)= (y*c)+(z*s)
a(jj,i)=-(y*s)+(z*c)
46 continue
47 continue
rv1(l)=0.0d0
rv1(k)=f
w(k)=x
48 continue
3 continue
49 continue
return
END
FUNCTION dpythag(a,b)
Implicit None
!c DOUBLE PRECISION a,b,dpythag
!c DOUBLE PRECISION absa,absb
Real*8 a,b,dpythag
Real*8 absa,absb
absa=abs(a)
absb=abs(b)
if(absa.gt.absb)then
dpythag=absa*sqrt(1.0d0+(absb/absa)**2)
else
if(absb.eq.0.0d0)then
dpythag=0.0d0
else
dpythag=absb*sqrt(1.0d0+(absa/absb)**2)
endif
endif
return
END
SUBROUTINE MMUL (M,N,A_OLD,X,C,nmax,mmax)
Implicit None
!C *****PARAMETERS:
Integer nmax, mmax, M, N
double precision :: a_old(MMAX,NMAX)
double precision :: x(NMAX),c(MMAX)
!! REAL*8 a_old(mmax,nmax),x(nmax),c(mmax)
INTEGER NA,NB,NC,L
!C *****LOCAL VARIABLES:
INTEGER I,K
NA = M
NB = nmax
NC = M
N = nmax
L = 1
!C *****SUBROUTINES CALLED:
!C NONE
!C
!C ------------------------------------------------------------------
!C
!C *****PURPOSE:
!C THIS SUBROUTINE COMPUTES THE MATRIX PRODUCT A*B AND STORES THE
!C RESULT IN THE ARRAY C. A IS M X N, B IS N X L, AND C IS
!C M X L. THE ARRAY C MUST BE DISTINCT FROM BOTH A AND B.
!C
!C *****PARAMETER DESCRIPTION:
!C ON INPUT:
!C NA ROW DIMENSION OF THE ARRAY CONTAINING A AS DECLARED
!C IN THE CALLING PROGRAM DIMENSION STATEMENT;
!C
!C NB ROW DIMENSION OF THE ARRAY CONTAINING B AS DECLARED
!C IN THE CALLING PROGRAM DIMENSION STATEMENT;
!C
!C NC ROW DIMENSION OF THE ARRAY CONTAINING C AS DECLARED
!C IN THE CALLING PROGRAM DIMENSION STATEMENT;
!C
!C L NUMBER OF COLUMNS OF THE MATRICES B AND C;
!C
!C M NUMBER OF ROWS OF THE MATRICES A AND C;
!C
!C N NUMBER OF COLUMNS OF THE MATRIX A AND NUMBER OF ROWS
!C OF THE MATRIX B;
!C
!C A AN M X N MATRIX;
!C
!C B AN N X L MATRIX.
!C
!C ON OUTPUT:
!C
!C C AN M X L ARRAY CONTAINING A*B.
!C
!C *****HISTORY:
!C WRITTEN BY ALAN J. LAUB (ELEC. SYS. LAB., M.I.T., RM. 35-331,
!C CAMBRIDGE, MA 02139, PH.: (617)-253-2125), SEPTEMBER 1977.
!C MOST RECENT VERSION: SEP. 21, 1977.
!C
!C ------------------------------------------------------------------
!C
DO 10 I=1,M
C(I)=0.0d0
10 CONTINUE
DO 30 K=1,N
DO 20 I=1,M
C(I)=C(I)+a_old(I,K)*x(K)
20 CONTINUE
30 CONTINUE
RETURN
END
!c Modify Numerical Recipes program moment.f to compute only
!c standard deviation and allow double precision
SUBROUTINE dmoment(data,p,sdev)
Implicit None
INTEGER p
REAL*8 adev,ave,curt,sdev,skew,var,data(p)
INTEGER j
REAL*8 t,s,ep
! if(p.le.1)pause 'p must be at least 2 in moment'
if(p.le.1) then
write (6,*) 'fitoff: p must be at least 2 in moment'
write (6,*) ' culling points failed'
stop
endif
s=0.0d0
do 11 j=1,p
s=s+data(j)
11 continue
ave=s/p
adev=0.0d0
var=0.0d0
skew=0.0d0
curt=0.0d0
ep=0.
do 12 j=1,p
s=data(j)-ave
t=s*s
var=var+t
12 continue
adev=adev/p
var=(var-ep**2/p)/(p-1)
sdev=sqrt(var)
return
END
!c This program is used to find the rotation matrix from the affine matrix
SUBROUTINE qrdcmp(a,n,np,c,d,sing)
INTEGER n,np
REAL*8 a(np,np),c(n),d(n)
LOGICAL sing
INTEGER i,j,k
REAL*8 scale,sigma,sum,tau
sing=.false.
scale=0.
do 17 k=1,n-1
do 11 i=k,n
scale=max(scale,abs(a(i,k)))
11 continue
if(scale.eq.0.)then
sing=.true.
c(k)=0.
d(k)=0.
else
do 12 i=k,n
a(i,k)=a(i,k)/scale
12 continue
sum=0.
do 13 i=k,n
sum=sum+a(i,k)**2
13 continue
sigma=sign(sqrt(sum),a(k,k))
a(k,k)=a(k,k)+sigma
c(k)=sigma*a(k,k)
d(k)=-scale*sigma
do 16 j=k+1,n
sum=0.
do 14 i=k,n
sum=sum+a(i,k)*a(i,j)
14 continue
tau=sum/c(k)
do 15 i=k,n
a(i,j)=a(i,j)-tau*a(i,k)
15 continue
16 continue
endif
17 continue
d(n)=a(n,n)
if(d(n).eq.0.)sing=.true.
return
END
!C (C) Copr. 1986-92 Numerical Recipes Software $23#1yR.3Z9.