code  33080;
 boolean procedure MULTISTEP(X,XEND,Y,HMIN,HMAX,YMAX,EPS,
            FIRST,SAVE,DERIV,AVAILABLE,JACOBIAN,STIFF,N,OUT);
 value HMIN,HMAX,EPS,XEND,N,STIFF;
 boolean FIRST,AVAILABLE,STIFF;
 integer N;
 real X,XEND,HMIN,HMAX,EPS;
 array Y,YMAX,SAVE,JACOBIAN;
 procedure DERIV,OUT;
 begin own boolean ADAMS,WITH JACOBIAN;
        own integer M,SAME,KOLD;
        own real XOLD,HOLD,A0,TOLUP,TOL,TOLDWN,TOLCONV;
        boolean EVALUATE,EVALUATED,DECOMPOSE,DECOMPOSED,CONV;
        integer I,J,L,K,KNEW,FAILS;
        real H, CH, CHNEW,ERROR,DFI,C;
        array A[0:5],DELTA,LAST DELTA,DF[1:N],JAC[1:N, 1:N],AUX[1:3];
        integer array P[1:N];

        real procedure NORM2(AI); real AI;
        begin real S,A; S:= 1.0"-100;
                for I:= 1 step 1 until N do 
                begin A:= AI/YMAX[I]; S:= S + A * A end;
                NORM2:= S
        end NORM2;

        procedure RESET;
        begin if CH < HMIN/HOLD then CH:= HMIN/HOLD else 
                if CH > HMAX/HOLD then CH:= HMAX/HOLD;
                X:= XOLD; H:= HOLD * CH; C:= 1;
                for J:= 0 step M until K*M do 
                begin for I:= 1 step 1 until N do 
                        Y[J+I]:= SAVE[J+I] * C;
                        C:= C * CH
                end;
                DECOMPOSED:= false 
        procedure METHOD;
        begin I:= -39;
                if ADAMS then 
                begin for C:= 1,1,144,4,0,.5,1,.5,576,144,1,5/12,1,
                              .75,1/6,1436,576,4,.375,1,11/12,1/3,1/24,
                               2844,1436,1,251/720,1,25/24,35/72,
                               5/48,1/120,0,2844,0.1
                        do begin I:= I+ 1; SAVE[I]:= C end 
                end else 

                begin for C:= 1,1,9,4,0,2/3,1,1/3,36,20.25,1,6/11,
                       1,6/11,1/11,84.028,53.778,0.25,.48,1,.7,.2,.02,
                        156.25, 108.51, .027778, 120/274, 1, 225/274,
                        85/274, 15/274, 1/274, 0, 187.69, .0047361
                        do begin I:= I + 1; SAVE[I]:= C end 
                end 
        end METHOD;

        procedure ORDER;
        begin C:= EPS * EPS; J:= (K-1) * (K + 8)/2 - 38;
                for I:= 0 step 1 until K do A[I]:= SAVE[I+J];
                TOLUP  := C * SAVE[J + K + 1];
                TOL    := C * SAVE[J + K + 2];
                TOLDWN := C * SAVE[J + K + 3];
                TOLCONV:= EPS/(2 * N * (K + 2));
                A0:= A[0];  DECOMPOSE:= true;
        end ORDER;

        procedure EVALUATE JACOBIAN;
        begin EVALUATE:= false;
                DECOMPOSE:= EVALUATED:= true;
                if AVAILABLE then else 
                begin real D; array FIXY,FIXDY,DY[1:N];
                        for I:= 1 step 1 until N do 
                        FIXY[I]:= Y[I];
                        DERIV(FIXDY);
                        for J:= 1 step 1 until N do 
                        begin D:= if EPS > ABS(FIXY[J])
                                then EPS * EPS
                                else EPS * ABS(FIXY[J]);
                                Y[J]:= Y[J] + D; DERIV(DY);
                                for I:= 1 step 1 until N do 
                                JACOBIAN[I,J]:= (DY[I]-FIXDY[I])/D;
                                Y[J]:= FIXY[J]
                        end 
                end 
        end EVALUATE JACOBIAN;

        procedure DECOMPOSE JACOBIAN;
        begin DECOMPOSE:= false;
                DECOMPOSED:= true; C:= -A0 * H;
                for J:= 1 step 1 until N do 
                begin for I:= 1 step 1 until N do 
                        JAC[I,J]:= JACOBIAN[I,J] * C;
                        JAC[J,J]:= JAC[J,J] + 1
                end;
                AUX[2]:=1.0"-12;
                DEC(JAC,N,AUX,P)
        end DECOMPOSE JACOBIAN;

        procedure CALCULATE STEP AND ORDER;
        begin real A1,A2,A3;
                A1:= if K <= 1 then 0 else 
                     0.75 * (TOLDWN/NORM2(Y[K*M+I])) ** (0.5/K);
                A2:= 0.80 * (TOL/ERROR) ** (0.5/(K + 1));
                A3:= if K >= 5 or FAILS ^= 0
                     then 0 else 
                     0.70 * (TOLUP/NORM2(DELTA[I] - LAST DELTA[I])) **
                     (0.5/(K+2));

                if A1 > A2 and A1 > A3 then 
                begin KNEW:= K-1; CHNEW:= A1 end else 
                if A2 > A3 then 
                begin KNEW:= K  ; CHNEW:= A2 end else 
                begin KNEW:= K+1; CHNEW:= A3 end 
        end CALCULATE STEP AND ORDER;

        if FIRST then 
        begin FIRST:= false; M:= N;
                for I:= -1,-2,-3 do SAVE[I]:= 0;
                OUT(0,0);
                ADAMS:= not STIFF; WITH JACOBIAN:= not ADAMS;
                if WITH JACOBIAN then EVALUATE JACOBIAN;
                METHOD;
        NEW START: K:= 1; SAME:= 2; ORDER; DERIV(DF);
                H:= if not WITH JACOBIAN then HMIN else 
                SQRT(2 * EPS/SQRT(NORM2 (MATVEC(1,N,I,JACOBIAN,DF))));
                if H > HMAX then H:= HMAX else 
                if H < HMIN then H:= HMIN;
                XOLD:= X; HOLD:= H; KOLD:= K; CH:= 1;
                for I:= 1 step 1 until N do 
                begin SAVE[I]:= Y[I]; SAVE[M+I]:= Y[M+I]:= DF[I] * H
                end;
                OUT(0,0)
        end else 
        begin WITH JACOBIAN:= not ADAMS; CH:= 1;
                K:=KOLD; RESET; ORDER;
                DECOMPOSE:= WITH JACOBIAN
        end;
        for L:= 0 while X < XEND do 
        begin if X + H <= XEND then X:= X + H else 
                begin H:= XEND-X; X:= XEND; CH:= H/HOLD; C:= 1;
                        for J:= M step M until K*M do 
                        begin C:= C* CH;
                                for I:= J+1 step 1 until J+N do 
                                Y[I]:= Y[I] * C
                        end;
                        SAME:= if SAME<3 then 3 else SAME+1;
                end;

                comment PREDICTION;
                for L:= 1 step 1 until N do 
                begin for I:= L step M until (K-1)*M+L do 
                        for J:= (K-1)*M+L step -M until I do 
                        Y[J]:= Y[J] + Y[J+M];
                        DELTA[L]:= 0
                end;  EVALUATED:= false;

        comment CORRECTION AND ESTIMATION LOCAL ERROR;
        for L:= 1,2,3 do 
        begin DERIV(DF);
                for I:= 1 step 1 until N do 
                DF[I]:= DF[I] * H - Y[M+I];
                if WITH JACOBIAN then 
                begin if EVALUATE then EVALUATE JACOBIAN;
                        if DECOMPOSE then DECOMPOSE JACOBIAN;
                        SOL(JAC,N,P,DF)
                end;

                CONV:= true;
                for I:= 1 step 1 until N do 
                begin DFI:= DF[I];
                        Y[  I]:= Y[  I] + A0 * DFI;
                        Y[M+I]:= Y[M+I] +      DFI;
                        DELTA[I]:= DELTA[I] +  DFI;
                        CONV:= CONV and ABS(DFI) < TOLCONV * YMAX[I]
                end;
                if CONV then 
                begin ERROR:= NORM2(DELTA[I]);
                        goto CONVERGENCE
                end 
        comment ACCEPTANCE OR REJECTION;
        if not CONV then 
        begin if not WITH JACOBIAN then 
                begin EVALUATE:= WITH JACOBIAN:= SAME >= K
                           or H<1.1 * HMIN;
                        if not WITH JACOBIAN then CH:= CH/4;
                end else 
                if not DECOMPOSED then DECOMPOSE:= true else 
                if not EVALUATED  then EVALUATE := true else 
                if H > 1.1 * HMIN   then CH:= CH/4 else 
                if ADAMS            then goto TRY CURTISS else 
                begin SAVE[-1]:= 1; goto RETURN end;

                RESET
        end else CONVERGENCE:

        if ERROR > TOL then 
        begin FAILS:= FAILS + 1;
                if H > 1.1 * HMIN then 
                begin if FAILS > 2 then 
                        begin if ADAMS then 
                                begin ADAMS:= false; METHOD end;
                                KOLD:= 0; RESET; goto NEW START
                        end else 
                        begin CALCULATE STEP AND ORDER;
                                if KNEW ^= K then 
                                begin K:= KNEW; ORDER end;
                                CH:= CH * CHNEW; RESET
                        end 
                end else 
                begin if ADAMS then TRY CURTISS:
                        begin ADAMS:= false; METHOD
                        end else 
                        if K = 1 then 
                        begin comment VIOLATE EPS CRITERION;
                                C:= EPS * SQRT(ERROR/TOL);
                                if C > SAVE[-3] then SAVE[-3]:= C;
                                SAVE[-2]:= SAVE[-2] + 1;
                                SAME:= 4; goto ERROR TEST OK
                        end;
                        K:= KOLD:= 1; RESET; ORDER; SAME:= 2
                end 
        end else ERROR TEST OK:
                FAILS:= 0;
                for I:= 1 step 1 until N do 
                begin C:= DELTA[I];
                        for L:= 2 step 1 until K do 
                        Y[L*M+I]:= Y[L*M+I] + A[L] * C;
                        if ABS(Y[I]) > YMAX[I] then 
                             YMAX[I]:=  ABS(Y[I])
                end;

                SAME:= SAME-1;
                if SAME= 1 then 
                begin for I:= 1 step 1 until N do 
                        LAST DELTA[I]:= DELTA[I]
                end else 
                if SAME= 0 then 
                begin CALCULATE STEP AND ORDER;
                        if CHNEW > 1.1 then 
                        begin DECOMPOSED:= false;
                                if K ^= KNEW then 
                                begin if KNEW > K then 
                                        begin for I:= 1 step 1
                                             until N do Y[KNEW*M+I]
                                                := DELTA[I] * A[K]/KNEW
                                        end;
                                        K:= KNEW; ORDER
                                end;
                                SAME:= K+1;
                                if CHNEW * H > HMAX
                                    then CHNEW:= HMAX/H;
                                H:= H * CHNEW; C:= 1;
                                for J:= M step M until K*M do 
                                begin C:= C * CHNEW;
                                        for I:= J+1 step 1 until 
                                        J+N do Y[I]:= Y[I] * C
                                end 
                        end 
                        else SAME:= 10
                end;
                if X ^= XEND then 
                begin XOLD:= X; HOLD:= H; KOLD:= K; CH:= 1;
                        for I:= K * M + N step -1 until 1 do 
                        SAVE[I]:= Y[I];
                        OUT(H,K)
                end 
        end CORRECTION AND ESTIMATION LOCAL ERROR;
        end STEP;

        RETURN: SAVE[0]:= if ADAMS then 0 else 1;
        MULTISTEP:= SAVE[-1]= 0 and SAVE[-2]=0
 end MULTISTEP;
        eop