

*     Matrix subprograms
*
*     The subprograms are in alphabetical order, with the exception:
*      DOUBLE PRECISION subprograms are immediately behind the single
*      precision version
*
*     GMAB       product of general matrices
*        DGMAB   ...
*     GMPR       print general matrix
*     GMTR       transpose general matrix
*     SMAVA      product of general and symmetric matrix AVAT
*        DSMAVA   ... (error propagation)
*     SMHHL      Householder transformation
*        DSMHHL  ...
*     SMINV      symmetric matrix inversion and solution of equations
*        DSMINV  ...
*     SMTOG      convert symmetric to general matrix
*     SMPR       print symmetric matrix
*     SMPRV      print (symmetric) covariance matrix and vector
*        DSMPRV  ...
*     SMTOS      copy (part of) symmetric matrix to symmetric matrix
*     SMQU       square of symmetric matrix 
*     SMVA       product of symmetric and general matrix
*        DSMVA   ...
*     SOLVA      solution of symmetric matrix equation 
*     SOLVB      second part of solution ...
*        DSOLVA  ...
*        DSOLVB  ...
*     TQHHL      utility routine for SMHHL
*        DTQHHL  ...
*     VXY        scalar product of two vectors 
*

      SUBROUTINE GMAB(A,B,C,N,M,L)
*     Multiply general n-by-m matrix and general m-by-l matrix  to  form
*     general n-by-l matrix
*
*                  - -   - - -
*        CALL GMAB(A,B,C,N,M,L)         C  :=    A   *    B
*                      -               N*L      N*M      M*L
*
*
      REAL A(1),B(1),C(1)
      DOUBLE PRECISION SUM
*     ...
      IJ=0
      IK=0
      DO K=1,N
       DO I=1,L
        JK=I
        SUM=0.0
        DO J=1,M
         SUM=SUM+A(IJ+J)*B(JK)
         JK=JK+L
        END DO
        IK=IK+1
        C(IK)=SUM
       END DO
       IJ=IJ+M
      END DO
      END

      SUBROUTINE DGMAB(A,B,C,N,M,L)
*     Multiply general n-by-m matrix and general m-by-l matrix  to  form
*     general n-by-l matrix
*
*                   - -   - - -
*        CALL DGMAB(A,B,C,N,M,L)         C  :=    A   *    B
*                       -               N*L      N*M      M*L
*
*
      DOUBLE PRECISION A,B,C 
      DIMENSION A(*),B(*),C(*)
      DOUBLE PRECISION SUM
*     ...
      IJ=0
      IK=0
      DO K=1,N
       DO I=1,L
        JK=I
        SUM=0.0
        DO J=1,M
         SUM=SUM+A(IJ+J)*B(JK)
         JK=JK+L
        END DO
        IK=IK+1
        C(IK)=SUM
       END DO
       IJ=IJ+M
      END DO
      END

      SUBROUTINE GMPR(A,N,M,TEXT)
*     prints the N-by-M general matrix A
*                  - - - ----
*        CALL GMPR(A,N,M,TEXT)
*
      REAL A(*)
      CHARACTER*(*) TEXT
*
*     general matrix or vector
*
*     ...
      IF(N.EQ.1.OR.M.EQ.1) THEN
*        special case of vector
         WRITE(*,101) N,M,TEXT
         WRITE(*,102) (A(L),L=1,N*M)
      ELSE 
*        matrix
         WRITE(*,103) N,M,TEXT
         IJ=0
         DO I=1,N
          WRITE(*,104) I,(A(IJ+L),L=1,M)
          IJ=IJ+M
         END DO
      END IF
      WRITE(*,102)
  100 RETURN
  101 FORMAT(1X,I4,' *',I3,'  Vector ',A/)
  102 FORMAT(10X,10G12.5)
  103 FORMAT(1X,I4,' *',I3,'  Matrix ',A/)
  104 FORMAT(1X,I4,5X,10G12.5/(10X,10G12.5/))
      END

      SUBROUTINE GMTR(A,B,N,M)
*     Transpose N-by-M matrix A --> B
*
      REAL A(M,N),B(N,M)
      DO I=1,N
       DO J=1,M
        B(I,J)=A(J,I)
       END DO
      END DO
      END

      SUBROUTINE SMAVA(V,A,W,N,M)
*     Multiply symmetric N-by-N matrix from the left with general M-by-N
*     matrix and from the right with the transposed of the same  general
*     matrix  to  form  symmetric  M-by-M   matrix   (used   for   error
*     propagation).
*                   - -   - -
*        CALL SMAVA(V,A,W,N,M)
*                       -
*                                  T
*         W   =   A   *   V   *   A
*        M*M     M*N     N*N     N*M
*
*
*        where V = symmetric N-by-N matrix
*              A = general N-by-M matrix
*              W = symmetric M-by-M matrix
*
      REAL V(1),A(1),W(1)
      DOUBLE PRECISION CIK
*     ...
      DO I=1,(M*M+M)/2
       W(I)=0.0
      END DO
*
      IL=-N
      IJS=0
      DO I=1,M
       IJS=IJS+I-1
       IL=IL+N
       LKL=0
       DO K=1,N
        CIK=0.0
        LKL=LKL+K-1
        LK=LKL
        DO L=1,K
         LK=LK+1
         CIK=CIK+A(IL+L)*V(LK)
        END DO
        DO L=K+1,N
         LK=LK+L-1
         CIK=CIK+A(IL+L)*V(LK)
        END DO
        JK=K
        IJ=IJS
        DO J=1,I
         IJ=IJ+1
         W(IJ)=W(IJ)+CIK*A(JK)
         JK=JK+N
        END DO 
       END DO
      END DO  
      END

      SUBROUTINE DSMAVA(V,A,W,N,M)
*     Multiply symmetric N-by-N matrix from the left with general M-by-N
*     matrix and from the right with the transposed of the same  general
*     matrix  to  form  symmetric  M-by-M   matrix   (used   for   error
*     propagation).
*
*                    - -   - -
*        CALL DSMAVA(V,A,W,N,M)
*                        -
*                                  T
*         W   =   A   *   V   *   A
*        M*M     M*N     N*N     N*M
*
*
*        where V = symmetric N-by-N matrix
*              A = general N-by-M matrix
*              W = symmetric M-by-M matrix
*
      DOUBLE PRECISION V,A,W
      DIMENSION V(*),A(*),W(*)
      DOUBLE PRECISION CIK
*     ...
      DO I=1,(M*M+M)/2
       W(I)=0.0
      END DO
*
      IL=-N
      IJS=0
      DO I=1,M
       IJS=IJS+I-1
       IL=IL+N
       LKL=0
       DO K=1,N
        CIK=0.0
        LKL=LKL+K-1
        LK=LKL
        DO L=1,K
         LK=LK+1
         CIK=CIK+A(IL+L)*V(LK)
        END DO
        DO L=K+1,N
         LK=LK+L-1
         CIK=CIK+A(IL+L)*V(LK)
        END DO
        JK=K
        IJ=IJS
        DO J=1,I
         IJ=IJ+1
         W(IJ)=W(IJ)+CIK*A(JK)
         JK=JK+N
        END DO 
       END DO
      END DO  
      END

      SUBROUTINE SMHHL(V,N,D,U,IDIR)
*     Determination  of  eigenvalues  and  eigenvectors  by  Householder
*     method
*                 - -     ----
*     CALL SMHHL(V,N,D,U,IDIR)
*                     - -
*     Method:
*     Reduce symmetric matrix V to tridiagonal  form  using  Householder
*     transformations, and, by  call  to  TQHHL,  diagonalization   of
*     tridiagonal matrix
*        D(I)   = diagonal elements
*        U(I,J) = transformations matrix
*        IDIR   <  0  means eigenvalues in decreasing order
*        IDIR   >= 0  means eigenvalues in increasing order
*
*
*     SMHHL uses a work array of N words in COMMON/MATCOM/. For N > 400
*     the user has to define COMMON/MATCOM/ with N words.
*
*     Subroutine called: TQHHL
*
      REAL V(1),D(1),U(N,N),TOL/1.0E-15/
      COMMON/MATCOM/E(400)
*     ...
      IJ=0
      DO I=1,N
       DO J=1,I
        IJ=IJ+1
        U(I,J)=V(IJ)
        V(IJ)=0.0
       END DO
      END DO
*
      DO II=2,N
       I=N+2-II
       L=I-2
       F=U(I,I-1)
       G=0.0
       IF(L.NE.0) THEN
          DO K=1,L
           IF(ABS(U(I,K)).GT.TOL) G=G+U(I,K)*U(I,K)
          END DO
          H=G+F*F
       END IF
*
*     If  G  too  small  for  orthogonality  to   be   guaranteed,   the
*     transformation is skipped
*
       IF(G.LT.TOL) THEN
          E(I)=F
          H   =0.0
       ELSE
          L=L+1
          SH=SQRT(H)
          IF(F.GE.0.0) SH=-SH
          G=SH
          E(I)=SH
          H=H-F*G
          U(I,I-1)=F-G
          F=0.0
*
          DO J=1,L
           U(J,I)=U(I,J)/H
           G=0.0
*          form element of a u
           DO K=1,J
            IF(ABS(U(J,K)).GT.TOL.AND.ABS(U(I,K)).GT.TOL) THEN
               G=G+U(J,K)*U(I,K)
            END IF 
           END DO
           J1=J+1
           DO K=J1,L
            IF(ABS(U(K,J)).GT.TOL.AND.ABS(U(I,K)).GT.TOL) THEN
               G=G+U(K,J)*U(I,K)
            END IF
           END DO
           E(J)=G/H
           F=F+G*U(J,I)
          END DO
*         form k
          HH=F/(H+H)
*         form reduced a
          DO J=1,L
           F=U(I,J)
           E(J)=E(J)-HH*F
           G=E(J)
           DO K=1,J
            U(J,K)=U(J,K)-F*E(K)-G*U(I,K)
           END DO
          END DO
       END IF
       D(I)=H
      END DO
*
      D(1)=0.0
      E(1)=0.0

*     accumulation of transformation matrices
      DO I=1,N
       L=I-1
       IF(D(I).NE.0.0) THEN
          DO J=1,L
           G=0.0
           DO K=1,L
            G=G+U(I,K)*U(K,J)
           END DO
           DO K=1,L
            U(K,J)=U(K,J)-G*U(K,I)
           END DO
          END DO
       END IF
       D(I)=U(I,I)
       U(I,I)=1.0
       DO J=1,L
        U(I,J)=0.0
        U(J,I)=0.0
       END DO
      END DO
      CALL TQHHL(N,D,E,U,IDIR)
      END

      SUBROUTINE DSMHHL(V,N,D,U,IDIR)
*     Determination  of  eigenvalues  and  eigenvectors  by  Householder
*     method
*                 - -     ----
*     CALL DSMHHL(V,N,D,U,IDIR)
*                     - -
*     Method:
*     Reduce symmetric matrix V to tridiagonal  form  using  Householder
*     transformations, and, by  call  to  TQHHL,  diagonalization   of
*     tridiagonal matrix
*        D(I)   = diagonal elements
*        U(I,J) = transformations matrix
*        IDIR   <  0  means eigenvalues in decreasing order
*        IDIR   >= 0  means eigenvalues in increasing order
*
*
*     SMHHL uses a work array of N words in COMMON/MATCOM/. For N > 400
*     the user has to define COMMON/MATCOM/ with N words.
*
*     Subroutine called: DTQHHL

*
      DOUBLE PRECISION V(1),D(1),U(N,N),TOL,E
      COMMON/MATCOM/E(400)
      DATA TOL/1.0D-30/
*     ...
      IJ=0
      DO I=1,N
       DO J=1,I
        IJ=IJ+1
        U(I,J)=V(IJ)
        V(IJ)=0.0
       END DO
      END DO
*
      DO II=2,N
       I=N+2-II
       L=I-2
       F=U(I,I-1)
       G=0.0
       IF(L.NE.0) THEN
          DO K=1,L
           G=G+U(I,K)*U(I,K)
          END DO
          H=G+F*F
       END IF
*
*     If  G  too  small  for  orthogonality  to   be   guaranteed,   the
*     transformation is skipped
*
       IF(G.LT.TOL) THEN
          E(I)=F
          H   =0.0
       ELSE
          L=L+1
          SH=SQRT(H)
          IF(F.GE.0.0) SH=-SH
          G=SH
          E(I)=SH
          H=H-F*G
          U(I,I-1)=F-G
          F=0.0
*
          DO J=1,L
           U(J,I)=U(I,J)/H
           G=0.0
*          form element of a u
           DO K=1,J
            G=G+U(J,K)*U(I,K)
           END DO
           J1=J+1
           DO K=J1,L
            G=G+U(K,J)*U(I,K)
           END DO
           E(J)=G/H
           F=F+G*U(J,I)
          END DO
*         form k
          HH=F/(H+H)
*         form reduced a
          DO J=1,L
           F=U(I,J)
           E(J)=E(J)-HH*F
           G=E(J)
           DO K=1,J
            U(J,K)=U(J,K)-F*E(K)-G*U(I,K)
           END DO
          END DO
       END IF
       D(I)=H
      END DO
*
      D(1)=0.0
      E(1)=0.0

*     accumulation of transformation matrices

      DO I=1,N
       L=I-1
       IF(D(I).NE.0.0) THEN
          DO J=1,L
           G=0.0
           DO K=1,L
            G=G+U(I,K)*U(K,J)
           END DO
           DO K=1,L
            U(K,J)=U(K,J)-G*U(K,I)
           END DO
          END DO
       END IF
       D(I)=U(I,I)
       U(I,I)=1.0
       DO J=1,L
        U(I,J)=0.0
        U(J,I)=0.0
       END DO
      END DO
      CALL DTQHHL(N,D,E,U,IDIR)
      END

      SUBROUTINE SMINV(V,B,NARG,M,NRANK)
*     Obtain solution of a system of linear equations V *  X  =  B  with
*     symmetric matrix V and inverse (for M =  1)  or  matrix  inversion
*     only (for M = 0).
*
*                   - - - -
*        CALL SMINV(V,B,N,M,NRANK)
*                   - -     -----
*
*           V = symmetric N-by-N matrix in symmetric storage mode
*               V(1) = V11, V(2) = V12, V(3) = V22, V(4) = V13, . . .
*               replaced by inverse matrix
*           B = N-vector   (for M = 0 use a dummy argument)
*               replaced by solution vector
*           M = see above
*
*
*     Method of solution is by elimination selecting the  pivot  on  the
*     diagonal each stage. The rank of the matrix is returned in  NRANK.
*     For NRANK ne N, all remaining  rows  and  cols  of  the  resulting
*     matrix V and the corresponding elements of  B  are  set  to  zero.
*     SMINV can be used for a dimension up to 100 (see INVCDR).
*
      REAL V(*),B(*),VKK,D,E
      COMMON/INVCDR/DR(2,100)
      DATA EPS/1.E-6/
*
*     construct table
*
      N=IABS(NARG)
      IF(NARG.GT.0) THEN
*        reset flags
         DO I=1,N
          DR(1,I)=1.0
         END DO 
         NI=N
      ELSE
*        call with negative N - matrix partially inverted
         NI=0
         DO I=1,N
          IF(DR(1,I).NE.0.0) NI=NI+1
         END DO
      END IF
      II=0
      DO I=1,N
       II=II+I
       DR(2,I)=ABS(V(II))
      END DO 
*     loop begin, with loop on all remaining rows/cols
      NRANK=N-NI
      DO I=1,NI
*      search for pivot and test for linearity and zero matrix
       K=0
       JJ=0
       KK=0
       VKK=0.0
       DO J=1,N
        JJ=JJ+J
        IF(DR(1,J).NE.0.0) THEN
           IF(ABS(V(JJ)).GT.VKK.AND.ABS(V(JJ)).GT.EPS*DR(2,J)) THEN
              VKK=ABS(V(JJ))
              K=J
              KK=JJ
           END IF   
        END IF
       END DO
c       if(k.ne.0) then
c       write(*,*) 'sminv',i,k,vkk,dr(2,k)
c       end if 
       IF(K.EQ.0.OR.VKK.LT.1.0E-16) THEN
*         no pivot found, clear of matrix
          IJ=0
          DO III=1,N
           IF(M.EQ.1.AND.DR(1,III).NE.0.0) B(III)=0.0
           DO J=1,III
            IJ=IJ+1
            IF(DR(1,III)+DR(1,J).NE.0.0) V(IJ)=0.0
            V(IJ)=-V(IJ)
           END DO 
          END DO
          GOTO 100
       END IF
*      preparation for elimination
       NRANK=NRANK+1
       DR(1,K)=0.0
       D=1.0/V(KK)
       IF(ABS(D).LT.1.0E-16) D=0.0
       V(KK)=-D
       IF(M.EQ.1) B(K)=B(K)*D
c       write(*,*) '      d and Bk ',D,B(K) 
       JK=KK-K
       JL=0
*      elimination 
       DO J=1,N
        IF(J.EQ.K) THEN
           JK=KK
           JL=JL+J
        ELSE
           IF(J.LT.K) THEN
              JK=JK+1
           ELSE
              JK=JK+J-1
           END IF
           E    =V(JK)
c           write(*,*) 'factor e',e,d 
           IF(ABS(E).LT.1.0E-16) E=0.0
           
           V(JK)=D*E
           IF(M.EQ.1) B(J) =B(J)-B(K)*E
           LK   =KK-K
           DO L=1,J
            JL=JL+1
            IF(L.EQ.K) THEN
               LK=KK
            ELSE
               IF(L.LT.K) THEN
                  LK=LK+1
               ELSE
                  LK=LK+L-1
               END IF
               V(JL)=V(JL)-V(LK)*E
            END IF
           END DO 
        END IF
       END DO 
      END DO 
*     change sign
      IJ=0
      DO I=1,N
       DO J=1,I
        IJ=IJ+1
        V(IJ)=-V(IJ)
       END DO
      END DO
  100 RETURN
      END

      SUBROUTINE DSMINV(V,B,NARG,M,NRANK)
*     Obtain solution of a system of linear equations V *  X  =  B  with
*     symmetric matrix V and inverse (for M =  1)  or  matrix  inversion
*     only (for M = 0).
*
*                   - - - -
*        CALL SMINV(V,B,N,M,NRANK)
*                   - -     -----
*
*           V = symmetric N-by-N matrix in symmetric storage mode
*               V(1) = V11, V(2) = V12, V(3) = V22, V(4) = V13, . . .
*               replaced by inverse matrix
*           B = N-vector   (for M = 0 use a dummy argument)
*               replaced by solution vector
*           M = see above
*
*
*     Method of solution is by elimination selecting the  pivot  on  the
*     diagonal each stage. The rank of the matrix is returned in  NRANK.
*     For NRANK ne N, all remaining  rows  and  cols  of  the  resulting
*     matrix V and the corresponding elements of  B  are  set  to  zero.
*     SMINV can be used for a dimension up to 100 (see INVCDR).
*
      DOUBLE PRECISION V,B,VKK,D,E,EPS
      DIMENSION V(*),B(*)
      COMMON/INVCDR/DR(2,512)
      DATA EPS/1.D-6/
*
*     construct table
*
      N=IABS(NARG)
      IF(NARG.GT.0) THEN
*        reset flags
         DO I=1,N
          DR(1,I)=1.0
         END DO 
         NI=N
      ELSE
*        call with negative N - matrix partially inverted
         NI=0
         DO I=1,N
          IF(DR(1,I).NE.0.0) NI=NI+1
         END DO
      END IF
      II=0
      DO I=1,N
       II=II+I
       DR(2,I)=ABS(V(II))
      END DO 
*     loop begin, with loop on all remaining rows/cols
      NRANK=N-NI
      DO I=1,NI
*      search for pivot and test for linearity and zero matrix
       K=0
       JJ=0
       KK=0
       VKK=0.0
       DO J=1,N
        JJ=JJ+J
        IF(DR(1,J).NE.0.0) THEN
           IF(ABS(V(JJ)).GT.VKK.AND.ABS(V(JJ)).GT.EPS*DR(2,J)) THEN
              VKK=ABS(V(JJ))
              K=J
              KK=JJ
           END IF   
        END IF
       END DO
       IF(K.EQ.0) THEN
*         no pivot found, clear of matrix
          IJ=0
          DO III=1,N
           IF(M.EQ.1.AND.DR(1,III).NE.0.0) B(III)=0.0
           DO J=1,III
            IJ=IJ+1
            IF(DR(1,III)+DR(1,J).NE.0.0) V(IJ)=0.0
            V(IJ)=-V(IJ)
           END DO 
          END DO
          GOTO 100
       END IF
*      preparation for elimination
       NRANK=NRANK+1
       DR(1,K)=0.0
       D=1.0/V(KK)
       V(KK)=-D
       IF(M.EQ.1) B(K)=B(K)*D
       JK=KK-K
       JL=0
*      elimination 
       DO J=1,N
        IF(J.EQ.K) THEN
           JK=KK
           JL=JL+J
        ELSE
           IF(J.LT.K) THEN
              JK=JK+1
           ELSE
              JK=JK+J-1
           END IF
           E    =V(JK)
           V(JK)=D*E
           IF(M.EQ.1) B(J) =B(J)-B(K)*E
           LK   =KK-K
           DO L=1,J
            JL=JL+1
            IF(L.EQ.K) THEN
               LK=KK
            ELSE
               IF(L.LT.K) THEN
                  LK=LK+1
               ELSE
                  LK=LK+L-1
               END IF
               V(JL)=V(JL)-V(LK)*E
            END IF
           END DO 
        END IF
       END DO 
      END DO 
*     change sign
      IJ=0
      DO I=1,N
       DO J=1,I
        IJ=IJ+1
        V(IJ)=-V(IJ)
       END DO
      END DO
  100 RETURN
      END

      SUBROUTINE SMTOG(V,A,N)
*
*     copy symmetric n-by-n matrix V to general n-by-n matrix A 
*
*                   -   -
*        CALL SMTOG(V,A,N)        A := V
*                     -
      REAL V(1),A(1)
*     ...         
      IJV=0
      DO I=1,N
       IJA=I
       DO J=1,I
        IJV=IJV+1
        A(IJA)=V(IJV)
        A(IJA+(N-1)*(I-J))=V(IJV)
        IJA=IJA+N
       END DO
      END DO
      END 

      SUBROUTINE SMPR(V,N,TEXT)
*     prints the symmetric n-by-n matrix v
*                       ----
*        CALL SMPRT(V,N,TEXT)
*
      REAL V(*)
      CHARACTER*(*) TEXT
*     ...
      WRITE(*,101) N,N,TEXT
      IF(N.LE.0) GOTO 100
      II=0
      DO I=1,N
       WRITE(*,102) I,(V(II+J),J=1,I)
       II=II+I
      END DO
      WRITE(*,102)
  100 RETURN
  101 FORMAT(1X,I4,' by',I3,' symmetric matrix ',A/)
  102 FORMAT(1X,I4,5X,10G12.5/(10X,10G12.5/))
      END

      SUBROUTINE SMPRV(X,V,N)
*     Prints the n-vector X and the symmetric N-by-N  covariance  matrix
*     V, the latter as a correlation matrix.
*
*                    - - -
*        CALL SMPRTC(X,V,N)     X = vector of parameters
*                               V = covariance matrix
*
      REAL X(*),V(*)
      INTEGER MC(15)
*
      WRITE(*,103)
      WRITE(*,101)
      II=0
      DO I=1,N
       IJ=II
       II=II+I
       ERR=0.0
       IF(V(II).GT.0.0) ERR=SQRT(V(II))
       L=0
       JJ=0
       DO J=1,I
        JJ=JJ+J
        IJ=IJ+1
        RHO=0.0
        PD=V(II)*V(JJ)
        IF(PD.GT.0.0) RHO=V(IJ)/SQRT(PD)
        L=L+1
        MC(L)=100.0*ABS(RHO)+0.5
        IF(RHO.LT.0.0) MC(L)=-MC(L)
        IF(J.EQ.I.OR.L.EQ.15) THEN
           IF(J.LE.15) THEN
              IF(J.EQ.I) THEN
                 WRITE(*,102) I,X(I),ERR,(MC(M),M=1,L-1)
              ELSE
                 WRITE(*,102) I,X(I),ERR,(MC(M),M=1,L)
              END IF
           ELSE
              IF(J.EQ.I) THEN
                 WRITE(*,103) (MC(M),M=1,L-1)
              ELSE
                 WRITE(*,103) (MC(M),M=1,L)
              END IF
              L=0
           END IF
        END IF
       END DO
      END DO
      WRITE(*,104)
  100 RETURN
  101 FORMAT(9X,'Param',7X,'error',7X,'correlation coefficients'/)
  102 FORMAT(1X,I5,2G12.4,1X,15I5)
  103 FORMAT(31X,15I5)
  104 FORMAT(33X,'(correlation coefficients in percent)')
      END

      SUBROUTINE DSMPRV(X,V,N)
*     Prints the n-vector X and the symmetric N-by-N  covariance  matrix
*     V, the latter as a correlation matrix.
*
*                    - - -
*        CALL DPRPAC(X,V,N)     X = vector of parameters
*                               V = covariance matrix
*
      DOUBLE PRECISION X,V
      DIMENSION X(*),V(*)
      INTEGER MC(15)
*
      WRITE(*,103)
      WRITE(*,101)
      II=0
      DO I=1,N
       IJ=II
       II=II+I
       ERR=0.0
       IF(V(II).GT.0.0) ERR=SQRT(V(II))
       L=0
       JJ=0
       DO J=1,I
        JJ=JJ+J
        IJ=IJ+1
        RHO=0.0
        PD=V(II)*V(JJ)
        IF(PD.GT.0.0) RHO=V(IJ)/SQRT(PD)
        L=L+1
        MC(L)=100.0*ABS(RHO)+0.5
        IF(RHO.LT.0.0) MC(L)=-MC(L)
        IF(J.EQ.I.OR.L.EQ.15) THEN
           IF(J.LE.15) THEN
              IF(J.EQ.I) THEN
                 WRITE(*,102) I,X(I),ERR,(MC(M),M=1,L-1)
              ELSE
                 WRITE(*,102) I,X(I),ERR,(MC(M),M=1,L)
              END IF
           ELSE
              IF(J.EQ.I) THEN
                 WRITE(*,103) (MC(M),M=1,L-1)
              ELSE
                 WRITE(*,103) (MC(M),M=1,L)
              END IF
              L=0
           END IF
        END IF
       END DO
      END DO
      WRITE(*,104)
  100 RETURN
  101 FORMAT(9X,'Param',7X,'error',7X,'correlation coefficients'/)
  102 FORMAT(1X,I5,2G12.4,1X,15I5)
  103 FORMAT(31X,15I5)
  104 FORMAT(33X,'(correlation coefficients in percent)')
      END

      SUBROUTINE SMTOS(V,I,W,J,N)
*     Copy symmetric N-by-N matrix or a N-by-N submatrix of a  symmetric
*     matrix to another symmetric matrix
*
*                     - -     -
*          CALL SMTOS(V,I,W,J,N)
*                         - -
*
*     N rows and columns of the matrix V, starting from diagonal element
*     (i,i), are copied to the matrix W, starting  in  diagonal  element
*     (j,j). thus if a complete symmetric matrix has to be copied, i=j=1
*     has to be used.
*    
      REAL V(*),W(*)
*     ...
      IM=(I*I+I)/2-1
      JM=(J*J+J)/2-1
      DO K=1,N
       DO L=1,K
        IM=IM+1
        JM=JM+1
        W(JM)=V(IM)
       END DO
       IM=IM+I-1
       JM=JM+J-1
      END DO 
      END

      SUBROUTINE SMQU(V,VQ,N)
*     calculate square of symmetric matrix V:   VQ:= V * V
*
      REAL V(1),VQ(1)
      DOUBLE PRECISION SUM
*     ...
      IJ=0
      DO I=1,N
       DO J=1,I
        IJ=IJ+1
        SUM=0.0
        IK=(I*I-I)/2
        JK=(J*J-J)/2
        DO K=1,N
         IF(K.LE.I) IK=IK+1
         IF(K.LE.J) JK=JK+1
         SUM=SUM+V(IK)*V(JK)
         IF(K.GE.I) IK=IK+K
         IF(K.GE.J) JK=JK+K
        END DO
        VQ(IJ)=SUM
       END DO
      END DO
      END

      SUBROUTINE SMVA(V,A,B,N,M)
*     multiply symmetric N-by-N matrix and general N-by-M matrix
*
*                  - -   - -
*        CALL SMVA(V,A,B,N,M)
*                      -
*
*         B   :=    V   *    A
*        N*M       N*N      N*M
*
      REAL V(1),A(1),B(1)
      DOUBLE PRECISION SUM
      IJS=1
      IKB=0
      DO I=1,N
       DO K=1,M
        SUM=0.0
        IJ=IJS
        JK=K
        DO J=1,N
         SUM=SUM+V(IJ)*A(JK)
         IF(J.LT.I) THEN
            IJ=IJ+1
         ELSE 
            IJ=IJ+J
         END IF 
         JK=JK+M
        END DO 
        IKB=IKB+1
        B(IKB)=SUM
       END DO 
       IJS=IJS+I
      END DO 
      END

      SUBROUTINE DSMVA(V,A,B,N,M)
*     multiply symmetric N-by-N matrix and general N-by-M matrix
*
*                   - -   - -
*        CALL DSMVA(V,A,B,N,M)
*                       -
*
*         B   :=    V   *    A
*        N*M       N*N      N*M
*
      DOUBLE PRECISION V,A,B
      DIMENSION V(*),A(*),B(*)
      DOUBLE PRECISION SUM
      IJS=1
      IKB=0
      DO I=1,N
       DO K=1,M
        SUM=0.0
        IJ=IJS
        JK=K
        DO J=1,N
         SUM=SUM+V(IJ)*A(JK)
         IF(J.LT.I) THEN
            IJ=IJ+1
         ELSE 
            IJ=IJ+J
         END IF 
         JK=JK+M
        END DO 
        IKB=IKB+1
        B(IKB)=SUM
       END DO 
       IJS=IJS+I
      END DO 
      END

      SUBROUTINE SOLVA(V,R,N,U,D)
*     solve ill-conditioned linear system of equations V X = R
*     
*     CALL SOLVA(V,R,N,U,D)
*
*     define positive limit DLIM for eigenvalues
*     DO I=1,N
*      IF(D(I).GT.DLIM) THEN
*         D(I)=1.0/D(I)
*      ELSE
*         D(I)=0.0
*      END IF
*     END DO
*     CALL SOLVB(V,R,N,U,D) 
*
      REAL V(*),R(*),U(N,N),D(*)
*     ...
*     transformation to diagonal matrix ... 
      CALL SMHHL(V,N,D,U,-1)   
*     with eigenvalues D in descending order
      END 

      SUBROUTINE SOLVB(V,R,N,U,D,DLIM)
*     ... see SOLVA 
      REAL V(*),R(*),U(N,N),D(*)
      DOUBLE PRECISION SUM 
*     ...   
      DO I=1,N
       IF(D(I).GT.ABS(DLIM)) THEN
          D(I)=1.0/D(I)
       ELSE
          D(I)=0.0
       END IF
      END DO 
*     inverse matrix V by product UT D U      
      IK=0 
      DO I=1,N
       DO K=1,I
        SUM=0.0
        DO J=1,N
         SUM=SUM+U(I,J)*D(J)*U(K,J)
        END DO
        IK=IK+1
        V(IK)=SUM
       END DO
      END DO 
*     copy R to D        
      DO I=1,N
       D(I)=R(I)
      END DO 
*     solution by product V R => R
      II=0 
      DO I=1,N
       SUM=0.0
       IJ=II
       DO J=1,N
        IF(J.LE.I) IJ=IJ+1 
        SUM=SUM+D(J)*V(IJ)
        IF(J.GE.I) IJ=IJ+J
       END DO
       R(I)=SUM
       II=II+I
      END DO
      END 

      SUBROUTINE DSOLVA(V,R,N,U,D)
*     solve ill-conditioned linear system of equations V X = R
*     
*     CALL DSOLVA(V,R,N,U,D)
*
*     define positive limit DLIM for eigenvalues
*     CALL DSOLVB(V,R,N,U,D,DLIM) 
*
      DOUBLE PRECISION V(*),R(*),U(N,N),D(*)
*     ...
*     transformation to diagonal matrix ... 
      CALL DSMHHL(V,N,D,U,-1)   
*     with eigenvalues D in descending order
      END 

      SUBROUTINE DSOLVB(V,R,N,U,D,DLIM)
*     .. see DSOLVA 
      DOUBLE PRECISION V(*),R(*),U(N,N),D(*),DLIM
      DOUBLE PRECISION SUM 
*     ...   
      DO I=1,N
       IF(D(I).GT.ABS(DLIM)) THEN
          D(I)=1.0/D(I)
       ELSE
          D(I)=0.0
       END IF
      END DO 
*     inverse matrix V by product UT D U      
      IK=0 
      DO I=1,N
       DO K=1,I
        SUM=0.0
        DO J=1,N
         SUM=SUM+U(I,J)*D(J)*U(K,J)
        END DO
        IK=IK+1
        V(IK)=SUM
       END DO
      END DO 
*     copy R to D        
      DO I=1,N
       D(I)=R(I)
      END DO 
*     solution by product V R => R
      II=0 
      DO I=1,N
       SUM=0.0
       IJ=II
       DO J=1,N
        IF(J.LE.I) IJ=IJ+1 
        SUM=SUM+D(J)*V(IJ)
        IF(J.GE.I) IJ=IJ+J
       END DO
       R(I)=SUM
       II=II+I
      END DO
      END 

      SUBROUTINE TQHHL(N,D,E,U,IDIR)
*     Auxiliary routine for SMHHL
*
      REAL D(1),E(1),U(N,N)
      DATA EPS/1.0E-6/
*     ...
      IF(IDIR.GE.0) THEN
*        increasing order of eigenvalues
         IREV=1
      ELSE
*        decreasing order of eigenvalues
         IREV=0
      END IF
      DO I=2,N
       E(I-1)=E(I)
      END DO
      E(N)=0.0
      B=0.0
      F=0.0
*
      DO 60 L=1,N
      J=0
      H=EPS*(ABS(D(L))+ABS(E(L)))
      IF(B.LT.H) B=H
*
*     look for small sub-diagonal element
*
      DO M=L,N
       IF(ABS(E(M)).LE.B) GOTO 25
      END DO
      M=L
   25 IF(M.EQ.L) GOTO 59
*
*     next iteration
*
   30 IF(J.EQ.30) GOTO 100
      J=J+1
      G=D(L)
      P=(D(L+1)-G)/(2.0*E(L))
      R=SQRT(1.0+P*P)
      D(L)=E(L)
      IF(P.LT.0.0) D(L)=D(L)/(P-R)
      IF(P.GE.0.0) D(L)=D(L)/(P+R)
      H=G-D(L)
      DO I=L+1,N
       D(I)=D(I)-H
      END DO
      F=F+H
*     QL transformation
      P=D(M)
      C=1.0
      S=0.0
      M1=M-1
      DO 50 II=L,M1
      I=M1+L-II
      G=C*E(I)
      H=C*P
      IF(ABS(P).GE.ABS(E(I))) THEN
         C=E(I)/P
         R=SQRT(1.0+C*C)
         E(I+1)=S*P*R
         S=C/R
         C=1.0/R
      ELSE
         C=P/E(I)
         R=SQRT(1.0+C*C)
         E(I+1)=S*E(I)*R
         S=1.0/R
         C=C/R
      END IF
      P=C*D(I)-S*G
      D(I+1)=H+S*(C*G+S*D(I))
*     form vector
      DO K=1,N
       H=U(K,I+1)
       U(K,I+1)=S*U(K,I)+C*H
       U(K,I)=C*U(K,I)-S*H
      END DO
   50 CONTINUE
      E(L)=S*P
      D(L)=C*P
      IF(ABS(E(L)).GT.B) GOTO 30
   59 D(L)=D(L)+F
   60 CONTINUE
*
      DO 90 I=1,N
      K=I
      P=D(I)
*     search for largest/smallest eigenvalue
      DO 70 J=I,N
      IF(IREV.EQ.0.AND.D(J).LE.P) GOTO 70
      IF(IREV.EQ.1.AND.D(J).GE.P) GOTO 70
      K=J
      P=D(J)
   70 CONTINUE
      IF(K.NE.I) THEN
*        exchange
         D(K)=D(I)
         D(I)=P
         DO J=1,N
          P=U(J,I)
          U(J,I)=U(J,K)
          U(J,K)=P
         END DO
      END IF
   90 CONTINUE
  100 RETURN
      END

      SUBROUTINE DTQHHL(N,D,E,U,IDIR)
*     Auxiliary routine for SMHHL
*
      DOUBLE PRECISION D(*),E(*),U(N,N),EPS
      DATA EPS/1.0D-6/
*     ...
      IF(IDIR.GE.0) THEN
*        increasing order of eigenvalues
         IREV=1
      ELSE
*        decreasing order of eigenvalues
         IREV=0
      END IF
      DO I=2,N
       E(I-1)=E(I)
      END DO
      E(N)=0.0
      B=0.0
      F=0.0
*
      DO 60 L=1,N
      J=0
      H=EPS*(ABS(D(L))+ABS(E(L)))
      IF(B.LT.H) B=H
*
*     look for small sub-diagonal element
*
      DO M=L,N
       IF(ABS(E(M)).LE.B) GOTO 25
      END DO
      M=L
   25 IF(M.EQ.L) GOTO 59
*
*     next iteration
*
   30 IF(J.EQ.30) GOTO 100
      J=J+1
      G=D(L)
      P=(D(L+1)-G)/(2.0*E(L))
      R=SQRT(1.0+P*P)
      D(L)=E(L)
      IF(P.LT.0.0) D(L)=D(L)/(P-R)
      IF(P.GE.0.0) D(L)=D(L)/(P+R)
      H=G-D(L)
      DO I=L+1,N
       D(I)=D(I)-H
      END DO
      F=F+H
*     QL transformation
      P=D(M)
      C=1.0
      S=0.0
      M1=M-1
      DO 50 II=L,M1
      I=M1+L-II
      G=C*E(I)
      H=C*P
      IF(ABS(P).GE.ABS(E(I))) THEN
         C=E(I)/P
         R=SQRT(1.0+C*C)
         E(I+1)=S*P*R
         S=C/R
         C=1.0/R
      ELSE
         C=P/E(I)
         R=SQRT(1.0+C*C)
         E(I+1)=S*E(I)*R
         S=1.0/R
         C=C/R
      END IF
      P=C*D(I)-S*G
      D(I+1)=H+S*(C*G+S*D(I))
*     form vector
      DO K=1,N
       H=U(K,I+1)
       U(K,I+1)=S*U(K,I)+C*H
       U(K,I)=C*U(K,I)-S*H
      END DO
   50 CONTINUE
      E(L)=S*P
      D(L)=C*P
      IF(ABS(E(L)).GT.B) GOTO 30
   59 D(L)=D(L)+F
   60 CONTINUE
*
      DO 90 I=1,N
      K=I
      P=D(I)
*     search for largest/smallest eigenvalue
      DO 70 J=I,N
      IF(IREV.EQ.0.AND.D(J).LE.P) GOTO 70
      IF(IREV.EQ.1.AND.D(J).GE.P) GOTO 70
      K=J
      P=D(J)
   70 CONTINUE
      IF(K.NE.I) THEN
*        exchange
         D(K)=D(I)
         D(I)=P
         DO J=1,N
          P=U(J,I)
          U(J,I)=U(J,K)
          U(J,K)=P
         END DO
      END IF
   90 CONTINUE
  100 RETURN
      END

      FUNCTION VXY(X,Y,N)
*     Scalar product of two vectors
*                - - -                 T
*        S = VXY(X,Y,N)           S = X  * Y (scalar product)
*
      REAL X(*),Y(*)
      DOUBLE PRECISION SUM
*     ...
      SUM=0.0D0
      M=N/4
      I=0
      DO J=1,M
       SUM=SUM+X(I+1)*Y(I+1)+X(I+2)*Y(I+2)+X(I+3)*Y(I+3)+X(I+4)*Y(I+4)
       I=I+4
      END DO
      DO J=I+1,N
       SUM=SUM+X(J)*Y(J)
      END DO
      VXY=SUM
      END

