(* ----------------------------------------------------------------------------
 * $Id: MASAPF.mi,v 1.4 1998/01/05 13:03:59 pesch Exp $
 * ----------------------------------------------------------------------------
 * This file is part of MAS.
 * ----------------------------------------------------------------------------
 * Copyright (c) 1989 - 1992 Universitaet Passau
 * ----------------------------------------------------------------------------
 * $Log: MASAPF.mi,v $
 * Revision 1.4  1998/01/05 13:03:59  pesch
 * Fixed bug found by Hermann Rufenacht: FL was used instead of EL in APWRIT
 *
 * Revision 1.3  1992/10/15  16:28:09  kredel
 * Changed rcsid variable
 *
 * Revision 1.2  1992/02/12  13:18:59  pesch
 * Moved CONST Definition to the right place.
 *
 * Revision 1.1  1992/01/22  15:08:24  kredel
 * Initial revision
 *
 * ----------------------------------------------------------------------------
 *)

IMPLEMENTATION MODULE MASAPF;

(* MAS Arbitrary Precision Floating Point Implementation Module. *)



(* Import lists and Definitions *) 

FROM MASELEM IMPORT MASQREM;


FROM MASBIOS IMPORT CREAD, CREADB, GWRITE, 
                    MASORD, DIGIT, BKSP, 
                    SWRITE, BLINES;


FROM MASSTOR IMPORT LIST, SIL, BETA,
                    ADV, FIRST, RED, 
                    INV, LIST1, COMP;

FROM MASERR IMPORT ERROR, harmless, severe, fatal;


FROM SACLIST IMPORT SECOND, LIST2, CINV;


FROM SACD IMPORT ETA, THETA, ZETA;


FROM SACI IMPORT IWRITE, IDQR, IABSF, ILOG2, IEXP,
                 IDP2, IMP2, ISUM, IPROD, IPRODK, INEG,
                 ICOMP, ISIGNF, IQ, IMIN, IDPR,
                 IDIF, IREAD;
                 

FROM SACRN IMPORT RNDEN, RNNUM, RNRED, RNDIF, 
                  RNINT, RNPROD, RNSUM;
                  
 
VAR APPR2, APP10: LIST;
    msg: BOOLEAN;


CONST rcsidi = "$Id: MASAPF.mi,v 1.4 1998/01/05 13:03:59 pesch Exp $";
CONST copyrighti = "Copyright (c) 1989 - 1992 Universitaet Passau";



PROCEDURE APCOMP(ML,EL: LIST): LIST;
(*Arbitrary precision floating point composition. e is the
exponent, m is the mantissa of the arbitrary precision
floating point number A.*)
BEGIN
(*1*) RETURN( COMP(EL, COMP(ML,SIL) ) );
(*9*) END APCOMP; 


PROCEDURE APMANT(A: LIST): LIST;
(*Arbitrary precision floating point mantissa. m is the mantissa 
of the arbitrary precision floating point number A.*)
BEGIN
(*1*) RETURN( FIRST(RED(A)) );
(*9*) END APMANT;
      

PROCEDURE APEXPT(A: LIST): LIST;
(*Arbitrary precision floating point exponent. e is the
exponent of the arbitrary precision floating point number A.*)
BEGIN
(*1*) RETURN( FIRST(A) );
(*9*) END APEXPT; 


PROCEDURE ILOG10(N: LIST): LIST;
(*Integer logarithm base 10.
N is an integer, l is a beta integer. l=LOG10(ABS(N)).*)
VAR  L, R, S: LIST;
BEGIN
(*1*) (*n=0 or 1.*) L:=0;
      IF N = 0 THEN RETURN(L); END;
      S:=IABSF(N);
      IF S = 1 THEN RETURN(L); END;
(*2*) (*divide.*)
      REPEAT IDQR(S,THETA,S,R); L:=L+ETA;
             UNTIL S = 0;
      L:=L-ETA; S:=R;
      REPEAT MASQREM(S,10,S,R); L:=L+1;
             UNTIL S = 0;
      L:=L-1;
      IF R <> 0 THEN L:=L+1; END;
(*3*) (*finish.*) RETURN(L);
(*6*) END ILOG10;


PROCEDURE APSPRE(N: LIST);
(*Arbitrary precision floating point set precision.
N is the desired precision of the floating point numbers.*)
VAR  J1Y, L, M, QL, RL: LIST;
BEGIN
(*1*) (*set precision.*) M:=IEXP(10,N); L:=ILOG2(M)+1; 
      MASQREM(L,ZETA,QL,RL);
      IF RL <> 0 THEN L:=L+ZETA-RL; END;
      L:=L-1; APPR2:=L; APP10:=N;
(*2*) (*generate message.*)
      IF msg THEN
         SWRITE("Floating point precision set to "); IWRITE(N);
         SWRITE(" digits = "); IWRITE(L); SWRITE(" bits. "); BLINES(0);
         END;
(*3*) (*finish.*) RETURN;
(*6*) END APSPRE;


PROCEDURE APFINT(N: LIST): LIST;
(*Arbitrary precision floating point from integer.
The integer N is converted to the arbitrary precision
floating point number A.*)
VAR  A, EL, FL, ML: LIST;
BEGIN
(*1*) (*n=0.*)
      IF N = 0 THEN A:=APCOMP(0,0); RETURN(A); END;
(*2*) (*normalize.*) EL:=ILOG2(N); FL:=EL-1-APPR2; (*1=log2(2).*)
      IF FL >= 0 
         THEN ML:=IDP2(N,FL); (*truncate*)   
         ELSE ML:=IMP2(N,-FL); (*fill up*) END; 
(*3*) (*round.*) ML:=ISUM(ML,1); 
      ML:=IDP2(ML,1);
(*4*) (*finish.*) A:=APCOMP(ML,EL); RETURN(A);
(*6*) END APFINT;



PROCEDURE APSHFT(B,EL: LIST): LIST;
(*Arbitrary precision floating point shift.
The arbitrary precision floating point number B is multiplied by 2**e.
A is an arbitrary precision floating point number.*)
VAR  A, FL, J1Y, J2Y, ML: LIST;
BEGIN
(*1*) (*b=0.*) ML:=APMANT(B);
      IF ML = 0 THEN A:=APCOMP(0,0); RETURN(A); END;
(*2*) (*shift and check.*) FL:=APEXPT(B)+EL; 
      IF FL >= BETA THEN
         ERROR(severe,"arbitrary precision floating point OVERFLOW");
         BLINES(1); SWRITE("Mantissa="); IWRITE(ML); BLINES(1);
         SWRITE("Exponent="); GWRITE(APEXPT(B)); BLINES(1);
         SWRITE("EL       ="); GWRITE(EL); BLINES(1);
         SWRITE("FL       ="); GWRITE(FL); BLINES(2); J1Y:=APPR2+1;
         J1Y:=IMP2(1,J1Y); J2Y:=-1; ML:=ISUM(J1Y,J2Y); FL:=BETA-1; END;
      IF FL <= -BETA THEN
         ERROR(severe,"arbitrary precision floating point UNDERFLOW");
         BLINES(1); SWRITE("Mantissa="); IWRITE(ML); BLINES(1);
         SWRITE("Exponent="); GWRITE(APEXPT(B)); BLINES(1);
         SWRITE("EL       ="); GWRITE(EL); BLINES(1);
         SWRITE("FL       ="); GWRITE(FL); BLINES(2); ML:=0; FL:=0; END;
(*3*) (*finish.*) A:=APCOMP(ML,FL); RETURN(A);
(*6*) END APSHFT;


PROCEDURE APSIGN(A: LIST): LIST;
(*Arbitrary precision floating point sign. A is an arbitrary precision 
floating point number, s is the sign of A.*)
VAR  ML, SL: LIST;
BEGIN
(*1*) (*get mantissa.*) ML:=APMANT(A);
(*2*) (*integer sign.*) SL:=ISIGNF(ML);
(*3*) (*finish.*) RETURN(SL);
      END APSIGN;


PROCEDURE APWRIT(A: LIST);
(*Arbitrary precision floating point write.
The arbitrary precision floating point number A is written to
the output stream.*)
VAR  AP, SL, B, EL, GL, J1Y, ML, Z: LIST;
BEGIN
(*1*) (*a=0.*) ML:=APMANT(A);
      IF ML = 0 THEN SWRITE("0.0"); RETURN; END;
(*2*) (*multiply by 10**(-log10(a)). *) SL:=APSIGN(A); AP:=APABS(A);
      ML:=APMANT(AP); 
      Z:=APFINT(10); EL:=APLG10(AP); 
      IF EL > 0 
         THEN J1Y:=APEXP(Z,EL);  B:=APQ(AP,J1Y); 
         ELSE J1Y:=APEXP(Z,-EL); B:=APPROD(AP,J1Y); END;
(*3*) (*convert to ml*10**el.*) 
      ML:=APMANT(B); GL:=APEXPT(B); (* now: 0 <= gl <= 3 *)
      IF GL > 0 THEN ML:=IMP2(ML,GL); ML:=ISUM(ML,1); 
         EL:=EL+1; END;
      J1Y:=IEXP(10,APP10); 
      ML:=IPROD(ML,J1Y);
      ML:=IDP2(ML,APPR2);
(*4*) (*write.*) IF SL < 0 THEN SWRITE("-"); END; 
      SWRITE("0."); IWRITE(ML); 
      SWRITE("E");IWRITE(EL);
(*5*) (*finish.*) RETURN;
(*8*) END APWRIT;


PROCEDURE APNEG(A: LIST): LIST;
(*Arbitrary precision floating point negative.
The arbitrary precision floating point number A is negated.
B= -A.*)
VAR  B, EL, ML: LIST;
BEGIN
(*1*) (*negate.*) ML:=APMANT(A); ML:=INEG(ML); EL:=APEXPT(A);
      B:=APCOMP(ML,EL);
(*2*) (*finish.*) RETURN(B);
(*5*) END APNEG;


PROCEDURE APABS(A: LIST): LIST;
(*Arbitrary precision floating point absolute value.
A is a arbitrary precision floating point number.
B is the absolute value of A.*)
VAR  B, EL, ML: LIST;
BEGIN
(*1*) (*absolute value.*) ML:=APMANT(A); ML:=IABSF(ML); EL:=APEXPT(A);
      B:=APCOMP(ML,EL);
(*2*) (*finish.*) RETURN(B);
(*5*) END APABS;


PROCEDURE APCMPR(A,B: LIST): LIST;
(*Arbitrary precision floating point compare.
A and B are arbitrary precision floating point numbers.
s is the sign of the difference of A and B. s=SIGN(A-B).*)
VAR  EL1, EL2, ML1, ML2, SL, SL1, SL2: LIST;
BEGIN
(*1*) (*compare signs.*) ML1:=APMANT(A); ML2:=APMANT(B);
      SL1:=ISIGNF(ML1); SL2:=ISIGNF(ML2); SL:=ICOMP(SL1,SL2);
      IF SL <> 0 THEN RETURN(SL); END;
(*2*) (*equal signs.*) EL1:=APEXPT(A); EL2:=APEXPT(B);
      SL:=ICOMP(EL1,EL2);
      IF SL = 0 THEN SL:=ICOMP(ML1,ML2); END;
(*3*) (*finish.*) SL:=SL*SL1; RETURN(SL);
(*6*) END APCMPR;


PROCEDURE APNELD(A,B: LIST): LIST;
(*Arbitrary precision floating point number of equal leading digits.
A and B are arbitrary precision floating point numbers.
l is the number of equal leading digits of A and B.*)
VAR  EL1, EL2, J1Y, LL, ML1, ML2, NL1, NL2, PL, PL1, PL2, SL, SL1,
     SL2: LIST;
BEGIN
(*1*) (*compare signs.*) LL:=0; ML1:=APMANT(A); ML2:=APMANT(B);
      SL1:=ISIGNF(ML1); SL2:=ISIGNF(ML2); SL:=ICOMP(SL1,SL2);
      IF SL <> 0 THEN RETURN(LL); END;
(*2*) (*compare exponents.*) EL1:=APEXPT(A); EL2:=APEXPT(B);
      SL:=ICOMP(EL1,EL2);
      IF SL <> 0 THEN RETURN(LL); END;
(*3*) (*compare digits. ml1 and ml2 have same length.*)
      IF ML1 < BETA THEN ML1:=LIST1(ML1); END;
      IF ML2 < BETA THEN ML2:=LIST1(ML2); END;
      NL1:=CINV(ML1); NL2:=CINV(ML2);
      REPEAT ADV(NL1,PL1,NL1); ADV(NL2,PL2,NL2);
             IF PL1 = PL2 THEN LL:=LL+ZETA; ELSE PL:=PL1-PL2;
                J1Y:=ILOG2(PL); J1Y:=ZETA-J1Y; LL:=LL+J1Y; RETURN(LL);
                END;
             UNTIL NL1 = SIL;
(*4*) (*finish.*) RETURN(LL);
(*7*) END APNELD;


PROCEDURE APPROD(A,B: LIST): LIST;
(*Arbitrary precision floating point product.
A, B and C are arbitrary precision floating point numbers.
C is the product of A and B. C=A*B.*)
VAR  C, EL, EL1, EL2, J1Y, ML, ML1, ML2: LIST;
BEGIN
(*1*) (*multiply mantisa and normalise.*) ML1:=APMANT(A);
      ML2:=APMANT(B); ML:=IPRODK(ML1,ML2); C:=APFINT(ML);
(*2*) (*add exponents and shift.*) EL1:=APEXPT(A); EL2:=APEXPT(B);
      J1Y:=EL1+EL2; J1Y:=J1Y-APPR2; EL:=J1Y-APPR2; C:=APSHFT(C,EL);
(*3*) (*finish.*) RETURN(C);
(*6*) END APPROD;


PROCEDURE APQ(A,B: LIST): LIST;
(*Arbitrary precision floating point quotient.
A, B and C are arbitrary precision floating point numbers.
C is the quotient of A and B. C=A/B.*)
VAR  C, EL, EL1, EL2, ML, ML1, ML2, MR, MQ: LIST;
BEGIN
(*1*) (*divide mantisa and normalise.*) ML1:=APMANT(A);
      ML2:=APMANT(B); ML:=IMP2(ML1,APPR2+1); 
      ML:=IQ(ML,ML2);  C:=APFINT(ML);
(*2*) (*subtract exponents and shift.*) EL1:=APEXPT(A);
      EL2:=APEXPT(B); EL:=EL1-APPR2-1-EL2;
      C:=APSHFT(C,EL);
(*3*) (*finish.*) RETURN(C);
(*6*) END APQ;


PROCEDURE APSUM(A,B: LIST): LIST;
(*Arbitrary precision floating point sum.
A, B and C are arbitrary precision floating point numbers.
C is the sum of A and B. C=A+B.*)
VAR  C, EL, EL1, EL2, J1Y, ML, ML1, ML2: LIST;
BEGIN
(*1*) (*normalize mantisa and add.*) EL1:=APEXPT(A); EL2:=APEXPT(B);
      EL:=IMIN(EL1,EL2); ML1:=APMANT(A); ML2:=APMANT(B); J1Y:=EL1-EL;
      ML1:=IMP2(ML1,J1Y); J1Y:=EL2-EL; ML2:=IMP2(ML2,J1Y);
      ML:=ISUM(ML1,ML2); C:=APFINT(ML);
(*2*) (*shift.*) EL:=EL-APPR2; C:=APSHFT(C,EL);
(*3*) (*finish.*) RETURN(C);
(*6*) END APSUM;


PROCEDURE APDIFF(A,B: LIST): LIST;
(*Arbitrary precision floating point difference.
A, B and C are arbitrary precision floating point numbers.
C is the difference of A and B. C=A-B.*)
VAR  C, XL: LIST;
BEGIN
(*1*) (*add negative.*) C:=APNEG(B); C:=APSUM(A,C);
(*2*) (*finish.*) RETURN(C);
(*5*) END APDIFF;


PROCEDURE APLG10(A: LIST): LIST;
(*Arbitrary precision floating point logarithm base 10.
A is an arbitrary precision floating point number,
l is a beta integer, l=LOG10(ABS(A)). *)
VAR  EL, FL, J1Y, L, S, XL, Z: LIST;
BEGIN
(*1*) (*initialize.*) L:=0;
      IF APMANT(A) = 0 THEN 
         ERROR(fatal,"APLG10, logarithm of 0 undefined"); RETURN(L); END;
      S:=APABS(A);
(*2*) (*divide and multiply by theta.*) J1Y:=APEXPT(S);
      FL:=IABSF(J1Y); XL:=ILOG2(THETA);
      IF FL > XL THEN
         IF FL > 50*XL THEN ERROR(severe,"APLG10 is not efficient") END;
         Z:=APFINT(THETA); EL:=APEXPT(Z);
         WHILE APEXPT(S) >= EL DO S:=APQ(S,Z); L:=L+ETA; END;
         WHILE APEXPT(S) <  0  DO S:=APPROD(S,Z); L:=L-ETA; END;
         END;
(*3*) (*divide and multiply by 10.*) Z:=APFINT(10); EL:=APEXPT(Z);
      WHILE APEXPT(S) >= EL DO S:=APQ(S,Z); L:=L+1; END;
      WHILE APEXPT(S) <  0  DO S:=APPROD(S,Z); L:=L-1; END;
(*4*) (*finish.*) RETURN(L);
(*7*) END APLG10;


PROCEDURE APEXP(A,NL: LIST): LIST;
(*Arbitrary precision floating point exponentiation.
A and B are arbitrary precision floating point numbers.
n is a beta-integer.  B=A**n.*)
VAR  B, J1Y, KL, XL: LIST;
BEGIN
(*1*) (*trivial cases.*)
      IF NL = 0 THEN B:=APFINT(1); RETURN(B); END;
      IF NL = 1 THEN B:=A; RETURN(B); END;
(*2*) (*nl negative.*)
      IF NL < 0 THEN J1Y:=-NL; B:=APEXP(A,J1Y); J1Y:=APFINT(1);
         B:=APQ(J1Y,B); RETURN(B); END;
(*3*) (*recursion.*) KL:=NL DIV 2; B:=APEXP(A,KL); B:=APPROD(B,B);
      IF NL > KL*2 THEN B:=APPROD(B,A); END;
(*4*) (*finish.*) RETURN(B);
(*7*) END APEXP;


PROCEDURE APFRN(A: LIST): LIST;
(*Arbitrary precision floating point from rational number.
B is an arbitrary precision floating point number.
A is a rational number.*)
VAR  A1, A2, B, B1, B2, XL: LIST;
BEGIN
(*1*) (*a=0.*)
      IF A = 0 THEN B:=APFINT(0); RETURN(B); END;
(*2*) (*convert numerator and denomiator.*) A1:=RNNUM(A);
      A2:=RNDEN(A); B1:=APFINT(A1); B2:=APFINT(A2);
(*3*) (*divide.*) B:=APQ(B1,B2);
(*4*) (*finish.*) RETURN(B);
(*7*) END APFRN;


PROCEDURE RNFAP(A: LIST): LIST;
(*Rational number from arbitrary precision floating point.
A is an arbitrary precision floating point number.
B is a rational number.*)
VAR  B, B1, B2, EL, J1Y, ML, XL: LIST;
BEGIN
(*1*) (*a=0.*) ML:=APMANT(A);
      IF ML = 0 THEN B:=0; RETURN(B); END;
      EL:=APEXPT(A);
(*2*) (*convert mantisa and exponent.*) B1:=ML; B2:=IMP2(1,APPR2);
      IF EL >= 0 THEN B1:=IMP2(B1,EL); ELSE J1Y:=-EL;
         B2:=IMP2(B2,J1Y); END;
(*3*) (*reduce to lowest terms.*) B:=RNRED(B1,B2);
(*4*) (*finish.*) RETURN(B);
(*7*) END RNFAP;


PROCEDURE RNDRD(): LIST;
(*Rational number decimal read.  The rational number R is read
from the input stream.  Any preceding blanks are skipped.*)
VAR  A, B, BL, BLP, C, EL, IL, J1Y, JL, R, R1, R2, RP, s: LIST;
BEGIN
(*1*) (*rational number read.*) C:=CREADB(); BKSP; 
      IF C = MASORD("-") THEN s:=-1 ELSE s:=1 END; 
      R1:=IREAD(); C:=CREAD();
      IF C <> MASORD(".") THEN
         IF C = MASORD("/") THEN R2:=IREAD(); ELSE R2:=1; BKSP; END;
         R:=RNRED(R1,R2); RETURN(R); END;
(*2*) (*read decimal fraction.*) JL:=-1;
      REPEAT C:=CREAD(); JL:=JL+1;
             UNTIL C <> 0;
(*3*) (*fraction=0.*)
      IF NOT DIGIT(C) THEN BKSP; 
         IF C <> MASORD("E") THEN R:=RNINT(R1); RETURN(R)
                             ELSE C:=0 END;
         END;
      A:=0;
(*4*) (*compute theta-digits.*) B:=SIL; BL:=0; IL:=0;
      REPEAT J1Y:=10*BL; BL:=J1Y+C; IL:=IL+1;
             IF IL = ETA THEN B:=COMP(BL,B); BL:=0; IL:=0; END;
             JL:=JL+1; C:=CREAD();
             UNTIL NOT DIGIT(C);
      BKSP;
(*5*) (*convert to base beta.*) B:=INV(B);
      WHILE B <> SIL DO A:=IDPR(A,THETA); ADV(B,BLP,B);
            A:=ISUM(A,BLP); END;
      IF A <> 0 THEN J1Y:=IEXP(10,IL); A:=IDPR(A,J1Y); END;
      A:=ISUM(A,BL); R2:=IEXP(10,JL); R:=RNRED(A,R2); 
      RP:=RNINT(R1);
      IF s < 0 THEN R:=RNDIF(RP,R); ELSE R:=RNSUM(RP,R) END;
(*6*) (*read floating point exponent.*) C:=CREAD(); 
      IF C <> MASORD("E") THEN BKSP; RETURN(R); END;
      EL:=IREAD();
      IF EL >= 0 
         THEN J1Y:=IEXP(10,EL);  RP:=RNRED(J1Y,1); 
         ELSE J1Y:=IEXP(10,-EL); RP:=RNRED(1,J1Y); END;
      R:=RNPROD(R,RP); RETURN(R);
(*9*) END RNDRD;


PROCEDURE APROOT(A,NL: LIST): LIST;
(*Arbitrary precision floating point n-th root.
A and B are arbitrary precision floating point numbers.
B is the n-th root of A.*)
VAR   B, KL, KL1, NL1, PR, SL, W, WH, WP, WS: LIST;
BEGIN
(*1*) (*initialize.*) PR:=(APPR2 DIV 2)+4; WP:=APFINT(1);
      IF NL = 0 THEN B:=WP; RETURN(B); END;
(*2*) (*square root only.*)
      IF NL = 2 THEN 
         REPEAT WS:=WP; W:=APQ(A,WS); W:=APSUM(WS,W); 
                WP:=APSHFT(W,-1); (*/2*) SL:=APNELD(WP,WS);
                UNTIL SL >= PR;
         B:=WP; RETURN(B);
         END;
(*3*) (*newtons loop for n-th root.*) KL:=APFINT(NL);
      NL1:=NL-1; KL1:=APFINT(NL1); 
      REPEAT WS:=WP; W:=APEXP(WS,NL1); W:=APQ(A,W); WH:=APPROD(WS,KL1);
             W:=APSUM(WH,W); WP:=APQ(W,KL); SL:=APNELD(WP,WS);
             UNTIL SL >= PR;
      B:=WP;
(*3*) (*finish.*) RETURN(B);
(*6*) END APROOT;


PROCEDURE APPI(): LIST;
(*Arbitrary precision floating point pi.
pi is an arbitrary precision floating point number. *)
VAR   A, B, C, D, EINS, F, J, P, PI, PR, S, SL, XL, ZWEI:
      LIST;
BEGIN
(*1*) (*set precision and initialize.*) PR:=(APPR2 DIV 2)+4;
      EINS:=APFINT(1); ZWEI:=APFINT(2); 
      A:=EINS; J:=APROOT(ZWEI,2); B:=APQ(EINS,J); C:=B;
      S:=APFINT(0); P:=1;
(*2*) (*arithmetic geometric mean loop.*) 
      REPEAT F:=A; J:=APSUM(F,B); A:=APSHFT(J,-1); (*/2*)
             J:=APDIFF(F,B); C:=APSHFT(J,-1); (*/2*) J:=APPROD(F,B);
             B:=APROOT(J,2); P:=P+1; J:=APSHFT(C,P); (* *2**P *)
             J:=APPROD(C,J); S:=APSUM(J,S); SL:=APNELD(A,B);
             UNTIL SL >= PR;
(*3*) (*compute pi.*) D:=APDIFF(EINS,S); J:=APSHFT(B,2); (* *4 *)
      J:=APPROD(A,J); PI:=APQ(J,D);
(*4*) (*finish.*) RETURN(PI);
(*7*) END APPI;


BEGIN 
(* Initialization. *)

msg:=FALSE;
APSPRE(20);
msg:=TRUE;

END MASAPF.


(* -EOF- *)