https://github.com/cran/dse
Raw File
Tip revision: f6673198843cfdf7ab8542715823fa692f1eb83c authored by Paul Gilbert on 07 March 2013, 00:00:00 UTC
version 2013.3-2
Tip revision: f667319
dsefor.f
C  Uses routines  DGESV, DGETRF and DGETRI from lapack.

C     removed PARM IS for scratch arrays in KF and calls but do more clean up
C  RR can be p*p, QQ can be n*n

C           Copyright 1993, 1994, 1995, 1996  Bank of Canada.
C           Copyright 1996, 1997  Paul Gilbert.
C           Copyright 1998, 2001, 2004  Bank of Canada.

C  Any person using this software has the right to use,
C        reproduce and distribute it.

C  The Bank does not warrant the accuracy of the information contained in the 
C  software. User assumes all liability for any loss or damages, either direct 
C  or indirect, arising from the use of the software.

C -------------------------------------------------------------------

C  A C code version of this code has also been distribute, but is not current.
C  It was generated using the following (extracted from the f2c readme).
C NOTE:	You may exercise f2c by sending netlib@netlib.bell-labs.com
C 	a message whose first line is "execute f2c" and whose remaining
C 	lines are the Fortran 77 source that you wish to have converted.
C 	Return mail brings you the resulting C, with f2c's error
C 	messages between #ifdef uNdEfInEd and #endif at the end.

C Comments below for compiling are fairly old. As of 2005 the code has been
C   compiled for a few years using standard package build procedure in R.

C Compile with: f77 -c -o dsefor.Sun4.o dsefor.f
C           or
C               f77 -c -o dsefor.Sun5.o dsefor.f
C           or
C             /opt/SUNWspro/f77 -c -o dsefor.S3.3.Sun5.o dsefor.f
C           or
C               f77.SC3.01.Sun4       -c -o dsefor.S3.3.Sun4.o dsefor.f
C     (Splus 3.3 requires compiler SC3.0.1 not SC3.0 as for Splus 3.1 and 3.2)

C           or  (with Solaris f77  (SunPro) )   for R

C               f77  -G -pic -o dse.so dsefor.f
C   or
C               f77  -G -pic -ansi -o dse.so dsefor.f
C   or
C        f77 -G -pic -ansi -L/home/asd3/opt/SUNWspro.old/lib -lF77 -lM77 -lm 
C               -lc -lucb -o dse.so dsefor.f


C   or
C               f77  -G -pic -fast -o dse.so dsefor.f   bombs
C   or
C               f77  -c -pic -o dsefor.o dsefor.f
C               ld -G -o dse.so dsefor.o

C                  -pic:  Generate pic code with short offset
C                  -c:    Produce '.o' file. Do not run ld.
C                  -P:    Generate optimized code
C                  -fast:  Bundled set of options for best performance
C                  -G:     Create shared object
C                  -O1:    Generate optimized code
C                  -O2:    Generate optimized code
C                  -O3:    Generate optimized code
C                  -O4:    Generate optimized code
C                  -O:     Generate optimized code
C                  Suffix 'so':    Shared object


C           or  (the following seems to be the preferred method for Splus)
C               splus COMPILE dsefor.f
C                 and then mv dsefor.o to dsefor.Sunx.o
C  
C   The pararameter IS=xxx controls the maximum size of the state in KF models.
C   A larger state makes S take more memory. 
C Compile with: f77 -c -o dsefor.Sun4.large.o dsefor.f
C           or
C               f77 -c -o dsefor.Sun5.large.o dsefor.f
C  
C   
C        1         2         3         4         5         6         712       8
C      SUBROUTINE ERROR(STR,L, IS,N)
CC  STR is a string of length L and IS is an integer vector of length N
C      INTEGER L,N
C      INTEGER IS(N)
C      CHARACTER STR(L)
CC      CALL INTPR(STR,L,IS,N)
CC      WRITE(STR,IS)
C      RETURN 
C      END

C      SUBROUTINE DBPR(STR,L, IS,N)
CC  STR is a string of length L and IS is an integer vector of length N
C      INTEGER L,N
C      INTEGER IS(N)
C      CHARACTER STR(L)
CC      CALL INTPR(STR,L,IS,N)
CC      WRITE(STR,IS)
C      RETURN 
C      END

C      SUBROUTINE DBPRDB(STR,L, R,N)
CC  STR is a string of length L and R is an double real vector of length N
C      INTEGER L,N
C      DOUBLE PRECISION R(N)
C      CHARACTER STR(L)
CC      CALL DBLEPR(STR,L, R, N)
CC      WRITE(STR,R)
C      RETURN 
C      END


      SUBROUTINE SIMSS(Y,Z,M,N,P,NSMPL,U,W,E,F,G,H,FK,Q,R, GAIN)
C
C  Simulate a state space model model.
C  See s code simulate.ss for details 
      INTEGER M,N,P, NSMPL
      INTEGER GAIN
      DOUBLE PRECISION Z(NSMPL,N)
      DOUBLE PRECISION Y(NSMPL,P),U(NSMPL,M) 
      DOUBLE PRECISION W(NSMPL,P),E(NSMPL,N) 
      DOUBLE PRECISION F(N,N),G(N,M),H(P,N),R(P,P),Q(N,N),FK(N,P)
C
C Note: the first period is done in the calling S routine so that
C   intial conditions can be handled there.
C
      DO 1000 IT=2,NSMPL

      DO 2001 I=1,N
         Z(IT,I)=0.0
         DO 2001 K=1,N
2001         Z(IT,I)=Z(IT,I)+F(I,K)*Z(IT-1,K)
      IF (M.NE.0) THEN
         DO 2003 I=1,N
            DO 2003 K=1,M
2003          Z(IT,I)=Z(IT,I)+G(I,K)*U(IT,K)
      ENDIF
      IF (GAIN .EQ. 1) THEN
        DO 2004 I=1,N
          DO 2004 K=1,P
2004        Z(IT,I)=Z(IT,I)+FK(I,K)*W(IT-1,K)
      ELSE
        DO 2005 I=1,N
          DO 2005 K=1,N
2005        Z(IT,I)=Z(IT,I)+Q(I,K)*E(IT-1,K)
      ENDIF

      DO 2010 I=1,P
         Y(IT,I)=0.0
         DO 2010 J=1,N
2010        Y(IT,I)= Y(IT,I) + H(I,J)*Z(IT,J)
      IF (GAIN .EQ. 1) THEN
         DO 2014 I=1,P
2014        Y(IT,I)=Y(IT,I)+W(IT,I)
      ELSE
         DO 2015 I=1,P
           DO 2015 K=1,P
2015        Y(IT,I)=Y(IT,I)+R(I,K)*W(IT,K)
      ENDIF
1000  CONTINUE
      RETURN 
      END
C
      SUBROUTINE SMOOTH( Z, TRKERR, U,Y, N,M,P,NSMPL, F,G,H,RR,
     +  IS, A,D,L,PT1, ZT, IPIV)
C see also the version XMOOTH below for debugging.
C
C   Calculate the smoothed state for the model:
C
C        z(t) = Fz(t-1) + Gu(t) + Qe(t)
C        y(t) = Hz(t)  + Rw(t)
C 
C   see KF and KF.s for details.
C   Z should be supplied as the filtered estimate of the state and is
C     returned as the smoothed estimate, and similarily for the 
C     tracking error TRKERR. 

      PARAMETER (NSTART=1)
      INTEGER N,M,P, NSMPL
      DOUBLE PRECISION Z(NSMPL,N),TRKERR(NSMPL,N,N)
      DOUBLE PRECISION U(NSMPL,M), Y(NSMPL,P)
      DOUBLE PRECISION F(N,N),G(N,M),H(P,N),RR(P,P)
C   
C   IS is the maximum state dimension  and the maximum output
C     dimension  (used for working arrays)
C   The following are for scratch space
      DOUBLE PRECISION A(IS,IS),D(IS,IS),L(IS,IS),PT1(IS,IS)
      DOUBLE PRECISION ZT(IS)
      INTEGER IPIV(IS,IS)

C
C      CALL DBPR('M     ',6, M,1)
C      CALL DBPR('N     ',6, N,1)
C      CALL DBPR('P     ',6, P,1)
C      CALL DBPR('NSMPL  ',6, NSMPL,1)
      
C
C        RR= RR' 
C
C  Next period state and tracking error get clobbered in 
C    backwards recursion, so:             
      DO 902 I=1,N
        DO 902 J=1,N
902         PT1(I,J)=TRKERR(NSMPL,I,J)

      DO 1000 IT=NSMPL-1,NSTART,-1

C                                          D=H*P(t|t-1)*H' + RR
      DO 2 I=1,N
         DO 2 J=1,P
            A(J,I)=0.0D0
            DO 2 K=1,N
  2            A(J,I)=A(J,I)+TRKERR(IT,I,K)*H(J,K)
C                     A now has  ( P(t|t-1)*H' )'                 
      DO 3 I=1,P
         DO 3 J=1,P
            D(I,J)=RR(I,J)
            DO 3 K=1,N
  3            D(I,J)=D(I,J)+H(I,K)*A(J,K)
C                     D now has  H*P(t|t-1)*H' + RR                

C                        Kalman gain    K=P(t|t-1)*H'*inv(D)   (A5)
C  For inverse call DGETRI, for solve call DGETRS.
CC    Invert method ( invert in place )
C      CALL DGETRF( P, P, D, IS, IPIV, INFO )
C      CALL DGETRI( P, D, IS, IPIV, L, IS*IS, INFO )
C
C      DO 4 I=1,N
C         DO 4 J=1,P
C            L(I,J)=0.0D0
C            DO 4 K=1,P
C  4            L(I,J)=L(I,J)+A(K,I)*D(K,J)

C     Solve  method (solve in place. Result is in non-inverted array.)
      CALL DGETRF( P, P, D, IS, IPIV, INFO )
C       A has been transposed to use here 
      CALL DGETRS( 'T', P, N, D, IS, IPIV, A, IS, INFO )

      DO 4 I=1,N
         DO 4 J=1,P
  4            L(I,J)=A(J,I)


C                       L now contains the Kalman gain K

C      IF (IT.EQ.NSMPL-1) THEN
C         CALL DBPRDB('K in L ',7,L,IS*IS)
C      ENDIF

C  E(z(t)|y(t),u(t+1) ZT = z(t|t) = Z(t|t-1) + K*(y - H*Z(t|t-1))  (A6)
      DO 107 I=1,P
            A(I,1)=Y(IT,I)
            DO 107 K=1,N
107            A(I,1)=A(I,1) - H(I,K)*Z(IT,K)
C                     A(,1) now has  y - H*Z(t|t-1)                   
      DO 109 I=1,N
            ZT(I)=Z(IT,I)
            DO 109 K=1,P
109            ZT(I)=ZT(I) + L(I,K)*A(K,1)
C                     ZT now has  Z(t|t-1) + K*(y - H*Z(t|t-1))                  


C                           P(t|t) = P(t|t-1) - K*H*P(t|t-1)      (A7)
      DO 7 I=1,N
         DO 7 J=1,N
            A(I,J)=0.0D0
            DO 7 K=1,P
  7            A(I,J)=A(I,J) + L(I,K)*H(K,J)
C                     A now has  K*H                   
      DO 8 I=1,N
         DO 8 J=1,N
            L(I,J)=TRKERR(IT,I,J)
            DO 8 K=1,N
  8            L(I,J)=L(I,J) - A(I,K)*TRKERR(IT,K,J)
C                     L now has  P(t|t) = P(t|t-1) - K*H*P(t|t-1)               
      DO 9 I=1,N
            DO 9 J=1,N
  9            A(I,J)=(L(I,J)+L(J,I))/2.0D0
C                                        A now contains P(t|t)
C      IF (IT.EQ.NSMPL-1) THEN
C         CALL DBPRDB('P(t|t) in A ',12,A,IS*IS)
C      ENDIF

C                                   J = P(t|t)*F'*inv(P(t+1|t))  (A8)
      DO 51 I=1,N
        DO 51 J=1,N
 51        L(I,J)=PT1(I,J)

C  For inverse call DGETRI, for solve call DGETRS.
CC    Invert method ( invert in place )
C      CALL DGETRF( N, N, L, IS, IPIV, INFO )
C      CALL DGETRI( N, L, IS, IPIV, D, IS*IS, INFO )
C
CC  transpose D to be consistent with solve method
C      DO 52 I=1,N
C        DO 52 J=1,N
C            D(J,I)=0.0D0
C            DO 52 K=1,N
C 52            D(J,I)=D(J,I) + F(K,I)*L(K,J)

C     Solve  method (solve in place. Result is in non-inverted array.)
      CALL DGETRF( N, N, L, IS, IPIV, INFO )
      DO 52 I=1,N
        DO 52 J=1,N
 52        D(I,J)=F(I,J)
      CALL DGETRS( 'T', N, N, L, IS, IPIV, D, IS, INFO )


C                       D  now contains ( F'*inv(P(t+1|t)) )'
      DO 53 I=1,N
        DO 53 J=1,N
         L(I,J)=0.0D0
            DO 53 K=1,N
 53            L(I,J)=L(I,J) + A(I,K)*D(J,K)
C                         L now contains J and A still contains P(t|t).

C            smoothed state sm[t] = ZT + J*(sm[t+1] - F*ZT - G*u(t+1))  (A9)
      DO 16 I=1,N
         D(I,1)=Z(IT+1,I)
         DO 16 K=1,N
 16            D(I,1)=D(I,1) - F(I,K)*ZT(K)
C                         D now contains sm[t+1] - F*ZT 
      IF (M.NE.0) THEN
         DO 17 I=1,N
            DO 17 K=1,M
 17            D(I,1)=D(I,1) - G(I,K)*U(IT+1,K)
      ENDIF
C                         D now contains sm[t+1] - F*ZT - G*u(t+1)
      DO 18 I=1,N
         Z(IT,I)=ZT(I)
         DO 18 K=1,N
 18           Z(IT,I)=Z(IT,I) + L(I,K)*D(K,1)
C                        Z now contains ZT + J*(sm[t+1] - F*ZT - G*u(t+1))

C  smoothed tracking error strk[t]= P[t|t] + J*(strk[t+1]-trk[t+1])*J'  (A10)
C     L contains J and A contains P(t|t) and PT1 contains trk[t+1].
      DO 26 I=1,N
         DO 26 J=1,N
 26          PT1(I,J)=TRKERR(IT+1,I,J) - PT1(I,J)
C                       PT1 now contains (strk[t+1]-trk[t+1])
      DO 27 I=1,N
         DO 27 J=1,N
            D(I,J)=0.0D0
            DO 27 K=1,N
 27            D(I,J)=D(I,J)+PT1(I,K)*L(J,K)
C                       D now contains (strk[t+1]-trk[t+1])*J'
      DO 28 I=1,N
         DO 28 J=1,N
            DO 28 K=1,N
 28            A(I,J)=A(I,J)+L(I,K)*D(K,J)
C                       A now contains P[t|t] + J*(strk[t+1]-trk[t+1])*J'
      DO 29 I=1,N
         DO 29 J=1,N
 29         PT1(I,J)=TRKERR(IT,I,J)
C  PT1 now contains trk[t+1], the filter tracking error for the next iteration  
      DO 30 I=1,N
            DO 30 J=1,N
 30            TRKERR(IT,I,J)=(A(I,J)+A(J,I))/2.0D0
C  TRKERR(IT,,) now contains smtrk[t+1], the smoother tracking error  

1000  CONTINUE

      RETURN 
      END
C


      SUBROUTINE KF(EY, HPERR,PRDERR,ERRWT, LSTATE,STATE,
     + LTKERR,TRKERR,
     + M,N,P,NSMPL,NPRED,NACC,  U,Y, F,G,H,FK, Q,R, GAIN,Z0,P0,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)
C
C   Calculate the likelihood value for the model:
C
C        z(t) = Fz(t-1) + Gu(t) + Qe(t-1)
C        y(t) = Hz(t)  + Rw(t)
C 
C or the innovations model:
C        z(t) = Fz(t-1) + Gu(t) + FKw(t-1)
C        y(t) = Hz(t)  + w(t)
C  
C  
C  FK is the Kalman gain
C  If GAIN is true then FK is taken as given (innovations model)
C
C  M is the dimension of the input u.
C  N is the dimension of the state z and the system noise e.
C  P is the dimension of the output y and the ouput noise w.
C  NSMPL is the length of the data series to use for residual
C      and likelihood calculations.
C  NPRED is the period to predict ahead (past NSMPL) (for z and y)
C  NACC is the actual first (time) dimension of Y and U.
C 
C   STATE is the one step ahead ESTIMATE OF STATE.
C   It is returned only if LSTATE is TRUE.
C   Z0  is the initial state (often set to zero).
C   P0  is the initial state tracking error (often set to I and 
C   totally ignored in innovations models).
C   PP is  the one step ahead est. cov matrix of the state estimation error.
C   TRKERR is the history of PP at each period. 
C   It is returned only for non-innovations models (GAIN=FALSE) and
C     then only if LTKERR is TRUE.
C   EY is the output prediction. EY is used to store WW during computation!
C   The prediction error at each period is WW (innovations) = Y - EY.
C     If HPERR is equal or greater than one then weighted prediction 
C     errors are calculated up to the horizon indicated
C     by HPERR. The weights taken from ERRWT are applied to the squared
C     error at each period ahead.

C   If HPERR is zero and LSTATE and LTKERR are false then ERRWT,
C    PRDERR, STATE, and TRKERR are not referenced, 
C    so KF can be called with dummy arguments as 
C    in KFP and GEND.
C             
C   IS is the maximum state dimension  and the maximum output
C     dimension  (used for working arrays)
C    NSTART is not properly implemented and must be set to 1.
C
C      PARAMETER (IS=100,NSTART=1)
      PARAMETER (NSTART=1)

      INTEGER HPERR, M,N,P, NSMPL, NACC

      DOUBLE PRECISION EY(NPRED,P), PRDERR(NSMPL,P)
      DOUBLE PRECISION ERRWT(HPERR)
      DOUBLE PRECISION STATE(NPRED,N),TRKERR(NPRED,N,N), Z0(N),P0(N,N)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
      DOUBLE PRECISION F(N,N),G(N,M),H(P,N),R(P,P),Q(N,N),FK(N,P)

      INTEGER LSTATE, LTKERR, GAIN
C   
C
      INTEGER IPIV(IS,IS)

      DOUBLE PRECISION A(IS,IS),AA(IS,IS),PP(IS,IS),QQ(N,N),RR(P,P)
      DOUBLE PRECISION Z(IS), ZZ(IS), WW(IS)

      DOUBLE PRECISION HW
      INTEGER LPERR
C
C      CALL DBPR('M     ',6, M,1)
C      CALL DBPR('N     ',6, N,1)
C      CALL DBPR('P     ',6, P,1)
C      CALL DBPR('NSMPL  ',6, NSMPL,1)
C      CALL DBPR('NPRED  ',6, NPRED,1)
C      CALL DBPR('NACC  ',6, NACC,1)
C      CALL DBPRDB('R  ',3,R,9)
C      IF (GAIN.EQ.1) THEN 
C         CALL DBPR('GAIN is T',9, 1,0)
C      ELSE
C         CALL DBPR('GAIN is F',9, 1,0)
C      ENDIF
C      CALL DBPRDB('Q  ',3,Q,N*N)
C      CALL DBPR('HPERR ',6, HPERR,1)
      
      LPERR= 0
      IF (HPERR.GT.0) THEN
         DO 500 I=1,HPERR
           IF (ERRWT(I).GT.0.0)  LPERR= 1
 500     CONTINUE    
      ENDIF
C
C     initial innovation.
      DO 209 I=1,P
 209         WW(I)=0.0
C     initial state.
      DO 210 I=1,N
 210         ZZ(I)=Z0(I) 
C
      IF (GAIN .NE. 1) THEN
C        initial tracking error.
         DO 220 I=1,N
            DO 220 J=1,N
 220           PP(I,J)=P0(I,J)
C
C        RR= RR'    QQ= QQ'
C

         DO 230 I=1,N
          DO 230 J=1,N
            QQ(I,J)=0.0D0
            DO 230 K=1,N
 230           QQ(I,J)=QQ(I,J)+Q(I,K)*Q(J,K)
         DO 236 I=1,P
           DO 236 J=1,P
            RR(I,J)=0.0D0
            DO 236 K=1,P
 236           RR(I,J)=RR(I,J)+R(I,K)*R(J,K) 
       ENDIF
C
C    Start Time loop
C
      DO 1000 IT=NSTART,NSMPL
      IF (GAIN .NE. 1) THEN  
                                   
C   Kalman gain  FK = F*P(t|t-1)*H'* inv( H*P(t|t-1)*H' + RR')
C   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C
C   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ P(t|t-1)*H' ~~~~~~
      DO 5 I=1,N
         DO 5 J=1,P
            AA(I,J)=0.0D0
            DO 5 K=1,N
  5            AA(I,J)=AA(I,J)+PP(I,K)*H(J,K)

C    ~~~~~~~~~~~~~~~~~~F*P(t|t-1)*H'~~~~~~~~~~~~~~~~~~~~~~~~~~~
      DO 6 I=1,N
         DO 6 J=1,P
            FK(I,J)=0.0D0
            DO 6 K=1,N
  6           FK(I,J)=FK(I,J)+F(I,K)*AA(K,J)

C     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~H*P(t|t-1)*H' + RR'~~~
      DO 7 I=1,P
         DO 7 J=1,P
            A(I,J)=RR(I,J)
            DO 7 K=1,N
  7            A(I,J)=A(I,J)+H(I,K)*AA(K,J)
C      CALL DBPRDB('DO 7 A ',7, A,(IS*IS))
C     force symetry.
      DO 9 I=1,P
         DO 9 J=1,P
  9         AA(I,J)=(A(I,J)+A(J,I))/2.0D0

C     ~~~~~~~~~~~~~FK =F*P(t|t-1)*H'* inv( H*P(t|t-1)*H' + RR')
C  For inverse call DGETRI, for solve call DGETRS.
C     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ inv( H*P(t|t-1)*H' + RR')
CC    Invert method ( invert in place )
C      CALL DGETRF( P, P, AA, IS, IPIV, INFO )
C      CALL DGETRI( P, AA, IS, IPIV, A, IS*IS, INFO )
C
C     ~~~~~~~~~~~~~~~~~F*P(t|t-1)*H'* inv( H*P(t|t-1)*H' + RR')
C      DO 14 I=1,N
C         DO 14 J=1,P
C            A(I,J)=0.0D0
C            DO 14 K=1,P
C  14           A(I,J)=A(I,J)+FK(I,K)*AA(K,J)
C
C      DO 15 I=1,N
C         DO 15 J=1,P
C  15           FK(I,J)=A(I,J)

C     Solve  method (solve in place. Result is in non-inverted array.)
C     ~~~~~~~~~~~~~~~~~F*P(t|t-1)*H'* inv( H*P(t|t-1)*H' + RR')
      CALL DGETRF( P, P, AA, IS, IPIV, INFO )
C       need KF transpose 
      DO 14 I=1,P
         DO 14 J=1,N
  14           A(I,J)=FK(J,I)
      CALL DGETRS( 'T',  P, N, AA, IS, IPIV, A, IS, INFO )

      DO 15 I=1,N
         DO 15 J=1,P
  15           FK(I,J)=A(J,I)

C   Now FK has the Kalman gain

C      IF (IT.EQ.1) THEN
C         CALL DBPRDB('K ',2,FK,N*P)
C      ENDIF
C
C     P(t|t-1)= F*P(t-|t-2)*F' -  K*H*P(t-1|t-2)*F' + Q*Q' 
C
      DO 2 I=1,N
         DO 2 J=1,N
            A(I,J)=0.0D0
            DO 2 K=1,N
  2            A(I,J)=A(I,J)+PP(I,K)*F(J,K)
      DO 3 I=1,N
         DO 3 J=1,N
            AA(I,J)=QQ(I,J)
            DO 3 K=1,N
  3            AA(I,J)=AA(I,J)+F(I,K)*A(K,J)
      DO 18 I=1,P
         DO 18 J=1,N
            PP(I,J)=0.0D0
            DO 18 K=1,N
  18           PP(I,J)=PP(I,J)+H(I,K)*A(K,J)
      DO 19 I=1,N
         DO 19 J=1,N
           DO 19 K=1,P
  19        AA(I,J)=AA(I,J)-FK(I,K)*PP(K,J)
C     force symetry to avoid numerical round off problems
      DO 20 I=1,N
         DO 20 J=1,N
  20        PP(I,J)=( AA(I,J)+AA(J,I) )/2.0D0
C      IF (IT.EQ.1) THEN
C         CALL DBPRDB('PP  ',4,PP,IS*IS)
C      ENDIF
      IF(LTKERR .EQ. 1) THEN
         DO 21 I=1,N
            DO 21 J=1,N
  21           TRKERR(IT,I,J)=PP(I,J)
      ENDIF
      ENDIF
C   end of Kalman gain and tracking error update ( if NOT GAIN )
C
C   one step ahead state estimate
C     z(t|t-1)= Fz(t-1|t-2) + FK*WW(t-1) + Gu(t)
C
      DO 1 I=1,N
         Z(I)=0.0
         DO 1 K=1,N
  1         Z(I)=Z(I)+F(I,K)*ZZ(K)
      DO 22 I=1,N
         DO 22 K=1,P
  22        Z(I)=Z(I)+FK(I,K)*WW(K)
      DO 23 I=1,N
         DO 23 K=1,M
  23        Z(I)=Z(I)+G(I,K)*U(IT,K)
      DO 24 I=1,N
 24         ZZ(I)=Z(I)
      IF (LSTATE .EQ. 1) THEN
         DO 25 I=1,N
 25         STATE(IT,I)=Z(I)
      ENDIF
C      CALL DBPRDB('Z  ',3,Z,N)


C  one step ahead prediction  EY(t)=H*z(t|t-1))
C
C  innovations  WW(t)=y(t)-H*z(t|t-1))
C
C   EY stores history of predition error WW to reconstruct predictions
      DO 10 I=1,P
         WW(I)=Y(IT,I)
         DO 10 J=1,N
  10        WW(I)= WW(I) - H(I,J)*Z(J)
      DO 11 I=1,P
  11        EY(IT,I)= WW(I)
C      CALL DBPRDB('WW ',3,WW,P)

C   Return weighted prediction error
      IF (LPERR .EQ. 1) THEN
         DO 401 I=1,P
 401          PRDERR(IT,I)= ERRWT(1)*WW(I)**2
         IF (HPERR.GT.1) THEN
            DO 400 K=2,HPERR        
              IF ((IT+K-1).LE.NSMPL) THEN
                 DO 402 I=1,N
 402                AA(1,I) = Z(I)
                 DO 409 I=1,N
 409                Z(I) = 0.0
                 DO 403 I=1,N
                    DO 403 J=1,N
 403                   Z(I)= Z(I)+F(I,J)*AA(1,J)
                 IF (K.EQ.2) THEN
                    DO 406 I=1,N
                       DO 406 J=1,P
 406                      Z(I)= Z(I)+FK(I,J)*WW(J)
                 ENDIF
                 IF(M.NE.0) THEN
                    DO 404 I=1,N
                       DO 404 J=1,M
 404                      Z(I)= Z(I)+G(I,J)*U(IT+K-1,J)
                 ENDIF
                 DO 408 I=1,P
                    HW=0.0
                    DO 407 J=1,N
 407                   HW = HW+ H(I,J)*Z(J)
 408                PRDERR(IT,I)= PRDERR(IT,I) +
     +                               ERRWT(K)*(Y(IT+K-1,I)-HW)**2
C                 IF (IT.GT.97) THEN
C                    CALL DBPR('K     ',6, K,1)
C                    CALL DBPRDB('PRDERR ',8,PRDERR,NSMPL*P)
C                 ENDIF
              ENDIF
 400      CONTINUE
         ENDIF
      ENDIF

1000  CONTINUE
C  end of time loop


C     reconstruct predictions
      DO 41 IT=NSTART,NSMPL
         DO 41 I=1,P
  41        EY(IT,I)=Y(IT,I) - EY(IT,I)
C
C    Start multi-step prediction loop
C
      IF (NPRED .GT. NSMPL) THEN  
      DO 2000 IT=NSMPL+1, NPRED
C
      DO 2001 I=1,N
         Z(I)=0.0
         DO 2001 K=1,N
2001         Z(I)=Z(I)+F(I,K)*ZZ(K)
      IF (M.NE.0) THEN
         DO 2003 I=1,N
            DO 2003 K=1,M
2003           Z(I)=Z(I)+G(I,K)*U(IT,K)
      ENDIF
C   use prediction error from last sample point (i.e. for first prediction)
      IF (IT.EQ.(NSMPL+1)) THEN
         DO 2004 I=1,N
            DO 2004 K=1,P
2004           Z(I)=Z(I)+FK(I,K)*WW(K)
      ENDIF
      IF (LSTATE .EQ. 1) THEN
         DO 2005 I=1,N
2005        STATE(IT,I)=Z(I)
      ENDIF
      DO 2010 I=1,P
         EY(IT,I)=0.0
         DO 2010 J=1,N
2010        EY(IT,I)= EY(IT,I) + H(I,J)*Z(J)
      DO 2024 I=1,N
2024        ZZ(I)=Z(I)

2000  CONTINUE
      ENDIF
C  end of multi-step prediction loop

      RETURN 
      END
C
C
C        1         2         3         4         5         6         7         8
      SUBROUTINE SIMRMA(Y,Y0,M,P,IA,IB,IC,NSMPL,U,U0,W,W0,A,B,C,TREND)
C      Simulate an ARMA model. See documentation in ARMA and in the S version.
      PARAMETER (NSTART=1)

      INTEGER M,P,IA,IB,IC, NSMPL

      DOUBLE PRECISION Y(NSMPL,P),U(NSMPL,M),Y0(IA,P), U0(IC,M)
      DOUBLE PRECISION W(NSMPL,P), W0(IB,P)
      DOUBLE PRECISION A(IA,P,P),B(IB,P,P),C(IC,P,M), TREND(NSMPL,P)

C       CALL DBPRDB('inSIMARMA ',7, 1,1)
C       CALL DBPR('M     ',6, M,1)
C       CALL DBPRDB('A     ',6, A,(IA*P*P))
C      IF (IT.LE.5) CALL DBPRDB('step1 ',6, Y(IT,3),1)
C      CALL DBPRDB('C ',2, C,(IC*P*M) )
C      CALL DBPRDB('U0 ',3, U0,(IC*M) )
C      CALL DBPRDB('U  ',3, U,(NSMPL*M) )

      DO 2001 I=1,P
        DO 2001 IT=NSTART,NSMPL
2001         Y(IT,I)= 0.0D0

      DO 1 IT=NSTART,NSMPL 
      DO 1 I=1,P
 1         Y(IT,I)= TREND(IT,I)

      DO 1000 IT=NSTART,NSMPL
 
C      IF (IT.LE.5) CALL DBPRDB('step1 ',6, Y(IT,3),1)
      DO 5 L=2,IA
         IF ((IT+1).LE.L) THEN
            DO 2 I=1,P
               DO 2 J=1,P
2               Y(IT,I)=Y(IT,I)-A(L,I,J)*Y0(L-IT,J)
         ELSE
            DO 3 I=1,P
               DO 3 J=1,P
3               Y(IT,I)=Y(IT,I)-A(L,I,J)* Y(IT+1-L,J)
         ENDIF
5     CONTINUE
C      IF (IT.LE.5) CALL DBPRDB('step2 ',6, Y(IT,3),1)

      DO 15 L=1,IB
         IF ((IT+1).LE.L) THEN
            DO 12 I=1,P
               DO 12 J=1,P
12               Y(IT,I)=Y(IT,I)+B(L,I,J)*W0(L-IT,J)
         ELSE
            DO 13 I=1,P
               DO 13 J=1,P
13               Y(IT,I)=Y(IT,I)+B(L,I,J)* W(IT+1-L,J)
         ENDIF
15    CONTINUE
C      IF (IT.LE.5) CALL DBPRDB('step3 ',6, Y(IT,3),1)
      IF (M.GT.0) THEN
      DO 25 L=1,IC
         IF ((IT+1).LE.L) THEN
            DO 22 I=1,P
               DO 22 J=1,M
22               Y(IT,I)=Y(IT,I)+C(L,I,J)*U0(L-IT,J)
C         IF (IT.LE.5) CALL DBPRDB('stepa ',6, Y(IT,3),1)
         ELSE
            DO 23 I=1,P
               DO 23 J=1,M
23               Y(IT,I)=Y(IT,I)+C(L,I,J)* U(IT+1-L,J)
C           IF (IT.LE.5) CALL DBPRDB('stepb ',6, Y(IT,3),1)
         ENDIF
25    CONTINUE
      ENDIF
C      IF (IT.LE.5) CALL DBPRDB('step4 ',6, Y(IT,3),1)

1000  CONTINUE
      RETURN 
      END

      SUBROUTINE ARMA(EY, HPERR, PRDERR, ERRWT,                  
     + M,P,IA,IB,IC,NSMPL,NPRED,NACC,  U,Y , A,B,C, TREND, 
     + IS,AA,BB,WW,IPIV)
C sampleT is the length of data which should be used for estimation.
C Calculate the one-step ahead predictions, and likelihood value for the model:
C
C       A(L)y(t) =  B(L)w(t) + C(L)u(t)  + TREND(t)
C 
C A(L) (axpxp) is the auto-regressive polynomial array.
C B(L) (bxpxp) is the moving-average polynomial array.
C C(L) (cxpxm) is the  input polynomial array.
C TREND is a constant vector added at each period.
C y is the p dimensional output data.
C u is the m dimensional control (input) data.

C  M is the dimension of the input u.
C  P is the dimension of the output y and the ouput noise w.
C  NSMPL is the length of the data series to use for residual
C      and likelihood calculations.
C  NPRED is the period to predict (past NSMPL)
C  NACC is the actual first (time) dimension of Y and U.
C 
C   EY is the output prediction. Initially EY is used to store WW.
C   The prediction error WW (innovations) = Y - EY.

C   Weighted prediction errors are returned in PRDERR.
C     If HPERR is equal or greater than one then weighted prediction 
C     errors are calculated up to the horizon indicated
C     by HPERR. The weights taken from ERRWT are applied to the squared
C     error at each period ahead.

C   If HPERR is zero or all elements of ERRWT are zero then
C   LPERR is set false then PRDERR is not referenced, so ARMA can be called
C    with dummy arguments as in GEND.
C             
C    NSTART is not properly implemented and must be set to 1.
C
      PARAMETER (NSTART=1)

      INTEGER M,P,IA,IB,IC, NSMPL, NACC
      INTEGER HPERR

      DOUBLE PRECISION EY(NPRED,P), PRDERR(NSMPL,P)
      DOUBLE PRECISION ERRWT(HPERR)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
      DOUBLE PRECISION A(IA,P,P),B(IB,P,P),C(IC,P,M), TREND(NPRED,P)
C   IS should be max(P,M)
      DOUBLE PRECISION AA(IS,IS),BB(IS,IS),WW(IS)
C   
C
      INTEGER LPERR
      INTEGER IPIV(IS,IS)
C
C       CALL DBPRDB('inARMA ',7, 1,1)
C      CALL DBPR('M     ',6, M,1)
C      CALL DBPR('P     ',6, P,1)
C      CALL DBPR('IA    ',6, IA,1)
C      CALL DBPR('IB    ',6, IB,1)
C      CALL DBPR('IC    ',6, IC,1)
C      CALL DBPR('NSMPL  ',6, NSMPL,1)
C      CALL DBPR('NPRED  ',6, NPRED,1)
C      CALL DBPR('NACC  ',6, NACC,1)
C       CALL DBPRDB('A     ',6, A,(IA*P*P))
C       CALL DBPRDB('B     ',6, B,(IB*P*P))
C       CALL DBPRDB('C     ',6, C,(IC*P*M))


      LPERR= 0
      IF (HPERR.GT.0) THEN
         DO 500 I=1,HPERR
           IF (ERRWT(I).GT.0.0)  LPERR= 1
 500     CONTINUE    
      ENDIF
C
C     Ensure B(0) = I by inverting B(0) and multiplying through
C        B(1,,) is not modified yet as B(0) is needed later, but
C        it is not referenced through the time loop, so effectively
C        asummed = I.
C
      DO 300 I=1,P
         DO 300 J=1,P
300         BB(I,J)=B(1,I,J)

C      CALL INVERS(BB,P,IS,DETOM)
C     invert in place. 
      CALL DGETRF( P, P, BB, IS, IPIV, INFO )
C  For inverse call DGETRI, for solve call DGETRS.
      CALL DGETRI( P, BB, IS, IPIV, AA, IS*IS, INFO )
C      CALL DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO )

      DO 302 L=1,IA
         DO 301 I=1,P
            DO 301 J=1,P
               AA(I,J)=A(L,I,J)
301            A(L,I,J)=0.0D+0
         DO 302 I=1,P
            DO 302 J=1,P
               DO 302 K=1,P
302               A(L,I,J)=A(L,I,J)+BB(I,K)*AA(K,J)
      DO 304 L=2,IB
         DO 303 I=1,P
            DO 303 J=1,P
               AA(I,J)=B(L,I,J)
303            B(L,I,J)=0.0D+0
         DO 304 I=1,P
            DO 304 J=1,P
               DO 304 K=1,P
304               B(L,I,J)=B(L,I,J)+BB(I,K)*AA(K,J)
      DO 306 L=1,IC
         DO 305 I=1,P
            DO 305 J=1,M
               AA(I,J)=C(L,I,J)
305            C(L,I,J)=0.0D+0
         DO 306 I=1,P
            DO 306 J=1,M
               DO 306 K=1,P
306               C(L,I,J)=C(L,I,J)+BB(I,K)*AA(K,J)
      DO 308 IT=1,NSMPL
         DO 307 I=1,P
            AA(I,1)=TREND(IT,I)
307         TREND(IT,I)=0.0D+0
         DO 308 I=1,P
            DO 308 K=1,P
308            TREND(IT,I)=TREND(IT,I) + BB(I,K)*AA(I,1)
         DO 309 IT=1,NPRED
            DO 309 J=1,P
309            EY(IT,J)=0.0D+0
C
C    Start Time loop
C
      DO 1000 IT=NSTART,NSMPL
C  
      DO 1 I=1,P
 1         WW(I)= -TREND(IT,I)
C
      DO 22 L=1,IA
         IF (L.LE.IT) THEN
            DO 2 I=1,P
               DO 2 J=1,P
2               WW(I)=WW(I)+A(L,I,J)*Y(IT+1-L,J)
         ENDIF
22    CONTINUE
C
      IF (IB.GE.2) THEN
         DO 23 L=2,IB
            IF (L.LE.IT) THEN
               DO 3 I=1,P
                  DO 3 J=1,P
3                  WW(I)=WW(I)-B(L,I,J)*EY(IT+1-L,J)
            ENDIF
23       CONTINUE
      ENDIF
C
      DO 24 L=1,IC
         IF (L.LE.IT) THEN
            DO 4 I=1,P
               DO 4 J=1,M
C         CALL DBPRDB('C     ',6, C(L,I,J),1)
C         CALL DBPRDB('U     ',6,U(IT+1-L,J) ,1)
4               WW(I)=WW(I)-C(L,I,J)*U(IT+1-L,J)
         ENDIF
24    CONTINUE
C      IF (IT.LE.3) THEN
C         CALL DBPRDB('ww  ',4, WW,P)
C      ENDIF
C
C   EY stores history of predition error WW to reconstruct predictions
      DO 10 I=1,P
10         EY(IT,I)=WW(I)

C   Return weighted prediction error
      IF (LPERR .EQ. 1) THEN
         DO 410 I=1,P
 410          PRDERR(IT,I)= ERRWT(1)*WW(I)**2
         IF (HPERR.GT.1) THEN
            DO 400 K=2,HPERR        
              IF ((IT+K-1).LE.NSMPL) THEN
                 DO 401 I=1,P
 401                WW(I)= -TREND(IT,I)
C
              DO 4022 L=1,IA
                  IF (L.LT.(IT+K)) THEN
                     DO 402 I=1,P
                        DO 402 J=1,P
402                        WW(I)=WW(I)+A(L,I,J)*Y(IT+K-L,J)
                  ENDIF
4022          CONTINUE
C
              IF (IB.GE.2) THEN
                 DO 4023 L=2,IB
                    IF (L.LT.(IT+K)) THEN
                       DO 403 I=1,P
                          DO 403 J=1,P
403                          WW(I)=WW(I)-B(L,I,J)*EY(IT+K-L,J)
                    ENDIF
4023             CONTINUE
              ENDIF
C
              DO 4024 L=1,IC
                 IF (L.LT.(IT+K)) THEN
                    DO 404 I=1,P
                       DO 404 J=1,M
404                       WW(I)=WW(I)-C(L,I,J)*U(IT+K-L,J)
                 ENDIF
4024           CONTINUE
C              correction for WW by B0. 
C      NB this has not been well tested and models with B0 != I may not work !!
               DO 407 I=1,P
                  DO 407 J=1,P
 407                BB(I,1) = BB(I,1) + B(1,I,J) * WW(J)
               DO 408 I=1,P
 408              PRDERR(IT,I)= PRDERR(IT,I) + ERRWT(K)*BB(I,1)**2
C                 IF (IT.GT.97) THEN
C                    CALL DBPR('K     ',6, K,1)
C                    CALL DBPRDB('PRDERR ',8,PRDERR,NSMPL*P)
C                 ENDIF
              ENDIF
 400      CONTINUE
         ENDIF
      ENDIF

1000  CONTINUE
C  end of time loop

C
      DO 45 IT=NSTART,NSMPL
         DO 40 I=1,P
  40        WW(I)=0.0
         DO 41 I=1,P
           DO 41 J=1,P
  41        WW(I)=WW(I) + B(1,I,J) *EY(IT,J)
         DO 45 I=1,P
  45        EY(IT,I)=Y(IT,I) - WW(I)
C
C    Start multi-step prediction loop
C
      IF (NSMPL .LT. NPRED) THEN
C  B(1,,) now needs to be filled in as I (storage was previously use for B0).
      DO 2298 I=1,P
         DO 2298 J=1,P
2298         B(1,I,J)=0.0
      DO 2299 I=1,P
2299         B(1,I,I)=1.0

C
C     Ensure A(0) = I by inverting A(0) and multiplying through
C
      DO 2300 I=1,P
         DO 2300 J=1,P
2300         BB(I,J)=A(1,I,J)

C      CALL INVERS(BB,P,IS,DETOM)
C     invert in place. 
      CALL DGETRF( P, P, BB, IS, IPIV, INFO )
C  For inverse call DGETRI, for solve call DGETRS.
      CALL DGETRI( P, BB, IS, IPIV, AA, IS*IS, INFO )
C      CALL DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO )

      DO 2302 L=1,IA
         DO 2301 I=1,P
            DO 2301 J=1,P
               AA(I,J)=A(L,I,J)
2301            A(L,I,J)=0.0D+0
         DO 2302 I=1,P
            DO 2302 J=1,P
               DO 2302 K=1,P
2302               A(L,I,J)=A(L,I,J)+BB(I,K)*AA(K,J)
      DO 2304 L=1,IB
         DO 2303 I=1,P
            DO 2303 J=1,P
               AA(I,J)=B(L,I,J)
2303            B(L,I,J)=0.0D+0
         DO 2304 I=1,P
            DO 2304 J=1,P
               DO 2304 K=1,P
2304               B(L,I,J)=B(L,I,J)+BB(I,K)*AA(K,J)
      DO 2306 L=1,IC
         DO 2305 I=1,P
            DO 2305 J=1,M
               AA(I,J)=C(L,I,J)
2305            C(L,I,J)=0.0D+0
         DO 2306 I=1,P
            DO 2306 J=1,M
               DO 2306 K=1,P
2306               C(L,I,J)=C(L,I,J)+BB(I,K)*AA(K,J)
      DO 2308 IT=NSMPL+1,NPRED
         DO 2307 I=1,P
            AA(I,1)=TREND(IT,I)
2307         TREND(IT,I)=0.0D+0
         DO 2308 I=1,P
            DO 2308 K=1,P
2308            TREND(IT,I)=TREND(IT,I) + BB(I,K)*AA(I,1)

      DO 2000 IT=NSMPL+1,NPRED
C  
      DO 2001 I=1,P
2001         EY(IT,I)= TREND(IT,I)
C
      IF (IA.GE.2) THEN
        DO 2002 L=2,IA
         DO 2002 I=1,P
            DO 2002 J=1,P
                IF ((IT+1-L) .LE.NSMPL) THEN
                   EY(IT,I)=EY(IT,I)-A(L,I,J)* Y(IT+1-L,J)
                ELSE
                   EY(IT,I)=EY(IT,I)-A(L,I,J)*EY(IT+1-L,J)
                ENDIF
2002    CONTINUE
      ENDIF
      IF (IB.GE.2) THEN
         DO 2004 L=2,IB
            IF ((IT+1-L).LE.NSMPL) THEN
               DO 2003 I=1,P
                 DO 2003 J=1,P
         EY(IT,I)=EY(IT,I)+B(L,I,J)*(Y(IT+1-L,J)-EY(IT+1-L,J))
2003           CONTINUE
            ENDIF
2004     CONTINUE
      ENDIF
C
      DO 2005 L=1,IC
         DO 2005 I=1,P
            DO 2005 J=1,M
                  EY(IT,I)=EY(IT,I)+C(L,I,J)*U(IT+1-L,J)
2005  CONTINUE

2000  CONTINUE
      ENDIF
C  end of multi-step prediction loop

      RETURN 
      END

            
      SUBROUTINE KFP(EY, HPERR, PRDERR, ERRWT,
     + M,N,P,NSMPL,NPRED,NACC,U,Y, F,G,H,FK, Q,R, GAIN,Z0,P0,
     + ITH,PARM,AP,IP,JP,ICT,CONST,AN,IN,JN,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)

C
C Put parameters into arrays (as in S function setArrays) and call KF
C
C  The state and tracking error are not calculated.
C       Use KF if these are needed.
C
C  It is assummed that M,N,P, the dimensions of the parameter
C    arrays - are given. Trying to calculate these causes problems.
C
      INTEGER HPERR
      INTEGER M,N,P, NSMPL, NPRED, NACC
      INTEGER ITH,ICT,IP(ITH),JP(ITH),IN(ICT),JN(ICT)
      INTEGER AP(ITH),AN(ICT)

      DOUBLE PRECISION EY(NPRED,P), PRDERR(NSMPL,P)
      DOUBLE PRECISION ERRWT(HPERR)
C      DOUBLE PRECISION STATE(NPRED,N),TRKERR(NPRED,N,N)
      DOUBLE PRECISION STATE(1,1),TRKERR(1,1,1)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
      DOUBLE PRECISION F(N,N),G(N,M),H(P,N),FK(N,P),R(P,P),Q(N,N)
      DOUBLE PRECISION  Z0(N), P0(N,N)

      INTEGER LSTATE, LTKERR
      INTEGER GAIN

      DOUBLE PRECISION A(IS,IS),AA(IS,IS),PP(IS,IS),QQ(N,N),RR(P,P)
      DOUBLE PRECISION Z(IS), ZZ(IS), WW(IS)
      INTEGER IPIV(IS,IS)

C..bug in S: passing characters is unreliable
C   use integer for AP and AN...
      DOUBLE PRECISION PARM(ITH),CONST(ICT)
C  state and trkerr are not used but must be passed to KF
C 
      INTEGER I,J
C
      LSTATE = 0
      LTKERR = 0

      DO 1 I=1,N
            DO 1 J=1,N
1              F(I,J) = 0.0D+0
      DO 2 I=1,N
            DO 2 J=1,M
2              G(I,J) = 0.0D+0
      DO 3 I=1,P
            DO 3 J=1,N
3              H(I,J) = 0.0D+0
      DO 4 I=1,N
            DO 4 J=1,P
4              FK(I,J) = 0.0D+0
      DO 5 I=1,N
            DO 5 J=1,N
5              Q(I,J) = 0.0D+0
      DO 6 I=1,P
            DO 6 J=1,P
6              R(I,J) = 0.0D+0
      DO 7 I=1,P
7              Z0(I) = 0.0D+0
      IF (ITH.GT.0) THEN
         DO 101 I=1,ITH
            IF   (AP(I).EQ.1) THEN  
               F(IP(I),JP(I)) = PARM(I)
            ELSEIF(AP(I).EQ.2) THEN
               G(IP(I),JP(I)) = PARM(I)
            ELSEIF(AP(I).EQ.3) THEN 
               H(IP(I),JP(I)) = PARM(I)   
            ELSEIF(AP(I).EQ.4) THEN 
              FK(IP(I),JP(I)) = PARM(I)   
            ELSEIF(AP(I).EQ.5) THEN 
               Q(IP(I),JP(I)) = PARM(I)   
            ELSEIF(AP(I).EQ.6) THEN 
               R(IP(I),JP(I)) = PARM(I)   
            ELSEIF(AP(I).EQ.7) THEN 
               Z0(IP(I)) = PARM(I)   
            ELSEIF(AP(I).EQ.8) THEN 
               P0(IP(I),JP(I)) = PARM(I)   
            ENDIF
101      CONTINUE   
      ENDIF
      IF (ICT.GT.0) THEN
         DO 102 I=1,ICT
            IF   (AN(I).EQ.1) THEN 
               F(IN(I),JN(I)) = CONST(I)
            ELSEIF(AN(I).EQ.2)  THEN
               G(IN(I),JN(I)) = CONST(I)
            ELSEIF(AN(I).EQ.3)  THEN
               H(IN(I),JN(I)) = CONST(I)   
            ELSEIF(AN(I).EQ.4) THEN 
              FK(IN(I),JN(I)) = CONST(I)   
            ELSEIF(AN(I).EQ.5) THEN 
               Q(IN(I),JN(I)) = CONST(I)   
            ELSEIF(AN(I).EQ.6) THEN 
               R(IN(I),JN(I)) = CONST(I)   
            ELSEIF(AN(I).EQ.7) THEN 
               Z0(IN(I)) = CONST(I)   
            ELSEIF(AN(I).EQ.8) THEN 
               P0(IN(I),JN(I)) = CONST(I)   
            ENDIF
102      CONTINUE   
      ENDIF

      CALL KF(EY, HPERR, PRDERR, ERRWT, LSTATE,STATE, LTKERR, TRKERR,
     + M,N,P,NSMPL,NPRED,NACC,  U,Y, F,G,H,FK, Q,R, GAIN,Z0,P0,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)
      RETURN
      END
C

      SUBROUTINE KFPRJ(PROJ, DSCARD, HORIZ, NHO,
     + EY, M,N,P, NACC,  U,Y, F,G,H,FK, Q,R, GAIN,Z0,P0,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)

C  multiple calls to KF for prediction at given horizons.
C     See S program project.
C
C  The state and tracking error are not calculate.

      INTEGER DSCARD, NHO, HORIZ(NHO)
      INTEGER M,N,P, NACC

      DOUBLE PRECISION PROJ(NHO,NACC,P)
      DOUBLE PRECISION EY(NACC,P)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
      DOUBLE PRECISION F(N,N),G(N,M),H(P,N),FK(N,P),R(P,P),Q(N,N)
      DOUBLE PRECISION  Z0(N), P0(N,N)

      INTEGER GAIN

      DOUBLE PRECISION A(IS,IS),AA(IS,IS),PP(IS,IS),QQ(N,N),RR(P,P)
      DOUBLE PRECISION Z(IS), ZZ(IS), WW(IS)
      INTEGER IPIV(IS,IS)

C  state and trkerr are not used but must be passed to KF
C 
      INTEGER LSTATE, LTKERR
      INTEGER HO,J, IT, MHORIZ
      INTEGER HPERR
      DOUBLE PRECISION PRDERR(1,1), ERRWT(1)
      DOUBLE PRECISION STATE(1,1),TRKERR(1,1,1)

      LSTATE = 0
      LTKERR = 0
      HPERR  = 0
      MHORIZ = HORIZ(1)
      DO 1 I=2, NHO
 1       MHORIZ=MIN(MHORIZ,HORIZ(I))

      DO 10 IT=DSCARD, (NACC-MHORIZ)
C       this assumes HORIZ is sorted in ascending order
        IF (IT.GT.(NACC-HORIZ(NHO))) THEN
            NHO = NHO-1
C            CALL DBPR('NHO   ',6, NHO,1)
        ENDIF

        CALL KF(EY, HPERR, PRDERR, ERRWT, LSTATE,STATE, LTKERR,TRKERR,
     +     M,N,P, IT , NACC,NACC,  U,Y, F,G,H,FK, Q,R, GAIN,Z0,P0,
     +     IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)

        DO 4 HO=1,NHO
            DO 4 J=1,P
              PROJ(HO,IT+HORIZ(HO),J) = EY(IT+HORIZ(HO),J) 
4     CONTINUE
10    CONTINUE

      RETURN
      END

      SUBROUTINE KFEPR(COV, DSCARD, HORIZ, NH, NT,
     + EY, M,N,P, NPRED,NACC,  U,Y, F,G,H,FK, Q,R, GAIN,Z0,P0,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)

C  multiple calls to KF for prediction evaluation.
C     See S program predictions.cov.TSmodel
C
C  The state and tracking error are not calculate.

      INTEGER DSCARD, NH, HORIZ(NH), NT(NH)
      INTEGER M,N,P, NPRED, NACC

      DOUBLE PRECISION COV(NH,P,P)
      DOUBLE PRECISION EY(NPRED,P)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
      DOUBLE PRECISION F(N,N),G(N,M),H(P,N),FK(N,P),R(P,P),Q(N,N)
      DOUBLE PRECISION  Z0(N), P0(N,N)

      INTEGER GAIN

      DOUBLE PRECISION A(IS,IS),AA(IS,IS),PP(IS,IS),QQ(N,N),RR(P,P)
      DOUBLE PRECISION Z(IS), ZZ(IS), WW(IS)
      INTEGER IPIV(IS,IS)

C  state and trkerr are not used but must be passed to KF
C 
      INTEGER LSTATE, LTKERR
      INTEGER I,J, IT, HI
      INTEGER HPERR
      DOUBLE PRECISION PRDERR(1,1), ERRWT(1), MF
      DOUBLE PRECISION STATE(1,1),TRKERR(1,1,1)

C
C        CALL DBPR('NPRED ',6, NPRED,1)
C        CALL DBPR('HORIZ ',6, HORIZ(1),1)
C        CALL DBPR('DSCARD',7, DSCARD,1)
      LSTATE = 0
      LTKERR = 0
      HPERR  = 0
      DO 1 I=1,NH
1        NT(I) = 0
      DO 2 K=1,NH
         DO 2 I=1,P
            DO 2 J=1,P
2               COV(K,I,J)= 0.0D0

      DO 10 IT=DSCARD, 1+NPRED-HORIZ(1)

        CALL KF(EY, HPERR, PRDERR, ERRWT, LSTATE,STATE, LTKERR,TRKERR,
     +     M,N,P, IT ,NPRED,NACC,  U,Y, F,G,H,FK, Q,R, GAIN,Z0,P0,
     +     IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)
C       this assumes HORIZ is sorted in ascending order


        IF ((IT-1+HORIZ(NH)).GT.NPRED) THEN
           NH = NH-1
        ENDIF
        DO 4 I=1,NH
           HI = IT-1+HORIZ(I)
           DO 4 J=1,P
4            EY(I,J) = EY(HI,J) - Y(HI,J)
        DO 5 K=1,NH
           NT(K) = NT(K)+1
           MF= DBLE(NT(K)-1)/DBLE(NT(K))
           DO 5 I=1,P
              DO 5 J=1,P
                COV(K,I,J)= COV(K,I,J)*MF + EY(K,I)*EY(K,J)/NT(K)
5     CONTINUE

10    CONTINUE

      RETURN
      END


      SUBROUTINE ARMAP(EY, HPERR, PRDERR, ERRWT,
     + M,P,IA,IB,IC,NSMPL,NPRED,NACC,  U,Y , A,B,C, TREND,
     + ITH,PARM,AP,LP,IP,JP,ICT,CONST,AN,LN,IN,JN, 
     + IS,AA,BB,WW, IPIV)
C
C Put parameters into arrays (as in S function setArrays) and call ARMA
C
C  It is assummed that M,P,IA,IB, and IC - the dimensions of the parameter
C    arrays - are given. Trying to calculate these causes problems.
C
      INTEGER M,P,IA,IB,IC, NSMPL, NACC
      INTEGER HPERR
      INTEGER ITH,ICT,IP(ITH),JP(ITH),LP(ITH),IN(ICT),JN(ICT),LN(ICT)

      DOUBLE PRECISION EY(NPRED,P), PRDERR(NSMPL,P)
      DOUBLE PRECISION ERRWT(HPERR)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
      DOUBLE PRECISION A(IA,P,P),B(IB,P,P),C(IC,P,M), TREND(NPRED,P) 
      DOUBLE PRECISION AA(IS,IS), BB(IS,IS), WW(IS)
      INTEGER IPIV(IS,IS)

C..bug in S: passing characters is unreliable
C   use integer for AP and AN...
      INTEGER AP(ITH),AN(ICT)
      DOUBLE PRECISION PARM(ITH),CONST(ICT)
C 
      INTEGER I,J,L
C
      DO 1 L=1,IA
         DO 1 I=1,P
            DO 1 J=1,P
1              A(L,I,J) = 0.0
      DO 2 L=1,IB
         DO 2 I=1,P
            DO 2 J=1,P
2              B(L,I,J) = 0.0 
      DO 3 L=1,IC
         DO 3 I=1,P
            DO 3 J=1,M
3              C(L,I,J) = 0.0
      DO 4 I=1,NPRED
      DO 4 J=1,P
4         TREND(I,J) = 0.0
C       IA=0
C       IB=0
C       IC=0
      IF (ITH.GT.0) THEN
         DO 101 I=1,ITH
            IF   (AP(I).EQ.1) THEN  
               A(LP(I),IP(I),JP(I)) = PARM(I)
C               IA=MAX(IA,LP(I))
            ELSEIF(AP(I).EQ.2) THEN
               B(LP(I),IP(I),JP(I)) = PARM(I)
C               IB=MAX(IB,LP(I))
            ELSEIF(AP(I).EQ.3) THEN 
               C(LP(I),IP(I),JP(I)) = PARM(I)   
C               IC=MAX(IC,LP(I))
            ELSEIF(AP(I).EQ.4) THEN 
               TREND(IP(I),JP(I)) = PARM(I)  
            ENDIF
101      CONTINUE   
      ENDIF
      IF (ICT.GT.0) THEN
         DO 102 I=1,ICT
            IF   (AN(I).EQ.1) THEN 
               A(LN(I),IN(I),JN(I)) = CONST(I)
C               IA=MAX(IA,LN(I))
            ELSEIF(AN(I).EQ.2)  THEN
               B(LN(I),IN(I),JN(I)) = CONST(I)
C               IB=MAX(IB,LN(I))
            ELSEIF(AN(I).EQ.3)  THEN
               C(LN(I),IN(I),JN(I)) = CONST(I)   
C               IC=MAX(IC,LN(I))
            ELSEIF(AN(I).EQ.4) THEN 
               TREND(IN(I),JN(I)) = CONST(I)  
            ENDIF
102      CONTINUE   
      ENDIF
      
      CALL ARMA(EY, HPERR, PRDERR, ERRWT,
     +M,P,IA,IB,IC,NSMPL,NPRED,NACC,U,Y, A,B,C, TREND, 
     + IS,AA,BB,WW, IPIV)
      RETURN
      END

      SUBROUTINE RMAPRJ(PROJ, DSCARD, HORIZ, NHO,
     + EY, M,P,IA,IB,IC,NACC,  U,Y , A,B,C, TREND, 
     + IS,AA,BB,WW, IPIV)

C  multiple calls to ARMA for for prediction at given horizons.
C     See S program horizonForecasts.TSmodel
C
C  Note: If DSCARD is too small then forecasting starts based on little (or 
C          no) data and the results will be spurious.

      INTEGER  DSCARD, NHO, HORIZ(NHO)
      INTEGER M,P, IA, IB, IC, NACC
      INTEGER HPERR

      DOUBLE PRECISION PROJ(NHO,NACC,P)
      DOUBLE PRECISION EY(NACC,P)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
      DOUBLE PRECISION A(IA,P,P),B(IB,P,P),C(IC,P,M), TREND(NACC,P)
      DOUBLE PRECISION AA(IS,IS), BB(IS,IS), WW(IS)
      DOUBLE PRECISION PRDERR(1,1), ERRWT(1)
      INTEGER IPIV(IS,IS)

      INTEGER I,J, IT, HO, MHORIZ

      HPERR = 0
      MHORIZ = HORIZ(1)
      DO 1 I=2, NHO
 1       MHORIZ=MIN(MHORIZ,HORIZ(I))

      DO 10 IT=DSCARD, (NACC-MHORIZ)
C       this assumes HORIZ is sorted in ascending order
        IF (IT.GT.(NACC-HORIZ(NHO))) NHO = NHO-1

        CALL ARMA(EY, HPERR, PRDERR, ERRWT,                  
     +     M,P,IA,IB,IC,IT,NACC,NACC,  U,Y , A,B,C, TREND, 
     +     IS,AA,BB,WW, IPIV)

        DO 4 HO=1,NHO
            DO 4 J=1,P
4             PROJ(HO,IT+HORIZ(HO),J) = EY(IT+HORIZ(HO),J) 
10    CONTINUE

      RETURN
      END


      SUBROUTINE RMAEPR(COV, DSCARD, HORIZ, NH, NT,
     + EY, M,P,IA,IB,IC,NPRED,NACC,  U,Y , A,B,C, TREND,
     + IS,AA,BB,WW, IPIV)

C  multiple calls to ARMA for prediction analysis.
C     See S program forecastCov
C
C  Note: If DSCARD is too small then forecasting starts based on little (or 
C          no) data and the results will be spurious.

      INTEGER DSCARD, NH, HORIZ(NH), NT(NH)
      INTEGER M,P, IA, IB, IC, NPRED, NACC

      DOUBLE PRECISION COV(NH,P,P)
      DOUBLE PRECISION EY(NPRED,P)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
      DOUBLE PRECISION A(IA,P,P),B(IB,P,P),C(IC,P,M), TREND(NPRED,P)
      DOUBLE PRECISION AA(IS,IS),BB(IS,IS), WW(IS)
      INTEGER IPIV(IS,IS)


      INTEGER HPERR
      DOUBLE PRECISION PRDERR(1,1), ERRWT(1), MF

      INTEGER I,J, IT, HI

C
C        CALL DBPR('NPRED ',6, NPRED,1)
C        CALL DBPR('HORIZ ',6, HORIZ(1),1)
C        CALL DBPR('DSCARD',7, DSCARD,1)
      HPERR = 0
      DO 1 I=1,NH
1        NT(I) = 0
      DO 2 K=1,NH
         DO 2 I=1,P
            DO 2 J=1,P
2               COV(K,I,J)= 0.0D0

      DO 10 IT=DSCARD, 1+NPRED-HORIZ(1)

        CALL ARMA(EY, HPERR, PRDERR, ERRWT,                  
     +     M,P,IA,IB,IC,IT,NPRED,NACC,  U,Y , A,B,C, TREND, 
     +     IS,AA,BB,WW, IPIV)

C       Eliminate longer horizons as date runs out.
C       This assumes HORIZ is sorted in ascending order.
        IF ((IT-1+HORIZ(NH)).GT.NPRED) THEN
           NH = NH-1
        ENDIF
        DO 4 I=1,NH
           HI = IT-1+HORIZ(I)
           DO 4 J=1,P
4            EY(I,J) = EY(HI,J) - Y(HI,J)
        DO 5 K=1,NH
           NT(K) = NT(K)+1
           MF= DBLE(NT(K)-1)/DBLE(NT(K))
           DO 5 I=1,P
              DO 5 J=1,P
                COV(K,I,J)= COV(K,I,J)*MF + EY(K,I)*EY(K,J)/NT(K)
5     CONTINUE

10    CONTINUE

      RETURN
      END

      SUBROUTINE DATEPR(COV, DSCARD, HORIZ, NH, NT, P, NPRED, ERR)

C     See S program predictions.cov.TSdata
C
      INTEGER DSCARD, NH, HORIZ(NH), NT(NH)
      INTEGER P, NPRED

      DOUBLE PRECISION COV(NH,P,P)
      DOUBLE PRECISION ERR(NPRED,P) 


      INTEGER I,J,K, IT, HI

      DOUBLE PRECISION  MF
C
C        CALL DBPR('NPRED ',6, NPRED,1)
C        CALL DBPR('HORIZ ',6, HORIZ(1),1)
C        CALL DBPR('DSCARD',7, DSCARD,1)

      DO 1 I=1,NH
1        NT(I) = 0
      DO 2 K=1,NH
         DO 2 I=1,P
            DO 2 J=1,P
2               COV(K,I,J)= 0.0D0

      DO 10 IT=DSCARD, 1+NPRED-HORIZ(1)
C       this assumes HORIZ is sorted in ascending order
        IF ((IT-1+HORIZ(NH)).GT.NPRED) THEN
           NH = NH-1
        ENDIF
        DO 5 K=1,NH
           NT(K) = NT(K)+1
           MF= DBLE(NT(K)-1)/DBLE(NT(K))
           HI = IT-1+HORIZ(K)
           DO 5 I=1,P
              DO 5 J=1,P
                COV(K,I,J)= COV(K,I,J)*MF + ERR(HI,I)*ERR(HI,J)/NT(K)
5     CONTINUE
10    CONTINUE
      RETURN
      END

C routines for curvature calculation
C
      SUBROUTINE GENDK(D,ITH,X0,DELTA0,N,ND,F0,RD,HAPROX,HDIAG,
     + DAPROX, X, DELTA,F1,F2,
     + M,P,NSMPL,NACC,  U,Y , 
     + AP,IP,JP,ICT,CONST,AN,IN,JN,
     + NS,Z0,P0,F,G,H,FK,Q,R,GAIN,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)
C 
C
C      The function must have a single vector arguement X.
C  X0   the parameter vector.
C  X    is the working copy (altered by DELTA).
C  ITH   is the length of the parameter vector.
C  F0  is the value (in sample/residual space) of the function.
C      (only the space is needed, the function is calculated).
C  N   is the dimension of the sample space (length of F0).
C  DELTA0  gives the fraction of X to use for the initial 
C           numerical approximation.
C  ND  is the number of columns of matrix D.( first
C               der. & lower triangle of Hessian)
C  EPS     is used for zero elements of X.
C  RD       the number of Richardson improvement iterations.
C  V=2       reduction factor for Richardson iterations.
C       V could be a parameter but the way the reduction formula is
C        coded assumes it is =2
C

      INTEGER ITH,N,RD

      DOUBLE PRECISION  X0(ITH),X(ITH), D(N,ND),DELTA0(ITH)
      DOUBLE PRECISION  F0(N), DAPROX(N,RD),HDIAG(N,ITH),HAPROX(N,RD)
      DOUBLE PRECISION DELTA(ITH),F1(N),F2(N)
C      
      INTEGER I,J,K,II,MC,UP
      DOUBLE PRECISION V,MD
C
C  parameters passed directly to ARMAp and/or KFp:
C
      INTEGER HPERR
      INTEGER M,NS,P, NSMPL, NACC
C      INTEGER IA,IB,IC

      DOUBLE PRECISION PRDERR(1,1), ERRWT(1)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
C      DOUBLE PRECISION A(IA,P,P),B(IB,P,P),C(IC,P,M)
C
C      F, Q, and R are used for scratch space in the call to ARMAP instead of:
C      DOUBLE PRECISION AA(IS,IS), BB(IS,IS), WW(IS)
C        this could cause some problems ... some checks are made.

C       Z0(NS) is used for TREND(P) in ARMA models
C     PARM(ITH) for ARMAP/KFP is X(ITH) in GEND, EY is function value
C   
      INTEGER ICT,IP(ITH),JP(ITH),IN(ICT),JN(ICT)    
C      INTEGER LP(ITH), LN(ICT) 

C      DOUBLE PRECISION Z(NSMPL,NS),TRKERR(NSMPL,NS,NS)
      DOUBLE PRECISION Z0(NS), P0(NS,NS)
      DOUBLE PRECISION F(NS,NS),G(NS,M),H(P,NS)
      DOUBLE PRECISION FK(NS,P),Q(NS,NS),R(P,P)

      INTEGER GAIN         

      DOUBLE PRECISION A(IS,IS),AA(IS,IS),PP(IS,IS),QQ(N,N),RR(P,P)
      DOUBLE PRECISION Z(IS), ZZ(IS), WW(IS)
      INTEGER IPIV(IS,IS)

C..bug in S: passing characters is unreliable
C   use integer for AP and AN...
      INTEGER AP(ITH),AN(ICT)
      DOUBLE PRECISION CONST(ICT)

C      CALL DBPR('starting gend N=',16, N,1)
C      CALL DBPR('            ITH=',16, ITH,1)
C      CALL DBPR('             ND=',16, ND,1)

      HPERR = 0
      V=2.0
      DO 1 II=1,ITH   
1          X(II) =X0(II)
      CALL KFP(F0, HPERR,PRDERR, ERRWT,
     +      M,NS,P,NSMPL,NSMPL,NACC,U,Y, F,G,H,FK, Q,R, GAIN, Z0,P0,
     +      ITH,X,AP,IP,JP,ICT,CONST,AN,IN,JN,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)

C                   each parameter  - first deriv. & hessian diagonal
      DO 100 I=1,ITH
         DO 10 II=1,ITH   
10          DELTA(II) =DELTA0(II)
C                                 successively reduce DELTA 
C
C  This could be done without both X and X0 by adding and then subtracting
C   DELTA, but accumulated round off error seems to affect the result.
         DO 20 K=1,RD 
            X(I)=X0(I)+DELTA(I)
            CALL KFP(F1, HPERR,PRDERR, ERRWT,
     +         M,NS,P,NSMPL,NSMPL,NACC,U,Y, F,G,H,FK, Q,R, GAIN, Z0,P0,
     +         ITH,X,AP,IP,JP,ICT,CONST,AN,IN,JN,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)

            X(I)=X0(I)-DELTA(I) 
            CALL KFP(F2, HPERR,PRDERR, ERRWT,
     +         M,NS,P,NSMPL,NSMPL,NACC,U,Y, F,G,H,FK, Q,R, GAIN, Z0,P0,
     +         ITH,X,AP,IP,JP,ICT,CONST,AN,IN,JN,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)

            X(I)=X0(I) 
            DO 15 II=1,N   
15             DAPROX(II,K) = (F1(II) - F2(II))  / (2.0*DELTA(I))  
            DO 16 II=1,N   
16             HAPROX(II,K) =(F1(II)-2.0*F0(II)+F2(II))/ DELTA(I)**2 
            DELTA(I) = DELTA(I)/V   
20       CONTINUE   
         DO 30 MC=1,(RD-1)
           MD=4.0D0**MC
           DO 30 K=1,(RD-MC)
             DO 25 II=1,N   
25             DAPROX(II,K)=(DAPROX(II,K+1)*MD-DAPROX(II,K))/(MD-1)
             DO 26 II=1,N   
26             HAPROX(II,K)=(HAPROX(II,K+1)*MD-HAPROX(II,K))/(MD-1)
30       CONTINUE 
         DO 31 II=1,N   
31         D(II,I) = DAPROX(II,1)
         DO 32 II=1,N   
32         HDIAG(II,I) = HAPROX(II,1)
100   CONTINUE
C
C                  2nd derivative  - do lower half of hessian only
      UP = ITH
C      CALL DBPR('2nd deriv. UP=\n',16, UP,1)
      DO 200 I=1,ITH   
         DO 200 J=1,I 
            UP = UP + 1
C      CALL DBPR('      UP=\n',11, UP,1)
            IF (I.EQ.J) THEN
               DO 120 II=1,N   
120               D(II,UP) = HDIAG(II,I)
            ELSE 
               DO 121 II=1,ITH   
121               DELTA(II) =DELTA0(II)
C                                successively reduce DELTA 
               DO 150 K=1,RD
                 X(I)=X0(I)+DELTA(I) 
                 X(J)=X0(J)+DELTA(J) 
                 CALL KFP(F1, HPERR,PRDERR, ERRWT,
     +         M,NS,P,NSMPL,NSMPL,NACC,U,Y, F,G,H,FK, Q,R, GAIN, Z0,P0,
     +         ITH,X,AP,IP,JP,ICT,CONST,AN,IN,JN,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)

                 X(I)=X0(I)-DELTA(I) 
                 X(J)=X0(J)-DELTA(J) 
                 CALL KFP(F2, HPERR,PRDERR, ERRWT,
     +         M,NS,P,NSMPL,NSMPL,NACC,U,Y, F,G,H,FK, Q,R, GAIN, Z0,P0,
     +         ITH,X,AP,IP,JP,ICT,CONST,AN,IN,JN,
     + IS, A, AA, PP, QQ, RR, Z, ZZ, WW, IPIV)

                 X(I)=X0(I) 
                 X(J)=X0(J) 
                 DO 130 II=1,N   
130                 DAPROX(II,K)=(F1(II)-2.0*F0(II)+F2(II)
     ,          -HDIAG(II,I)*DELTA(I)**2-HDIAG(II,J)*DELTA(J)**2)/
     ,                    (2.0*DELTA(I)*DELTA(J))   
                 DO 140 II=1,ITH   
140                 DELTA(II) = DELTA(II)/V
150            CONTINUE
               DO 190 MC=1,(RD-1)
                 MD=4.0D0**MC
                 DO 170 K=1,(RD-MC)
                  DO 170 II=1,N   
170                DAPROX(II,K)=
     ,                (DAPROX(II,K+1)*MD-DAPROX(II,K))/(MD-1.0)
                 DO 180 II=1,N   
180                 D(II,UP) = DAPROX(II,1)
190            CONTINUE
            ENDIF  
200   CONTINUE
C      DBPRDB('gend returning D[1,1]=',24, D(1,1),1)
      RETURN
      END

C routines for curvature calculation
C
      SUBROUTINE GENDA(D,ITH,X0,DELTA0,N,ND,F0,RD,HAPROX,HDIAG,
     + DAPROX, X, DELTA,F1,F2,
     + M,P,NSMPL,NACC,  U,Y , 
     + AP,IP,JP,ICT,CONST,AN,IN,JN,
     + LP,LN,IA,IB,IC,A,B,C,TREND,
     + IS,AA,BB,WW, IPIV)
C 
C
C      The function must have a single vector arguement X.
C  X0   the parameter vector.
C  X    is the working copy (altered by DELTA).
C  ITH   is the length of the parameter vector.
C  F0  is the value (in sample/residual space) of the function.
C      (only the space is needed, the function is calculated).
C  N   is the dimension of the sample space (length of F0).
C  DELTA0  gives the fraction of X to use for the initial 
C           numerical approximation.
C  ND  is the number of columns of matrix D.( first
C               der. & lower triangle of Hessian)
C  EPS     is used for zero elements of X.
C  RD       the number of Richardson improvement iterations.
C  V=2       reduction factor for Richardson iterations.
C       V could be a parameter but the way the reduction formula is
C        coded assumes it is =2
C

      INTEGER ITH,N,RD

      DOUBLE PRECISION  X0(ITH),X(ITH), D(N,ND),DELTA0(ITH)
      DOUBLE PRECISION  F0(N), DAPROX(N,RD),HDIAG(N,ITH),HAPROX(N,RD)
      DOUBLE PRECISION DELTA(ITH),F1(N),F2(N)
C      
      INTEGER I,J,K,II,MC,UP
      DOUBLE PRECISION V,MD
C
C  parameters passed directly to ARMAp and/or KFp:
C
      INTEGER HPERR
      INTEGER M,P,NSMPL, NACC
C      INTEGER NS
      INTEGER IA,IB,IC

      DOUBLE PRECISION PRDERR(1,1), ERRWT(1)
      DOUBLE PRECISION Y(NACC,P),U(NACC,M) 
      DOUBLE PRECISION A(IA,P,P),B(IB,P,P),C(IC,P,M)
C
      DOUBLE PRECISION AA(IS,IS), BB(IS,IS), WW(IS)

C     PARM(ITH) for ARMAP/KFP is X(ITH) in GEND, EY is function value
C   
      INTEGER ICT,IP(ITH),JP(ITH),LP(ITH),IN(ICT),JN(ICT),LN(ICT)    

C      DOUBLE PRECISION Z(NSMPL,NS),TRKERR(NSMPL,NS,NS)
      DOUBLE PRECISION TREND(NACC,P)
C      DOUBLE PRECISION P0(NS,NS)
C      DOUBLE PRECISION F(NS,NS),G(NS,M),H(P,NS)
C      DOUBLE PRECISION FK(NS,P),Q(NS,NS),R(P,P)

C      INTEGER GAIN         
C
C..bug in S: passing characters is unreliable
C   use integer for AP and AN...
      INTEGER AP(ITH),AN(ICT)
      DOUBLE PRECISION CONST(ICT)
      INTEGER IPIV(IS,IS)

C      CALL DBPR('starting gend N=',16, N,1)
C      CALL DBPR('            ITH=',16, ITH,1)
C      CALL DBPR('             ND=',16, ND,1)


      HPERR = 0
      V=2.0
      DO 1 II=1,ITH   
1          X(II) =X0(II)
      CALL ARMAP(F0, HPERR,PRDERR, ERRWT,
     +      M,P,IA,IB,IC,NSMPL,NSMPL,NACC,  U,Y , A,B,C, TREND,
     +      ITH,X,AP,LP,IP,JP,ICT,CONST,AN,LN,IN,JN, 
     +      IS,AA,BB,WW, IPIV)

C                   each parameter  - first deriv. & hessian diagonal
      DO 100 I=1,ITH
         DO 10 II=1,ITH   
10          DELTA(II) =DELTA0(II)
C                                 successively reduce DELTA 
C
C  This could be done without both X and X0 by adding and then subtracting
C   DELTA, but accumulated round off error seems to affect the result.
         DO 20 K=1,RD 
            X(I)=X0(I)+DELTA(I)
            CALL ARMAP(F1, HPERR,PRDERR, ERRWT,
     +         M,P,IA,IB,IC,NSMPL,NSMPL,NACC,  U,Y , A,B,C, TREND, 
     +         ITH,X,AP,LP,IP,JP,ICT,CONST,AN,LN,IN,JN, 
     +         IS,AA,BB,WW, IPIV)  
            
            X(I)=X0(I)-DELTA(I) 
            CALL ARMAP(F2, HPERR,PRDERR, ERRWT,
     +         M,P,IA,IB,IC,NSMPL,NSMPL,NACC,  U,Y , A,B,C, TREND,
     +         ITH,X,AP,LP,IP,JP,ICT,CONST,AN,LN,IN,JN, 
     +         IS,AA,BB,WW, IPIV)
            
            X(I)=X0(I) 
            DO 15 II=1,N   
15             DAPROX(II,K) = (F1(II) - F2(II))  / (2.0*DELTA(I))  
            DO 16 II=1,N   
16             HAPROX(II,K) =(F1(II)-2.0*F0(II)+F2(II))/ DELTA(I)**2 
            DELTA(I) = DELTA(I)/V   
20       CONTINUE   
         DO 30 MC=1,(RD-1)
           MD=4.0D0**MC
           DO 30 K=1,(RD-MC)
             DO 25 II=1,N   
25             DAPROX(II,K)=(DAPROX(II,K+1)*MD-DAPROX(II,K))/(MD-1)
             DO 26 II=1,N   
26             HAPROX(II,K)=(HAPROX(II,K+1)*MD-HAPROX(II,K))/(MD-1)
30       CONTINUE 
         DO 31 II=1,N   
31         D(II,I) = DAPROX(II,1)
         DO 32 II=1,N   
32         HDIAG(II,I) = HAPROX(II,1)
100   CONTINUE
C
C                  2nd derivative  - do lower half of hessian only
      UP = ITH
C      CALL DBPR('2nd deriv. UP=\n',16, UP,1)
      DO 200 I=1,ITH   
         DO 200 J=1,I 
            UP = UP + 1
C      CALL DBPR('      UP=\n',11, UP,1)
            IF (I.EQ.J) THEN
               DO 120 II=1,N   
120               D(II,UP) = HDIAG(II,I)
            ELSE 
               DO 121 II=1,ITH   
121               DELTA(II) =DELTA0(II)
C                                successively reduce DELTA 
               DO 150 K=1,RD
                 X(I)=X0(I)+DELTA(I) 
                 X(J)=X0(J)+DELTA(J) 
                 CALL ARMAP(F1, HPERR,PRDERR, ERRWT,
     +              M,P,IA,IB,IC,NSMPL,NSMPL,NACC, U,Y, A,B,C, TREND,
     +              ITH,X,AP,LP,IP,JP,ICT,CONST,AN,LN,IN,JN, 
     +              IS,AA,BB,WW, IPIV)
                 
                 X(I)=X0(I)-DELTA(I) 
                 X(J)=X0(J)-DELTA(J) 
                 CALL ARMAP(F2, HPERR,PRDERR, ERRWT,
     +              M,P,IA,IB,IC,NSMPL,NSMPL,NACC, U,Y, A,B,C, TREND,
     +              ITH,X,AP,LP,IP,JP,ICT,CONST,AN,LN,IN,JN, 
     +              IS,AA,BB,WW, IPIV)
                 
                 X(I)=X0(I) 
                 X(J)=X0(J) 
                 DO 130 II=1,N   
130                 DAPROX(II,K)=(F1(II)-2.0*F0(II)+F2(II)
     ,          -HDIAG(II,I)*DELTA(I)**2-HDIAG(II,J)*DELTA(J)**2)/
     ,                    (2.0*DELTA(I)*DELTA(J))   
                 DO 140 II=1,ITH   
140                 DELTA(II) = DELTA(II)/V
150            CONTINUE
               DO 190 MC=1,(RD-1)
                 MD=4.0D0**MC
                 DO 170 K=1,(RD-MC)
                  DO 170 II=1,N   
170                DAPROX(II,K)=
     ,                (DAPROX(II,K+1)*MD-DAPROX(II,K))/(MD-1.0)
                 DO 180 II=1,N   
180                 D(II,UP) = DAPROX(II,1)
190            CONTINUE
            ENDIF  
200   CONTINUE
C      DBPRDB('gend returning D[1,1]=',24, D(1,1),1)
      RETURN
      END
back to top