! ================================================ subroutine dkmxhf( a, det, zero, nrank, n, iopt) ! ================================================ implicit none integer, intent(in) :: n ! no. of rows/columns logical, intent(in) :: iopt ! .true./.false. : print warnings real(8), dimension(n*(n+1)/2), intent(inout) :: a ! matrix; upper triangle, stored row-wise real(8), intent(in) :: zero ! operational zero real(8), intent(out) :: det ! log determinant integer, intent(out) :: nrank ! rank of matrix real(8), dimension(n) :: v, w integer, dimension(n) :: iflag real(8) :: ww, xx, dmax, amax, bmax, dimax integer :: ii, i1, n1, il, imax, & & imaxm1,imaxp1,ij,j,i,neg ! matrix is a scalar if( n == 1 )then if(a(1) > zero)then det=dlog( a(1) ); a(1)=1.d0/a(1); nrank=1 else a(1)=0.d0; nrank=0; det=0.d0 end if return end if ! initialize neg=0; det=0.d0; iflag=0; n1=n+1 ! pick out diagonal elements ii=-n do i=1,n ii=ii+n1; w(i)=a(ii); ii=ii-i end do ! gaussian elimination steps do ii=1,n ! ... find diag. element with largest absolute value (pivot) dmax=0.d0; amax=0.d0 do i=1,n if(iflag(i) /= 0 ) cycle bmax=dabs(w(i)) if(bmax.gt.amax)then dmax=w(i); amax=bmax; imax=i end if end do ! ... check for singularity if(amax.le.zero)go to 11 if(iopt .and. amax.lt.1.d-5) print *,'small pivot ',ii,dmax ! ... set flag iflag(imax)=ii ! accumulate log determinant det=det+dlog(amax) if(dmax.lt.0.d0)then neg=neg+1 if(iopt)print *,'negative pivot, ignore sign for log det',ii,imax,dmax end if dimax=1.d0/dmax; imaxm1=imax-1; imaxp1=imax+1 ! ... pick out elements for row imax il=imax-n do i=1,imaxm1 il=il+n1-i; v(i)=a(il) end do il=il+n1-imax do i=imaxp1,n il=il+1; v(i)=a(il) end do ! ... transform matrix ij=0 do i=1,imaxm1 ww = v(i) if(ww /= 0.d0)then xx = ww*dimax ij = ij+1; w(i) = w(i) - ww*xx do j=i+1,imaxm1 ij=ij+1; if( v(j) /= 0) a(ij) = a(ij)-xx*v(j) end do ! element a(i,imax) ij=ij+1; a(ij) = xx do j = imaxp1,n ij=ij+1; if( v(j) /= 0) a(ij) = a(ij)-xx*v(j) end do else ij=ij+n1-i ! update address counter end if end do ! row imax ij=ij+1; w(imax)=-dimax do j =imaxp1,n ij=ij+1; a(ij)=v(j)*dimax end do do i=imaxp1,n ww=v(i) if(ww /= 0.d0)then xx=ww*dimax; ij=ij+1; w(i)=w(i)-ww*xx do j=i+1,n ij=ij+1; a(ij)=a(ij)-xx*v(j) end do else ij=ij+n1-i end if end do end do ! loop over rows/columns ! store diagonals back & reverse signs ij=0 do i=1,n ij=ij+1; ww=-w(i); w(i)=ww; a(ij)=ww do j=i+1,n ij=ij+1; a(ij)=-a(ij) end do end do nrank=n 300 if(iopt) then if(neg.gt.0) write(*,*)'no. of negative pivots =', neg if(mod(neg,2)/=0) write(*,*)'dkmxhf : uneven no. of negative pivots',& & ' - log determinant not correct !' end if return ! matrix not of full rank, return generalised inverse 11 nrank=ii-1; ij=0 do i=1,N if(iflag(i) == 0)then ! ... zero out row/column w(i)=0.d0 do j=i,n ij=ij+1; a(ij)=0.d0 end do else ij=ij+1; ww=-w(i); w(i)=ww; a(ij)=ww do j=i+1,n ij=ij+1 if(iflag(j).ne.0)then a(ij)=-a(ij) else a(ij)=0.d0 end if end do end if end do if(iopt) write(*,'(a,i5,a,i5)')'Generalised inverse of matrix with order =', & & n,' and rank =',nrank go to 300 end subroutine dkmxhf