Rev 76639 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
cc dpoco factors a double precision symmetric positive definitec matrix and estimates the condition of the matrix.cc if rcond is not needed, dpofa is slightly faster.c to solve a*x = b , follow dpoco by dposl.c to compute inverse(a)*c , follow dpoco by dposl.c to compute determinant(a) , follow dpoco by dpodi.c to compute inverse(a) , follow dpoco by dpodi.cc on entrycc a double precision(lda, n)c the symmetric matrix to be factored. only thec diagonal and upper triangle are used.cc lda integerc the leading dimension of the array a .cc n integerc the order of the matrix a .cc on returncc a an upper triangular matrix r so that a = trans(r)*rc where trans(r) is the transpose.c the strict lower triangle is unaltered.c if info .ne. 0 , the factorization is not complete.cc rcond double precisionc an estimate of the reciprocal condition of a .c for the system a*x = b , relative perturbationsc in a and b of size epsilon may causec relative perturbations in x of size epsilon/rcond .c if rcond is so small that the logical expressionc 1.0 + rcond .eq. 1.0c is true, then a may be singular to workingc precision. in particular, rcond is zero ifc exact singularity is detected or the estimatec underflows. if info .ne. 0 , rcond is unchanged.cc z double precision(n)c a work vector whose contents are usually unimportant.c if a is close to a singular matrix, then z isc an approximate null vector in the sense thatc norm(a*z) = rcond*norm(a)*norm(z) .c if info .ne. 0 , z is unchanged.cc info integerc = 0 for normal return.c = k signals an error condition. the leading minorc of order k is not positive definite.cc linpack. this version dated 08/14/78 .c cleve moler, university of new mexico, argonne national lab.cc subroutines and functionscc linpack dpofac blas daxpy,ddot,dscal,dasumc fortran abs,max,signcsubroutine dpoco(a,lda,n,rcond,z,info)integer lda,n,infodouble precision a(lda,n),z(n)double precision rcondcc internal variablescdouble precision ddot,ek,t,wk,wkmdouble precision anorm,s,dasum,sm,ynorminteger i,j,jm1,k,kb,kp1ccc find norm of a using only upper halfcdo 30 j = 1, nz(j) = dasum(j,a(1,j),1)jm1 = j - 1if (jm1 .lt. 1) go to 20do 10 i = 1, jm1z(i) = z(i) + abs(a(i,j))10 continue20 continue30 continueanorm = 0.0d0do 40 j = 1, nanorm = max(anorm,z(j))40 continuecc factorccall dpofa(a,lda,n,info)if (info .ne. 0) go to 180cc rcond = 1/(norm(a)*(estimate of norm(inverse(a)))) .c estimate = norm(z)/norm(y) where a*z = y and a*y = e .c the components of e are chosen to cause maximum localc growth in the elements of w where trans(r)*w = e .c the vectors are frequently rescaled to avoid overflow.cc solve trans(r)*w = ecek = 1.0d0do 50 j = 1, nz(j) = 0.0d050 continuedo 110 k = 1, nif (z(k) .ne. 0.0d0) ek = sign(ek,-z(k))if (abs(ek-z(k)) .le. a(k,k)) go to 60s = a(k,k)/abs(ek-z(k))call dscal(n,s,z,1)ek = s*ek60 continuewk = ek - z(k)wkm = -ek - z(k)s = abs(wk)sm = abs(wkm)wk = wk/a(k,k)wkm = wkm/a(k,k)kp1 = k + 1if (kp1 .gt. n) go to 100do 70 j = kp1, nsm = sm + abs(z(j)+wkm*a(k,j))z(j) = z(j) + wk*a(k,j)s = s + abs(z(j))70 continueif (s .ge. sm) go to 90t = wkm - wkwk = wkmdo 80 j = kp1, nz(j) = z(j) + t*a(k,j)80 continue90 continue100 continuez(k) = wk110 continues = 1.0d0/dasum(n,z,1)call dscal(n,s,z,1)cc solve r*y = wcdo 130 kb = 1, nk = n + 1 - kbif (abs(z(k)) .le. a(k,k)) go to 120s = a(k,k)/abs(z(k))call dscal(n,s,z,1)120 continuez(k) = z(k)/a(k,k)t = -z(k)call daxpy(k-1,t,a(1,k),1,z(1),1)130 continues = 1.0d0/dasum(n,z,1)call dscal(n,s,z,1)cynorm = 1.0d0cc solve trans(r)*v = ycdo 150 k = 1, nz(k) = z(k) - ddot(k-1,a(1,k),1,z(1),1)if (abs(z(k)) .le. a(k,k)) go to 140s = a(k,k)/abs(z(k))call dscal(n,s,z,1)ynorm = s*ynorm140 continuez(k) = z(k)/a(k,k)150 continues = 1.0d0/dasum(n,z,1)call dscal(n,s,z,1)ynorm = s*ynormcc solve r*z = vcdo 170 kb = 1, nk = n + 1 - kbif (abs(z(k)) .le. a(k,k)) go to 160s = a(k,k)/abs(z(k))call dscal(n,s,z,1)ynorm = s*ynorm160 continuez(k) = z(k)/a(k,k)t = -z(k)call daxpy(k-1,t,a(1,k),1,z(1),1)170 continuec make znorm = 1.0s = 1.0d0/dasum(n,z,1)call dscal(n,s,z,1)ynorm = s*ynormcif (anorm .ne. 0.0d0) rcond = ynorm/anormif (anorm .eq. 0.0d0) rcond = 0.0d0180 continuereturnend