c     ..................................................................
c
c        subroutine dsinv
c
c        purpose
c           invert a given symmetric positive definite matrix
c
c        usage
c           call dsinv(a,n,eps,ier)
c
c        description of parameters
c           a      - double precision upper triangular part of given
c                    symmetric positive definite n by n coefficient
c                    matrix.
c                    on return a contains the resultant upper
c                    triangular matrix in double precision.
c           n      - the number of rows (columns) in given matrix.
c           eps    - single precision input constant which is used
c                    as relative tolerance for test on loss of
c                    significance.
c           ier    - resulting error parameter coded as follows
c                    ier=0  - no error
c                    ier=-1 - no result because of wrong input parame-
c                             ter n or because some radicand is non-
c                             positive (matrix a is not positive
c                             definite, possibly due to loss of signi-
c                             ficance)
c                    ier=k  - warning which indicates loss of signifi-
c                             cance. the radicand formed at factoriza-
c                             tion step k+1 was still positive but no
c                             longer greater than abs(eps*a(k+1,k+1)).
c
c        remarks
c           the upper triangular part of given matrix is assumed to be
c           stored columnwise in n*(n+1)/2 successive storage locations.
c           in the same storage locations the resulting upper triangu-
c           lar matrix is stored columnwise too.
c           the procedure gives results if n is greater than 0 and all
c           calculated radicands are positive.
c
c        subroutines and function subprograms required
c           dmfsd
c
c        method
c           solution is done using factorization by subroutine dmfsd.
c
c     ..................................................................
c
      subroutine dsinv (a,n,eps,ier)
c
      dimension a(1)
      double precision a, din, work
c
c        factorize given matrix by means of subroutine dmfsd
c        a = transpose(t) * t
      call dmfsd (a,n,eps,ier)
      if (ier) 90,10,10
c
c        invert upper triangular matrix t
c        prepare inversion-loop
   10 ipiv=n*(n+1)/2
      ind=ipiv
c
c        initialize inversion-loop
      do 60 i=1,n
      din=1.d0/a(ipiv)
      a(ipiv)=din
      min=n
      kend=i-1
      lanf=n-kend
      if (kend) 50,50,20
   20 j=ind
c
c        initialize row-loop
      do 40 k=1,kend
      work=0.d0
      min=min-1
      lhor=ipiv
      lver=j
c
c        start inner loop
      do 30 l=lanf,min
      lver=lver+1
      lhor=lhor+l
   30 work=work+a(lver)*a(lhor)
c        end of inner loop
c
      a(j)=-work*din
   40 j=j-min
c        end of row-loop
c
   50 ipiv=ipiv-min
   60 ind=ind-1
c        end of inversion-loop
c
c        calculate inverse(a) by means of inverse(t)
c        inverse(a) = inverse(t) * transpose(inverse(t))
c        initialize multiplication-loop
      do 80 i=1,n
      ipiv=ipiv+i
      j=ipiv
c
c        initialize row-loop
      do 80 k=i,n
      work=0.d0
      lhor=j
c
c        start inner loop
      do 70 l=k,n
      lver=lhor+k-i
      work=work+a(lhor)*a(lver)
   70 lhor=lhor+l
c        end of inner loop
c
      a(j)=work
   80 j=j+k
c        end of row- and multiplication-loop
c
   90 return
      end
