C mplinux1.f
C
C MP Package excluding machine-dependent routines
C MPIS, MPLARG and MPUPW (for these see mplinux0.f)
C
C This is MP Linux version 20010829 (essentially the same as
C version 810614 except for the three routines above
C and bug fix 890208 in MPGAMQ).
C
C $$                   ******  MPABS  ******
      SUBROUTINE MPABS (X, Y)
C SETS Y = ABS(X) FOR MP NUMBERS X AND Y.
C Y WILL BE PACKED IF X IS.
      INTEGER X(1), Y(1)
      CALL MPSTR (X, Y)
      Y(1) = IABS(Y(1))
      RETURN
      END
C $$                   ******  MPADD  ******
      SUBROUTINE MPADD (X, Y, Z)
C ADDS X AND Y, FORMING RESULT IN Z, WHERE X, Y AND Z ARE MP NUMBERS.
C ROUNDING DEFINED BY PARAMETER RNDRL IN COMMON /MPCOM/ AS FOLLOWS -
C RNDRL = 0 - TRUNCATE TOWARDS ZERO IF X*Y .GE. 0,
C             AWAY FROM ZERO IF X*Y .LT. 0,
C             IN BOTH CASES USING ONE GUARD DIGIT, SO RESULT IS
C             EXACT IF SEVERE CANCELLATION OCCURS.
C RNDRL = 1, 2 OR 3 -  SEE COMMENTS IN SUBROUTINE MPNZR.
C             SUFFICIENT GUARD DIGITS ARE USED TO ENSURE THE
C             CORRECT RESULT.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $               MXEXPN, MNEXPN, RNDRL, DUMMY
      INTEGER ED, I2, J, KG, MED, RE, RS, S, TWO
      INTEGER B, DUMMY(12), LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR, MXSPTR,
     $     R(1), RNDRL, SPTR, T, X(1), Y(1), Z(1)
      TWO = 2
C COMPUTE NUMBER OF GUARD DIGITS REQUIRED
      KG = 1
      IF (RNDRL.NE.0) KG = T
C ALLOCATE T + KG WORDS FOR ACCUMULATOR.
      CALL MPNEW2 (I2, T+KG)
C CHECK FOR X OR Y ZERO
      IF (X(1).NE.0) GO TO 20
C X = 0 OR NEGLIGIBLE, SO RESULT = Y
   10 CALL MPSTR(Y, Z)
      GO TO 120
   20 IF (Y(1).NE.0) GO TO 40
C Y = 0 OR NEGLIGIBLE, SO RESULT = X
   30 CALL MPSTR (X, Z)
      GO TO 120
C COMPARE SIGNS
   40 S = X(1)*Y(1)
      IF (IABS(S).LE.1) GO TO 50
      CALL MPERRM (38HSIGN NOT 0, +1 OR -1 IN CALL TO MPADD$)
      GO TO 80
C COMPARE EXPONENTS
   50 ED = X(TWO) - Y(TWO)
      MED = IABS(ED)
C CAN REDUCE KG IF MED SMALL.  THIS SAVES TIME.
      KG = MIN0 (KG, MED + (S+1)/2)
      IF (ED) 90, 60, 130
C EXPONENTS EQUAL SO COMPARE SIGNS, THEN FRACTIONS IF NEC.
   60 IF (S.GT.0) GO TO 100
      DO 70 J = 1, T
      IF (X(J+2) - Y(J+2)) 100, 70, 140
   70 CONTINUE
C RESULT IS ZERO
   80 Z(1) = 0
      GO TO 120
C HERE EXPONENT(Y) .GT. EXPONENT(X)
   90 IF ((MED.GT.T).AND.(RNDRL.LE.1)) GO TO 10
C CHECK FOR COMMON SPECIAL CASE HERE (FOR SAKE OF SPEED)
      IF ((RNDRL.GT.0).OR.(((Y(TWO+1).GE.(B-1)).OR.(S.LT.0)).AND.
     $     ((Y(TWO+1).EQ.1).OR.(S.GT.0))))  GO TO 100
C CAN AVOID CALLING MPNZR HERE, SAVING TIME.
      CALL MPADD3 (X, Y, RE, Z(TWO+1), 0)
      Z(1) = Y(1)
      Z(TWO) = RE
      GO TO 120
C HERE ABS(Y) .GT. ABS(X)
  100 RS = Y(1)
      CALL MPADD3 (X, Y, RE, R(I2), KG)
C NORMALIZE AND ROUND OR TRUNCATE
  110 CALL MPNZR (RS, RE, Z, R(I2), KG)
C RESTORE STACK POINTER AND RETURN
  120 SPTR = I2
      RETURN
C HERE EXPONENT(X) .GT. EXPONENT(Y)
C CODE IS AS ABOVE WITH X AND Y INTERCHANGED.
  130 IF ((MED.GT.T).AND.(RNDRL.LE.1)) GO TO 30
C CHECK FOR COMMON SPECIAL CASE HERE (FOR SAKE OF SPEED)
      IF ((RNDRL.GT.0).OR.(((X(TWO+1).GE.(B-1)).OR.(S.LT.0)).AND.
     $     ((X(TWO+1).EQ.1).OR.(S.GT.0))))  GO TO 140
C CAN AVOID CALLING MPNZR HERE.
      CALL MPADD3 (Y, X, RE, Z(TWO+1), 0)
      Z(1) = X(1)
      Z(TWO) = RE
      GO TO 120
C HERE ABS(X) .GT. ABS(Y)
  140 RS = X(1)
      CALL MPADD3 (Y, X, RE, R(I2), KG)
      GO TO 110
      END
C $$                   ******  MPADDI  ******
      SUBROUTINE MPADDI (X, IY, Z)
C ADDS MULTIPLE-PRECISION X TO INTEGER IY GIVING MULTIPLE-PRECISION Z.
C ROUNDING IS CONTROLLED BY RNDRL IN COMMON /MPCOM/ - SEE
C COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      INTEGER IY, I2, R(1), X(1), Z(1), SV
C SAVE T ETC., ALLOCATE TEMPORARY SPACE.
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
C CONVERT IY TO MULTIPLE-PRECISION AND ADD TO X.
      CALL MPCIM (IY, R(I2))
      CALL MPADD (X, R(I2), Z)
C RESTORE EVERYTHING.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPADDQ  ******
      SUBROUTINE MPADDQ (X, I, J, Y)
C ADDS THE RATIONAL NUMBER I/J TO MP NUMBER X, MP RESULT IN Y
C ROUNDING DEFINED BY PARAMETER RNDRL IN COMMON /MPCOM/ -
C EFFECT IS SAME AS CONVERTING I/J TO MULTIPLE-PRECISION USING
C MPCQM AND THEN ADDING TO X USING MPADD, SO SEE COMMENTS IN
C THESE ROUTINES.
      COMMON R
      INTEGER I, I2, J, R(1), SV, X(1), Y(1)
      CALL MPSAVN (SV)
C ALLOCATE TEMPORARY SPACE, COMPUTE I/J AND ADD TO X
      CALL MPNEW (I2)
      CALL MPCQM (I, J, R(I2))
      CALL MPADD (X, R(I2), Y)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPADD3  ******
      SUBROUTINE MPADD3 (X, Y, RE, A, KG)
C CALLED BY MPADD, DOES INNER LOOPS OF ADDITION
C ASSUMES 0 .LT. ABS(X) .LE. ABS(Y).
C RETURNS DIGITS OF X + Y IN A(1), ... , A(T+KG)
C AND EXPONENT IN RE.  ASSUMES KG .GE. 0.  THERE IS A SLIGHT
C CLUDGE TO ENSURE CORRECT DIRECTED ROUNDING.  THIS MAY
C AFFECT A(T+1), ... , A(T+KG).
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER C, I, J, MED, S, TED, TG, TG1, TWO,
     $  A(1), B, DUMMY(21), KG, RE, T, X(1), Y(1)
      TWO = 2
C Y(TWO) - X(TWO) .GT. T IN CALL ONLY FOR RNDRL .GT. 1
      MED = MIN0 (Y(TWO) - X(TWO), T)
      TED = T + MED
      S = X(1)*Y(1)
      RE = Y(TWO)
      TG = T + KG
      I = TG
      C = 0
C CLEAR GUARD DIGITS TO RIGHT OF X DIGITS
   10 IF (I.LE.TED) GO TO 20
      A(I) = 0
      I = I - 1
      GO TO 10
   20 IF (S.LT.0) GO TO 130
C HERE DO ADDITION, EXPONENT(Y) .GE. EXPONENT(X)
      IF (I.LE.T) GO TO 40
   30 J = I - MED
      A(I) = X(J+2)
      I = I - 1
      IF (I.GT.T) GO TO 30
   40 IF (I.LE.MED) GO TO 60
      J = I - MED
      C = Y(I+2) + X(J+2) + C
      IF (C.LT.B) GO TO 50
C CARRY GENERATED HERE
      A(I) = C - B
      C = 1
      I = I - 1
      GO TO 40
C NO CARRY GENERATED HERE
   50 A(I) = C
      C = 0
      I = I - 1
      GO TO 40
   60 IF (I.LE.0) GO TO 90
      C = Y(I+2) + C
      IF (C.LT.B) GO TO 70
      A(I) = 0
      C = 1
      I = I - 1
      GO TO 60
   70 A(I) = C
      I = I - 1
C NO CARRY POSSIBLE HERE
   80 IF (I.LE.0) RETURN
      A(I) = Y(I+2)
      I = I - 1
      GO TO 80
   90 IF (C.EQ.0) RETURN
C MUST SHIFT RIGHT HERE AS CARRY OFF END
      TG1 = TG + 1
      DO 100 J = 2, TG
      I = TG1 - J
  100 A(I+1) = A(I)
      A(1) = 1
      RE = RE + 1
      RETURN
C HERE DO SUBTRACTION, ABS(Y) .GT. ABS(X)
  110 J = I - MED
      A(I) = C - X(J+2)
      C = 0
      IF (A(I).GE.0) GO TO 120
C BORROW GENERATED HERE
      C = -1
      A(I) = A(I) + B
  120 I = I - 1
  130 IF (I.GT.T) GO TO 110
  140 IF (I.LE.MED) GO TO 160
      J = I - MED
      C = Y(I+2) + C - X(J+2)
      IF (C.GE.0) GO TO 150
C BORROW GENERATED HERE
      A(I) = C + B
      C = -1
      I = I - 1
      GO TO 140
C NO BORROW GENERATED HERE
  150 A(I) = C
      C = 0
      I = I - 1
      GO TO 140
  160 IF (I.LE.0) RETURN
      C = Y(I+2) + C
      IF (C.GE.0) GO TO 70
      A(I) = C + B
      C = -1
      I = I - 1
      GO TO 160
      END
C $$                   ******  MPART1  ******
      SUBROUTINE MPART1 (N, Y)
C COMPUTES MP Y = ARCTAN(1/N), ASSUMING INTEGER N .GT. 1.
C USES SERIES ARCTAN(X) = X - X**3/3 + X**5/5 - ...
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, KTUNFL, DUMMY
      INTEGER I, ID, I2, I3, KTU, SV, TG
      INTEGER B, DUMMY(11), KTUNFL, LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR
      INTEGER MXSPTR, N, R(1), RNDRL, SPTR, T, Y(1)
      INTEGER MPPARN, MPTLB
C SAVE T ETC.
      CALL MPSAVN (SV)
      IF (N .LE. 1) CALL MPERRM (27HN .LE. 1 IN CALL TO MPART1$)
C INCREASE WORKING PRECISION.
      IF ((N.LT.B).AND.(T.GT.2)) T = T - 1
      CALL MPGD3 (MPTLB (IABS(R(SV))), TG)
C SAVE UNDERFLOW COUNTER
      KTU = KTUNFL
C USE TRUNCATED ARITHMETIC INTERNALLY IF RNDRL .LE. 1.
      IF (RNDRL.EQ.1) RNDRL = 0
C ALLOCATE SPACE FOR TEMPORARY STORAGE
      CALL MPNEW (I2)
      CALL MPNEW (I3)
C SET SUM TO 1/N
      CALL MPCQM (1, N, R(I3))
C SET ADDITIVE TERM TO 1/N
      CALL MPSTR (R(I3), R(I2))
      I = 1
C MPPARN(16) RETURNS A LARGE INTEGER (SEE MPSET).
      ID = (MPPARN(16)/N)/N - 2
C MAIN LOOP.  FIRST REDUCE T IF POSSIBLE
   10 T = TG + 2 + R(I2+1) - R(I3+1)
      IF (T.LT.2) GO TO 40
      T = MIN0 (T, TG)
      IF (RNDRL.NE.0) T = TG
C IF (I+2)*N**2 IS NOT REPRESENTABLE AS AN INTEGER THE DIVISION
C FOLLOWING HAS TO BE PERFORMED IN SEVERAL STEPS.
      IF (I.GE.ID)  GO TO 20
      CALL MPMULQ (R(I2), -I, (I+2)*N*N, R(I2))
      GO TO 30
   20 CALL MPMULQ (R(I2), -I, I+2, R(I2))
      CALL MPMULS (R(I2), 1, 1, N, N)
   30 I = I + 2
C RESTORE T TO WORKING PRECISION
      T = TG
C ACCUMULATE SUM
      CALL MPADD (R(I3), R(I2), R(I3))
C CAN ONLY FALL THROUGH NEXT STATEMENT IF MP UNDERFLOW OCCURED.
      IF (KTU.EQ.KTUNFL) GO TO 10
C RESTORE T ETC., ROUND RESULT AND RETURN
   40 CALL MPRES2 (SV)
      CALL MPRND (R(I3), TG, Y, IABS(T), 1)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPASIN  ******
      SUBROUTINE MPASIN (X, Y)
C RETURNS Y = ARCSIN(X), ASSUMING ABS(X) .LE. 1,
C FOR MP NUMBERS X AND Y.
C Y IS IN THE RANGE -PI/2 TO +PI/2.
C METHOD IS TO USE MPATAN, SO TIME IS O(M(T)T).
C ROUNDING OPTIONS NOT YET IMPLEMENTED, NO GUARD DIGITS USED.
      COMMON R
      INTEGER I2, I3, SV
      INTEGER R(1), X(1), Y(1)
      INTEGER MPCOMP, MPGET
C SAVE T ETC., USE TRUNCATED ARITHMETIC, ALLOCATE SPACE.
      CALL MPSAVN (SV)
      CALL MPSETR (0)
      CALL MPNEW (I2)
      IF (X(1).EQ.0) GO TO 20
      IF (MPGET (X, 2) .LE. 0) GO TO 30
C HERE ABS(X) .GE. 1.  SEE IF X = +-1
      CALL MPCIM (X(1), R(I2))
      IF (MPCOMP(X, R(I2)).NE.0) GO TO 10
C X = +-1 SO RETURN +-PI/2
      CALL MPPI (Y)
      CALL MPDIVI (Y, 2*R(I2), Y)
      GO TO 40
   10 CALL MPERRM (32HABS(X) .GT. 1 IN CALL TO MPASIN$)
   20 Y(1) = 0
      GO TO 40
C HERE ABS(X) .LT. 1 SO USE ARCTAN(X/SQRT(1 - X**2))
   30 CALL MPNEW (I3)
      CALL MPCIM (1, R(I3))
      CALL MPSTR (R(I3), R(I2))
C FOLLOWING SUBTRACTION IS EXACT IF X CLOSE TO 1, ADDITION EXACT IF
C X CLOSE TO -1.  THUS (1 - X**2) IS COMPUTED WITH SMALL RELATIVE ERROR.
      CALL MPSUB (R(I3), X, R(I3))
      CALL MPADD (R(I2), X, R(I2))
      CALL MPMUL (R(I3), R(I2), R(I2))
      CALL MPROOT (R(I2), -2, R(I2))
      CALL MPMUL (X, R(I2), Y)
      CALL MPATAN (Y, Y)
C RESTORE EVERYTHING AND RETURN.
   40 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPATAN  ******
      SUBROUTINE MPATAN (X, Y)
C
C RETURNS Y = ARCTAN(X) FOR MP X AND Y, USING AN O(T.M(T)) METHOD
C WHICH COULD EASILY BE MODIFIED TO AN O(SQRT(T)M(T))
C METHOD (AS IN MPEXP1). Y IS IN THE RANGE -PI/2 TO +PI/2.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C
C FOR AN ASYMPTOTICALLY FASTER METHOD, SEE - FAST MULTIPLE-
C PRECISION EVALUATION OF ELEMENTARY FUNCTIONS
C (BY R. P. BRENT), J. ACM 23 (1976), 242-251,
C AND THE COMMENTS IN MPPIGL.
C
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
C
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, KTUNFL, DUMMY
      INTEGER I, I2, I3, I4, KTU, Q, SV, TG
      INTEGER B, DUMMY(11), KTUNFL, LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR
      INTEGER MPTLB, MXSPTR, R(1), RNDRL, SPTR, T, X(1), Y(1)
      IF (X(1).NE.0) GO TO 10
C ARCTAN (0) = 0.
      Y(1) = 0
      RETURN
C SAVE T ETC.
   10 CALL MPSAVN (SV)
C INCREASE T, ALLOCATE TEMPORARY STORAGE.
      CALL MPGD3 (MPTLB (IABS(T)), TG)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      IF (RNDRL.EQ.1) RNDRL = 0
C MOVE X TO TEMPORARY STORAGE.
      CALL MPMOVE (X, IABS(R(SV)), R(I3), TG)
      Q = 1
C REDUCE ARGUMENT IF NECESSARY BEFORE USING SERIES
   20 IF (R(I3+1).LT.0) GO TO 30
      IF ((R(I3+1).EQ.0).AND.((2*(R(I3+2)+1)).LE.B)) GO TO 30
      Q = 2*Q
      CALL MPREVR (R(I3))
      CALL MPMUL (R(I3), R(I3), R(I2))
      CALL MPADDI (R(I2), 1, R(I2))
      CALL MPSQRT (R(I2), R(I2))
      CALL MPADDI (R(I2), 1, R(I2))
      CALL MPREVR (R(I3))
      CALL MPDIV (R(I3), R(I2), R(I3))
      GO TO 20
C USE POWER SERIES NOW ARGUMENT IN (-0.5, 0.5)
   30 CALL MPNEW (I4)
      CALL MPSTR (R(I3), R(I4))
      KTU = KTUNFL
      CALL MPMUL (R(I3), R(I3), R(I2))
      I = 1
C SERIES LOOP.  REDUCE T IF POSSIBLE.
   40 T = TG + 2 + R(I3+1)
      IF (T.LE.2) GO TO 50
      T = MIN0 (T, TG)
      IF (RNDRL .NE. 0) T = TG
      CALL MPMUL (R(I3), R(I2), R(I3))
      CALL MPMULQ (R(I3), -I, I+2, R(I3))
      I = I + 2
      T = TG
      CALL MPADD (R(I4), R(I3), R(I4))
C FALL THROUGH END OF LOOP IF UNDERFLOW OCCURRED ABOVE.
      IF (KTU.EQ.KTUNFL) GO TO 40
C CORRECT FOR ARGUMENT REDUCTION.
   50 T = TG
      CALL MPMULI (R(I4), Q, R(I4))
C ROUND RESULT, RESTORE T ETC. AND RETURN.
      CALL MPRND (R(I4), TG, Y, IABS(R(SV)), 1)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPATN2  ******
      SUBROUTINE MPATN2 (X, Y, Z)
C SETS Z = ARCTAN (X/Y) IF Y NONZERO,
C        = PI/2         IF Y ZERO,
C FOR (PACKED OR UNPACKED) MP X, UNPACKED MP Y.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, DUMMY
      INTEGER I2, I3, SV, TG, Z(1)
      INTEGER B, DUMMY(17), LUN, M, MXR, R(1), SPTR, T, X(1), Y(1)
C SAVE T ETC., INCREASE WORKING PRECISION, ALLOCATE SPACE.
      CALL MPSAVN (SV)
      CALL MPGD3 (1, TG)
      CALL MPNEW (I2)
C CHECK FOR Y ZERO.
      IF (Y(1).NE.0) GO TO 10
      CALL MPPI (R(I2))
      CALL MPDIVI (R(I2), 2, R(I2))
      GO TO 20
C HERE Y NONZERO, INCREASE M SO X/Y DOES NOT OVER/UNDERFLOW.
   10 M = 2*M + 2
      CALL MPNEW (I3)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPMOVE (Y, IABS(R(SV)), R(I3), TG)
      CALL MPDIV (R(I2), R(I3), R(I2))
C FREE SOME SPACE.
      SPTR = I3
C USE MPATAN(X/Y)
      CALL MPATAN (R(I2), R(I2))
C ROUND RESULT, RESTORE T ETC. AND RETURN.
   20 CALL MPRND (R(I2), TG, Z, IABS(R(SV)), 1)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPBASA  ******
      INTEGER FUNCTION MPBASA (X)
C RETURNS THE MP BASE (FIRST WORD IN COMMON /MPCOM/).
C X IS A DUMMY MP ARGUMENT.
      INTEGER MPPARN, X(1)
      MPBASA = MPPARN (1)
      RETURN
      END
C $$                   ******  MPBASB  ******
      SUBROUTINE MPBASB (I, X)
C SETS THE MP BASE (FIRST WORD OF COMMON /MPCOM/) TO I.
C I SHOULD BE AN INTEGER SUCH THAT I .GE. 2
C AND (8*I*I-1) IS REPRESENTABLE AS A SINGLE-PRECISION INTEGER.
C X IS A DUMMY MP ARGUMENT (AUGMENT EXPECTS ONE).
C WARNING - SETTING THE BASE DOES NOT AUTOMATICALLY CONVERT MP
C NUMBERS TO THE NEW BASE.  THIS MAY BE DONE BY CONVERTING TO
C DECIMAL (USING MPFOUT), CHANGING THE BASE (USING MPBASB),
C THEN CONVERTING FROM DECIMAL TO THE NEW BASE (USING MPFIN).
      INTEGER I, X(1)
      CALL MPPARC (1, I)
      RETURN
      END
C $$                   ******  MPBERN  ******
      SUBROUTINE MPBERN (N, P, X)
C
C COMPUTES THE BERNOULLI NUMBERS B2 = 1/6, B4 = -1/30,
C B6 = 1/42, B8 = -1/30, B10 = 5/66, B12 = -691/2730, ETC.,
C DEFINED BY THE GENERATING FUNCTION Y/(EXP(Y)-1).
C N AND P ARE SINGLE-PRECISION INTEGERS, WITH 2*P .GE. T+2.
C X SHOULD BE A ONE-DIMENSIONAL INTEGER ARRAY OF DIMENSION AT
C LEAST P*N.  THE BERNOULLI NUMBERS B2, B4, ... , B(2N) ARE
C RETURNED IN PACKED FORMAT IN X, WITH B(2J) IN LOCATIONS
C X((J-1)*P+1), ... , X(P*J).  THUS, TO GET B(2J) IN USUAL
C MP FORMAT IN Y, ONE SHOULD CALL MPUNPK (X(IX), Y) AFTER
C CALLING MPBERN, WHERE IX = (J-1)*P+1.
C
C ALTERNATIVELY (SIMPLER BUT NONSTANDARD) -
C X MAY BE A TWO-DIMENSIONAL INTEGER ARRAY DECLARED WITH
C DIMENSION (P, N1), WHERE N1 .GE. N AND 2*P .GE. T+2.
C THEN B2, B4, ... , B(2N) ARE RETURNED IN PACKED FORMAT IN
C X, WITH B(2J) IN X(1,J), ... , X(P,J).  THUS, TO GET
C B(2J) IN USUAL MP FORMAT IN Y ONE SHOULD
C CALL MPUNPK (X(1, J), Y) AFTER CALLING MPBERN.
C
C THE WELL-KNOWN RECURRENCE IS UNSTABLE (LOSING ABOUT 2J BITS
C OF RELATIVE ACCURACY IN THE COMPUTED B(2J)), SO WE USE A
C DIFFERENT RECURRENCE DERIVED BY EQUATING COEFFICIENTS IN
C (SINH(Y)/Y)*(SIGMA B(2J)*(2Y)**(2J)/FACTORIAL(2J)) = COSH Y,
C WHERE THE SUMMATION IS FROM J = 0 TO INFINITY.  THIS METHOD
C WAS SUGGESTED BY CHRISTIAN REINSCH, AND IS FASTER THAN THE METHOD
C USED IN EARLIER VERSIONS OF MPBERN.  THE RELATION
C B(2J) = -2*((-1)**J)*FACTORIAL(2J)*ZETA(2J)/((2PI)**(2J))
C IS USED IF ZETA(2J) IS EQUAL TO 1 TO WORKING ACCURACY.
C A DIFFERENT METHOD IS GIVEN BY KNUTH AND BUCKHOLTZ IN
C MATH. COMP. 21 (1967), 663-688.
C
C TIME IS O(T*(MIN(N, T)**2) + N*M(T)).
C
C ROUNDING OPTIONS NOT IMPLEMENTED, NO GUARD DIGITS USED.
C THE RELATIVE ERROR IN B(2J) IS O((J**2)*(B**(1-T))).
C
C IF N IS NEGATIVE, ABS(N) BERNOULLI NUMBERS ARE RETURNED, BUT
C THE COMMENT ABOVE ABOUT RELATIVE ERROR NO LONGER APPLIES -
C INSTEAD THE PRECISION DECREASES LINEARLY FROM THE FIRST TO THE
C LAST BERNOULLI NUMBER (THIS IS USUALLY SUFFICIENT IF THE
C BERNOULLI NUMBERS ARE TO BE USED AS COEFFICIENTS IN AN
C EULER-MACLAURIN EXPANSION).
C
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, IX, I2, I3, I4, J, NL, NP, N2, SV
      INTEGER B, DUMMY(21), MPTLB, N, P, R(1), T, X(1)
      NL = IABS(N)
      IF (NL.LE.0) RETURN
      CALL MPSAVN (SV)
      IF ((2*P) .LT. (R(SV)+2)) CALL MPERRM (
     $   30HP TOO SMALL IN CALL TO MPBERN$)
C ALLOCATE WORKING SPACE, USE TRUNCATED ARITHMETIC.
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPSETR (0)
C COMPUTE UPPER LIMIT FOR RECURRENCE RELATION METHOD.
      N2 = MIN0 (NL, MPTLB(IABS(R(SV)))/2)
C SET ALL RESULTS TO ZERO
      NP = NL*P
      DO 30 I = 1, NP
   30 X(I) = 0
      CALL MPCQM (1, 12, R(I2))
      CALL MPSTR (R(I2), R(I3))
C MAIN LOOP TO GENERATE SCALED BERNOULLI NUMBERS
      DO 70 J = 1, N2
C DECREASE T IF N NEGATIVE.
      IF (N .LT. 0) T = MIN0 (R(SV), ((NL+1-J)*(R(SV)-2))/NL + 4)
      IX = (J-1)*P + 1
      CALL MPPACK (R(I3), X(IX))
      IF (J.GE.N2) GO TO 80
      CALL MPMULS (R(I2), 1, 1, 4*J, 4*J+6)
      CALL MPSTR (R(I2), R(I3))
      DO 60 I = 1, J
C CHANGE T IF N NEGATIVE.
      IF (N .LT. 0) T = MIN0 (R(SV), ((NL+1-I)*(R(SV)-2))/NL + 4)
      IX = (I-1)*P + 1
      CALL MPUNPK (X(IX), R(I4))
      CALL MPMULS (R(I4), 1, 1, 4*(J-I)+4, 4*(J-I)+6)
      CALL MPPACK (R(I4), X(IX))
   60 CALL MPSUB (R(I3), R(I4), R(I3))
   70 CONTINUE
C NOW UNSCALE RESULTS
   80 T = R(SV)
      CALL MPCIM (1, R(I2))
      IF (N2.LE.1) GO TO 100
      I = N2
   90 CALL MPMULS (R(I2), 4*(N2-I)+4, 4*(N2-I)+6, 1, 1)
      I = I - 1
      IX = (I-1)*P + 1
      CALL MPUNPK (X(IX), R(I4))
      CALL MPMUL (R(I2), R(I4), R(I4))
      CALL MPPACK (R(I4), X(IX))
      IF (I.GT.1) GO TO 90
C NOW HAVE B(2J)/FACTORIAL(2J) IN X
      CALL MPCIM (1, R(I2))
  100 DO 110 I = 1, N2
      CALL MPMULS (R(I2), 2*I-1, 2*I, 1, 1)
      IX = (I-1)*P + 1
      CALL MPUNPK (X(IX), R(I4))
      CALL MPMUL (R(I2), R(I4), R(I4))
  110 CALL MPPACK (R(I4), X(IX))
C RETURN IF FINISHED
      IF (NL.LE.N2) GO TO 130
C ELSE COMPUTE REMAINING NUMBERS
      CALL MPPI (R(I3))
      CALL MPPWR (R(I3), -2, R(I3))
      CALL MPDIVI (R(I3), -4, R(I3))
      N2 = N2 + 1
      DO 120 I = N2, NL
      CALL MPMUL (R(I4), R(I3), R(I4))
      CALL MPMULS (R(I4), 2*I-1, 2*I, 1, 1)
      IX = (I-1)*P + 1
  120 CALL MPPACK (R(I4), X(IX))
C RESTORE STACK POINTER ETC. AND RETURN.
  130 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPBESJ  ******
      SUBROUTINE MPBESJ (X, NU, Y)
C RETURNS Y = J(NU,X), THE FIRST-KIND BESSEL FUNCTION OF ORDER NU,
C FOR SMALL INTEGER NU, MP X AND Y.
C THE METHOD IS HANKELS ASYMPTOTIC EXPANSION IF
C ABS(X) LARGE, THE POWER SERIES IF ABS(X) SMALL, AND THE
C BACKWARD RECURRENCE METHOD OTHERWISE.
C RESULTS FOR NEGATIVE ARGUMENTS ARE DEFINED BY
C J(-NU,X) = J(NU,-X) = ((-1)**NU)*J(NU,X).
C ERROR COULD BE INDUCED BY O(B**(1-T)) PERTURBATIONS
C IN X AND Y.  TIME IS O(T.M(T)) FOR FIXED X AND NU, INCREASES
C AS X AND NU INCREASE, UNLESS X LARGE ENOUGH FOR ASYMPTOTIC
C SERIES TO BE USED.
C ROUNDING OPTIONS NOT YET IMPLEMENTED, USES TRUNCATED ARITHMETIC.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      LOGICAL ERROR
      INTEGER IE, IT, I2, I3, I4, K, MXINT, NUA, SV, TG, TM,
     $  B, DUMMY(21), NU, R(1), T, X(1), Y(1),
     $  MPCHGB, MPGET, MPPARN
      NUA = IABS(NU)
C CHECK FOR X ZERO
      IF (X(1).NE.0) GO TO 10
C J(NU,0) = 0 IF NU .NE. 0, 1 IF NU .EQ. 0
      Y(1) = 0
      IF (NUA.EQ.0) CALL MPCIM (1, Y)
      RETURN
C SAVE T ETC., USE TRUNCATED ARITHMETIC.
   10 CALL MPSAVN (SV)
      CALL MPSETR (0)
      MXINT = MPPARN(16)
C SEE IF ABS(X) SO LARGE THAT NO ACCURACY POSSIBLE
      IF (MPGET (X, 2).GE.T) CALL MPERRM (
     $  35HABS(X) TOO LARGE IN CALL TO MPBESJ$)
C X NONZERO SO TRY HANKEL ASYMPTOTIC SERIES WITH GUARD DIGITS.
      CALL MPGD3 (1, TG)
      CALL MPNEW (I2)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPHANK (R(I2), NUA, R(I2), ERROR)
C GO TO ROUNDING OF FINAL RESULT IF ASYMPTOTIC SERIES ACCURATE.
      IF (.NOT. ERROR) GO TO 40
C ASYMPTOTIC SERIES NOT GOOD ENOUGH SO RESTORE T ETC.
      CALL MPRESN (SV)
      CALL MPSAVN (SV)
      CALL MPSETR (0)
C MAY NEED TO INCREASE T LATER SO PREPARE FOR THIS
C MAX ALLOWABLE T IS APPROXIMATELY DOUBLE
      TM = 2*TG
      TG = T
C NO APPRECIABLE CANCELLATION IN POWER SERIES IF ABS(X) .LT. 1
      IF (MPGET (X, 2).LE.0) GO TO 20
C ESTIMATE NUMBER OF DIGITS REQUIRED TO COMPENSATE FOR CANCELLATION.
C FIRST REDUCE T TO EQUIVALENT OF 6 DECIMAL PLACES (COULD USE
C SINGLE-PRECISION REAL ARITHMETIC HERE IF TRUSTED).
      T = MIN0 (T, MAX0 (2, MPCHGB (IABS(B), 10, 5) + 1))
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPABS (X, R(I2))
      CALL MPDIVI (R(I2), 2, R(I3))
      CALL MPLN (R(I3), R(I3))
      CALL MPMULQ (R(I3), 2*NUA + 1, 2, R(I3))
      CALL MPADD (R(I2), R(I3), R(I2))
      CALL MPLNI (IABS(B), R(I3))
      CALL MPDIV (R(I2), R(I3), R(I2))
      CALL MPCMI (R(I2), IT)
      CALL MPRESN (SV)
      CALL MPSAVN (SV)
      CALL MPSETR (0)
      TG = T + MAX0 (0, IT + 1)
C IF NEED MORE DIGITS THAN SPACE ALLOWS FOR POWER SERIES THEN
C USE RECURRENCE METHOD INSTEAD
      IF (TG.GT.TM) GO TO 50
C PREPARE FOR POWER SERIES LOOP
   20 T = TG
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      T = R(SV)
      CALL MPDIVI (X, 2, R(I4))
      CALL MPPWRA (R(I4), NUA, R(I4))
      CALL MPGAMQ (NUA+1, 1, R(I2))
      CALL MPDIV (R(I4), R(I2), R(I4))
      CALL MPMUL (X, X, R(I3))
      CALL MPDIVI (R(I3), -4, R(I3))
C CLEAR TRAILING DIGITS OF R(I3) AND R(I4).
      CALL MPMOVE (R(I3), IABS(R(SV)), R(I3), TG)
      CALL MPMOVE (R(I4), IABS(R(SV)), R(I4), TG)
      CALL MPMOVE (R(I4), TG, R(I2), TG)
      IE = R(I2+1)
      K = 0
C POWER SERIES LOOP, REDUCE T IF POSSIBLE
   30 T = MIN0 (TG, TG + 2 + R(I4+1) - IE)
      IF (T.LT.2) GO TO 40
      CALL MPMUL (R(I3), R(I4), R(I4))
      K = K + 1
      IF ((K+NUA) .GT. (MXINT/2)) CALL MPERRM (
     $  36HABS(NU) TOO LARGE IN CALL TO MPBESJ$)
      CALL MPMULS (R(I4), 1, 1, K, K+NUA)
C RESTORE T FOR ADDITION
      T = TG
      CALL MPADD (R(I2), R(I4), R(I2))
      IF ((R(I4).NE.0).AND.(R(I4+1).GE.(R(I2+1)-R(SV)))) GO TO 30
C RESTORE T ETC. AND ROUND FINAL RESULT
   40 CALL MPRES2 (SV)
      CALL MPRND (R(I2), TG, Y, IABS(R(SV)), 0)
C NOW RESTORE STACK POINTER
      CALL MPRESN (SV)
C CORRECT SIGN IF NU ODD AND NEGATIVE
      IF ((NU.LT.0).AND.(MOD(NUA,2).NE.0)) Y(1) = -Y(1)
      RETURN
C HERE USE BACKWARD RECURRENCE METHOD WITH GUARD DIGITS
   50 CALL MPGD3 (1, TG)
      CALL MPNEW (I2)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      R(I2) = IABS(R(I2))
      CALL MPBES2 (R(I2), NUA, R(I2))
C CORRECT SIGN IF NUA ODD
      IF (MOD (NUA,2) .NE. 0) R(I2) = X(1)*R(I2)
      GO TO 40
      END
C $$                   ******  MPBES2  ******
      SUBROUTINE MPBES2 (X, NU, Y)
C USES THE BACKWARD RECURRENCE METHOD TO EVALUATE Y = J(NU,X),
C WHERE X AND Y ARE MP NUMBERS, NU (THE INDEX) IS AN INTEGER,
C AND J IS THE BESSEL FUNCTION OF THE FIRST KIND.  ASSUMES THAT
C 0 .LE. NU (NOT TOO LARGE) AND X .GT. 0.
C FOR NORMALIZATION THE IDENTITY
C J(0,X) + 2*J(2,X) + 2*J(4,X) + ... = 1  IS USED.
C CALLED BY MPBESJ AND NOT RECOMMENDED FOR INDEPENDENT USE.
C ROUNDING OPTIONS NOT IMPLEMENTED, USES NO GUARD DIGITS.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, T, DUMMY(21), MPCHGB, MPCMPI
      INTEGER I, I2, I3, I3S, I4, I5, I6, NU1, SV
      INTEGER NU, R(1), X(1), Y(1), MPPARN
C CHECK LEGALITY OF NU AND X
      IF ((NU.GE.0) .AND. (X(1).EQ.1)) GO TO 20
   10 CALL MPERRM (34HNU OR X ILLEGAL IN CALL TO MPBES2$)
   20 CALL MPSAVN (SV)
C ALLOCATE TEMPORARY SPACE
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
C USE TRUNCATED ARITHMETIC
      CALL MPSETR (0)
C USE ABOUT 6 DECIMAL PLACES TO COMPUTE STARTING POINT
      T = MIN0 (T, MAX0 (3, MPCHGB (IABS(B), 10, 5) + 1))
      CALL MPCIM (MAX0 (1, NU), R(I2))
      CALL MPMULI (R(I2), 2, R(I3))
      CALL MPDIV (R(I3), X, R(I3))
      CALL MPLN (R(I3), R(I3))
      CALL MPADDI (R(I3), -1, R(I3))
      CALL MPCIM (1, R(I4))
      CALL MPMAX (R(I3), R(I4), R(I3))
      CALL MPMUL (R(I2), R(I3), R(I3))
      CALL MPLNI (IABS(B), R(I2))
      CALL MPMULQ (R(I2), IABS(R(SV)), 2, R(I2))
      CALL MPADD (R(I2), R(I3), R(I2))
      CALL MPDIV (R(I2), X, R(I2))
C 125/92 .LT. E/2
      CALL MPMULQ (R(I2), 92, 125, R(I2))
      CALL MPCIM (2, R(I4))
      CALL MPMAX (R(I2), R(I4), R(I2))
      CALL MPSTR (R(I2), R(I3))
C DO TWO NEWTON ITERATIONS
      DO 30 I = 1, 2
      CALL MPADD (R(I2), R(I3), R(I4))
      CALL MPLN (R(I3), R(I3))
      CALL MPADDI (R(I3), 1, R(I3))
   30 CALL MPDIV (R(I4), R(I3), R(I3))
      CALL MPMUL (R(I3), X, R(I2))
C 34/25 .GT. E/2
      CALL MPMULQ (R(I2), 34, 25, R(I2))
      IF (MPCMPI (R(I2), MPPARN(16)-2) .GT. 0) GO TO 10
      CALL MPCMI (R(I2), NU1)
      NU1 = NU1 + 2
C NOW RESTORE T
      T = R(SV)
      CALL MPNEW (I5)
      CALL MPNEW (I6)
      CALL MPCIM (MOD(NU1+1,2), R(I6))
      CALL MPREC (X, R(I2))
      CALL MPMULI (R(I2), 2, R(I2))
      R(I3) = 0
      CALL MPCIM (1, R(I4))
C BACKWARD RECURRENCE LOOP
   40 CALL MPMUL (R(I4), R(I2), R(I5))
      CALL MPMULI (R(I5), NU1, R(I5))
      CALL MPSUB (R(I5), R(I3), R(I5))
      NU1 = NU1 - 1
C FASTER TO INTERCHANGE POINTERS THAN MP NUMBERS
      I3S = I3
      I3 = I4
      I4 = I5
      I5 = I3S
      IF (MOD(NU1,2) .NE. 0) GO TO 50
C NU1 EVEN SO UPDATE NORMALIZING SUM
      IF (NU1.EQ.0) CALL MPMULI (R(I6), 2, R(I6))
      CALL MPADD (R(I6), R(I4), R(I6))
C SAVE UNNORMALIZED RESULT IF NU1 .EQ. NU
   50 IF (NU1.EQ.NU) CALL MPSTR (R(I4), Y)
      IF (NU1.GT.0) GO TO 40
C NORMALIZE RESULT AND RETURN
      CALL MPDIV (Y, R(I6), Y)
C RESTORE STACK POINTER ETC. AND RETURN.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCAM  ******
      SUBROUTINE MPCAM (A, X)
C CONVERTS THE HOLLERITH STRING A TO AN MP NUMBER X.
C A CAN BE A STRING OF DIGITS ACCEPTABLE TO ROUTINE MPIN
C AND TERMINATED BY A DOLLAR ($), E.G. 7H-5.367$,
C OR ONE OF THE FOLLOWING SPECIAL STRINGS -
C            EPS  (MP MACHINE-PRECISION, SEE MPEPS),
C            EUL  (EULERS CONSTANT 0.5772..., SEE MPEUL),
C            MAXR (LARGEST VALID MP NUMBER, SEE MPMAXR),
C            MINR (SMALLEST POSTIVE MP NUMBER, SEE MPMINR),
C            PI   (PI = 3.14..., SEE MPPI).
C ONLY THE FIRST TWO CHARACTERS OF THESE STRINGS ARE CHECKED.
C WORST-CASE SPACE = 2*N + O(T) WORDS, WHERE N IS THE LENGTH IN
C CHARACTERS OF THE STRING A.
C THE ERROR MESSAGE
C     *** MXR TOO SMALL ... ***
C IS USUALLY CAUSED BY OMISSION OF THE SENTINEL $
      COMMON R
      INTEGER A(1), D(2), I2, I3, LEN, N, R(1), SV, X(1),
     $  HA, HE, HI, HM, HP, HU
      LOGICAL ERROR, MPIS
      DATA HA, HE, HI, HM, HP, HU
     $  /1HA, 1HE, 1HI, 1HM, 1HP, 1HU/
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      R(I2) = 0
      LEN = R(SV) + 2
C UNPACK FIRST 2 CHARACTERS OF A
      CALL MPUPK (A, D, 2, N)
      IF (N.NE.2) GO TO 10
C CHECK FOR SPECIAL STRINGS
      IF (MPIS (D(1), HE) .AND. MPIS (D(2), HP)) CALL MPEPS (R(I2))
      IF (MPIS (D(1), HE) .AND. MPIS (D(2), HU)) CALL MPEUL (R(I2))
      IF (MPIS (D(1), HM) .AND. MPIS (D(2), HA)) CALL MPMAXR (R(I2))
      IF (MPIS (D(1), HM) .AND. MPIS (D(2), HI)) CALL MPMINR (R(I2))
      IF (MPIS (D(1), HP) .AND. MPIS (D(2), HI)) CALL MPPI (R(I2))
C IF R(I2) NONZERO ONE OF ABOVE TESTS WAS SUCCESSFUL.
      IF (R(I2) .EQ. 0) GO TO 10
      CALL MPSTR (R(I2), X)
      GO TO 20
C LEN IS GUESS AT STRING LENGTH - DOUBLE AND TRY AGAIN IF TOO SHORT.
C FIRST ALLOCATE NECESSARY EXTRA SPACE.
   10 CALL MPNEW2 (I3, LEN)
      LEN = 2*LEN
C UNPACK UP TO LEN CHARACTERS OF STRING
      CALL MPUPK (A, R(I2), LEN, N)
C IF N .LT. LEN THEN LEN WAS LARGE ENOUGH, ELSE LOOP
      IF (N.GE.LEN) GO TO 10
C CONVERT UNPACKED STRING TO MP NUMBER.
      CALL MPIN (R(I2), X, N, ERROR)
      IF (ERROR) CALL MPERRM (
     $  45HERROR IN HOLLERITH CONSTANT IN CALL TO MPCAM$)
C RESTORE STACK POINTER AND RETURN
   20 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCDM  ******
      SUBROUTINE MPCDM (DX, Z)
C CONVERTS DOUBLE-PRECISION NUMBER DX TO MULTIPLE-PRECISION Z.
C SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
C WITH BASE OTHER THAN TWO OR IF B IS NOT A POWER OF TWO WITH
C B**(T-1) SUFFICIENTLY LARGE.  THUS MPCDM SHOULD BE USED ONLY TO
C OBTAIN STARTING APPROXIMATIONS ETC.  FOR ACCURATE INITIALIZATION
C OF MP NUMBERS USE MPCIM, MPCQM, MPQPWR, OR MPIN.
C WARNING - THE PARAMETER RNDRL IN COMMON /MPCOM/ HAS NO EFFECT.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, DUMMY(21), I, IE, ISV, J, RE, RS, SV, T,
     $  THREE, Z(1)
      DOUBLE PRECISION DB, DJ, DX, DBLE
      REAL FLOAT
      CALL MPSAVN (SV)
      CALL MPSETR (0)
      THREE = 3
C CHECK SIGN
      IF (DX) 20, 10, 30
C IF DX = 0D0 RETURN 0
   10 Z(1) = 0
      GO TO 100
C DX .LT. 0D0
   20 RS = -1
      DJ = -DX
      GO TO 40
C DX .GT. 0D0
   30 RS = 1
      DJ = DX
C WE WANT TO REDUCE DJ TO RANGE 1/16 .LE. DJ .LT. 1.
   40 IE = 0
   50 IF (DJ.LT.1D0) GO TO 60
C INCREASE IE AND DIVIDE DJ BY 16.
      IE = IE + 1
      DJ = 0.0625D0*DJ
      GO TO 50
   60 IF (DJ.GE.0.0625D0) GO TO 70
      IE = IE - 1
      DJ = 16D0*DJ
      GO TO 60
C NOW DJ IS DY DIVIDED BY SUITABLE POWER OF 16.
C SET EXPONENT TO 0
   70 RE = 0
C DFLOAT IS NOT ANSI STANDARD, BELIEVE IT OR NOT
      DB = DBLE(FLOAT(B))
C CONVERSION LOOP (ASSUME SINGLE-PRECISION OPS. EXACT)
      DO 80 I = 1, T
      DJ = DB*DJ
      ISV = I
      J = IDINT(DJ)
C CHECK FOR (UNLIKELY) EFFECT OF STRANGE FLOATING-POINT ARITHMETIC.
      IF (J.GE.B) GO TO 110
      IF (DJ.LT.0.0D0) GO TO 120
      Z(I+2) = J
   80 DJ = DJ - DBLE(FLOAT(J))
C NORMALIZE RESULT
   90 CALL MPNZR (RS, RE, Z(1), Z(THREE), 0)
C NOW MULTIPLY BY 16**IE
      CALL MPSCAL (Z, 16, IE)
C CAN RETURN NOW
  100 CALL MPRESN (SV)
      RETURN
C HERE A DIGIT IS .GE. B, WHICH SHOULD NEVER HAPPEN
  110 J = B-1
      GO TO 130
C HERE A DIGIT IS NEGATIVE, WHICH SHOULD NEVER HAPPEN
  120 J = 0
C SET REMAINING DIGITS TO J (EITHER B-1 OR 0)
  130 DO 140 I = ISV, T
  140 Z(I+2) = J
      GO TO 90
      END
C $$                   ******  MPCEIL  ******
      SUBROUTINE MPCEIL (X, Y)
C SETS Y = CEILING (X), I.E. THE SMALLEST INTEGER NOT LESS THAN X.
C X AND Y ARE MP NUMBERS.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/
C (THIS IS ONLY RELEVANT IF X IS LARGE AND POSITIVE) -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      INTEGER I2, MPCOMP, R(1), SV, X(1), Y(1)
C SAVE T ETC. AND TRUNCATE X (TOWARDS ZERO) TO AN INTEGER.
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPCMIM (X, R(I2))
C IF X POSITIVE AND NOT AN INTEGER NEED TO ADD 1
      IF ((X(1).GT.0) .AND. (MPCOMP (X, R(I2)).NE.0))
     $          CALL MPADDI (R(I2), 1, R(I2))
C MOVE RESULT, RESTORE EVERYTHING AND RETURN.
      CALL MPSTR (R(I2), Y)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCHEB  ******
      SUBROUTINE MPCHEB (C, NC, N, IND)
C
C CONVERTS THE POWER SERIES COEFFICIENTS C(1), ... , C(N) TO
C CHEBYSHEV SERIES COEFFICIENTS.  (IT IS ASSUMED THAT THE CONSTANT
C TERM IN THE CHEBYSHEV SUM IS HALVED.)
C IND = 0 MEANS THAT C(I) IS THE COEFFICIENT OF X**(I-1) ON INPUT,
C         OF T(I-1)(X) ON OUTPUT,
C IND = -1 MEANS THAT C(I) IS THE COEFFICIENT OF X**(2I-1) ON INPUT,
C         OF T(2I-1)(X) ON OUTPUT,
C IND = +1 MEANS THAT C(I) IS THE COEFFICIENT OF X**(2I-2) ON INPUT,
C          OF T(2I-2) ON OUTPUT.
C C IS AN ARRAY OF MP VARIABLES WITH FIRST DIMENSION NC (FOR
C AUGMENT USERS, NC = MT2).
C
      INTEGER I, I1, J, JJ, J1, J2, SV
C     INTEGER N, NC  (UNIVAC FORTRAN V DOES NOT ALLOW THIS)
      INTEGER C(NC,N), IND, MPPARN
      CALL MPSAVN (SV)
C USE TRUNCATED ARITHMETIC AND NO GUARD DIGITS.
      CALL MPSETR (0)
C CHECK LEGALITY OF NC, N AND IND.
      IF ((NC .LT. (MPPARN(2)+2)) .OR. (N .LE. 0) .OR.
     $  (IABS(IND) .GT. 1)) CALL MPERRM (
     $  36HILLEGAL ARGUMENTS ON CALL TO MPCHEB$)
      DO 40 JJ = 1, N
      J = N + 1 - JJ
      CALL MPMULI (C(1,J), 2, C(1,J))
      J2 = J + 2 - IABS(IND)
      IF (J2 .LE. N) CALL MPADD (C(1,J), C(1,J2), C(1,J))
      J1 = J + 1
      IF (J1 .GT. N) GO TO 20
      DO 10 I = J1, N
      I1 = I + 2 - IABS(IND)
      IF (I1 .LE. N) CALL MPADD (C(1,I), C(1,I1), C(1,I))
   10 CALL MPDIVI (C(1,I), 2, C(1,I))
   20 IF (((J .EQ. 1) .AND. (IND .EQ. 1)) .OR. (IND .EQ. 0))
     $  GO TO 40
      DO 30 I = J, N
      IF (I .LT. N) CALL MPADD (C(1,I), C(1,I+1), C(1,I))
   30 CALL MPDIVI (C(1,I), 2, C(1,I))
   40 CONTINUE
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCHEV  ******
      SUBROUTINE MPCHEV (C, NC, N, IND, X, Y)
C RETURNS Y = CHEBYSHEV SERIES EVALUATED AT X.
C X AND Y ARE MP VARIABLES, MP COEFFICIENTS ARE IN C,
C FOR A DESCRIPTION OF C, NC, N AND IND SEE MPCHEB.
      COMMON R
      INTEGER I, II, ISV, I2, I3, I4, I5, SV
C     INTEGER N, NC  (UNIVAC FORTRAN V DOES NOT ALLOW THIS)
      INTEGER C(NC,N), IND, MPPARN, R(1), X(1), Y(1)
      CALL MPSAVN (SV)
C USE TRUNCATED ARITHMETIC, NO GUARD DIGITS.
      CALL MPSETR (0)
C CHECK LEGALITY OF NC, N AND IND.
      IF ((NC .LT. (MPPARN(2)+2)) .OR. (N .LE. 0) .OR.
     $  (IABS(IND) .GT. 1)) CALL MPERRM (
     $  36HILLEGAL ARGUMENTS ON CALL TO MPCHEV$)
C ALLOCATE WORKING SPACE
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPNEW (I5)
      R(I2) = 0
      R(I3) = 0
      CALL MPMULI (X, 2, R(I5))
      IF (IND .EQ. 0) GO TO 10
      CALL MPMUL (R(I5), R(I5), R(I5))
      CALL MPADDI (R(I5), (-2), R(I5))
   10 DO 20 II = 1, N
      I = N + 1 - II
C INTERCHANGE POINTERS RATHER THAN MP NUMBERS.
      ISV = I4
      I4 = I3
      I3 = I2
      I2 = ISV
      CALL MPMUL (R(I5), R(I3), R(I2))
      CALL MPSUB (R(I2), R(I4), R(I2))
   20 CALL MPADD (R(I2), C(1, I), R(I2))
      IF (IND .GE. 0) GO TO 30
      CALL MPSUB (R(I2), R(I3), R(I2))
      CALL MPMUL (X, R(I2), Y)
      GO TO 40
   30 CALL MPSUB (R(I2), R(I4), R(I2))
      CALL MPDIVI (R(I2), 2, Y)
C RESTORE EVERYTHING AND RETURN.
   40 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCHGB  ******
      INTEGER FUNCTION MPCHGB (B1, B2, N)
C RETURNS J SUCH THAT B1**ABS(J) .GE. B2**ABS(N),
C I.E.    ABS(J) .GE. ABS(N)*LOG(B2)/LOG(B1),
C AND     SIGN(J) = SIGN(N),
C ASSUMING B1 .GT. 1, B2 .GE. 1, B1*B2 .LE. MXINT .
C USUALLY THE VALUE OF J RETURNED IS CLOSE TO MINIMAL.
      INTEGER B1, B2, J, K, MB, MPPARN, MUL, MXINT, N, N2, Q
      MXINT = MPPARN(16)
      MB = MXINT/B1
      IF ((B1 .LE. 1) .OR. (B2 .LE. 0) .OR. (B2 .GT. MB))
     $  CALL MPERRM (36HILLEGAL ARGUMENTS IN CALL TO MPCHGB$)
      J = 0
      IF ((N .EQ. 0) .OR. (B2 .EQ. 1)) GO TO 60
      K = 0
      Q = 1
C THE CONSTANT 100 IS LARGE ENOUGH TO GIVE REASONABLE ACCURACY.
C IF IT IS INCREASED THE TIME REQUIRED WILL INCREASE.
      MUL = (IABS(N)-1)/100 + 1
      N2 = (IABS(N)-1)/MUL + 1
C INCREASE J AND K, KEEPING Q .LE. B1**J/B2**K
   10 IF (K .GE. N2) GO TO 40
   20 IF (Q .GT. MB) GO TO 30
      Q = B1*Q
      J = J + 1
      GO TO 20
   30 Q = Q/B2
      K = K + 1
      GO TO 10
C FINAL STAGE, MAY HAVE OVERSHOT
   40 IF (Q .LT. B1) GO TO 50
      Q = Q/B1
      J = J - 1
      GO TO 40
C CHECK IF RESULT WOULD OVERFLOW
   50 IF (J .GT. (MXINT/MUL)) CALL MPERRM (
     $  30HN TOO LARGE IN CALL TO MPCHGB$)
      J = ISIGN (MUL*J, N)
   60 MPCHGB = J
      RETURN
      END
C $$                   ******  MPCHK  ******
      SUBROUTINE MPCHK
C CHECKS LEGALITY OF PARAMETERS WHICH SHOULD BE SET IN
C COMMON /MPCOM/, ALSO UPDATES MXSPTR.
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, KTUNFL, MXUNFL, DECPL, MT2,
     $  MXINT, EXWID, INRECL, INBASE, OUTBAS, EXPCH, CHWORD, ONESCP
      INTEGER B, CHWORD, DECPL, EXPCH, EXWID, INBASE, INRECL, KTUNFL,
     $  LUN, M, MNEXPN, MNSPTR, MT2, MXEXPN, MXINT, MXR, MXSPTR, MXUNFL,
     $  ONESCP, OUTBAS, RNDRL, SPTR, T, IB, JSP
C FIRST CHECK THAT LUN IN RANGE 1 TO 99, IF NOT PRINT ERROR
C MESSAGE ON LOGICAL UNIT 6.
      IF ((0.LT.LUN) .AND. (LUN.LT.100)) GO TO 20
      WRITE (6, 10) LUN
   10 FORMAT (10H *** LUN =, I10, 29H ILLEGAL IN CALL TO MPCHK ***)
      LUN = 6
      CALL MPERR
C NOW CHECK LEGALITY OF B, T AND M
   20 IF (B.GT.1) GO TO 40
      WRITE (LUN, 30) B
   30 FORMAT (8H *** B =, I10, 29H ILLEGAL IN CALL TO MPCHK ***)
      CALL MPERR
C T MAY EXCEED MT2-2 IN CALL FROM OTHER MP ROUTINES
   40 IF ((T.GT.1). AND. ((T.LE.(MT2-2)) .OR. (SPTR.GT.MNSPTR)))
     $   GO TO 60
      WRITE (LUN, 50) T
   50 FORMAT (8H *** T =, I10, 29H ILLEGAL IN CALL TO MPCHK ***)
      CALL MPERR
   60 IF (M.GT.(4*T)) GO TO 80
C HERE M IS NOT GREATER THAN 4*T.  SINCE MANY MP ROUTINES INCREASE
C T INTERNALLY, IT IS SAFEST TO SET M MUCH LARGER THAN 4*T
C INITIALLY.  NOTE, THOUGH, THAT 4*M MUST NOT OVERFLOW.
      WRITE (LUN, 70)
   70 FORMAT (36H *** M .LE. 4*T IN CALL TO MPCHK ***)
      CALL MPERR
C 8*B*B-1 SHOULD BE REPRESENTABLE, IF NOT WILL OVERFLOW
C AND MAY BECOME NEGATIVE, SO CHECK FOR THIS
   80 IB = 4*B*B - 1
      IF ((IB.GT.0) .AND. ((2*IB+1).GT.0)) GO TO 100
      WRITE (LUN, 90)
   90 FORMAT (37H *** B TOO LARGE IN CALL TO MPCHK ***)
      CALL MPERR
C CHECK THAT STACK SPACE IN COMMON IS SUFFICIENT.
C SPTR SHOULD POINT TO FIRST FREE WORD IN STACK,
C AND MXR TO LAST AVAILABLE WORD.
C AT LEAST 80 WORDS MUST BE AVAILABLE (SEE MPERRM).
  100 JSP = MAX0 (SPTR, MNSPTR + 80) - 1
      IF (MXR.GE.JSP) GO TO 120
C HERE STACK IS TOO SMALL.  CALL MPSTOV TO EXPAND IT IF POSSIBLE.
      CALL MPSTOV (JSP - MXR)
C SEE IF MPSTOV ACTUALLY DID EXPAND ENOUGH.
      IF (MXR.GE.JSP) GO TO 120
C HERE COMMON IS TOO SMALL (ASSUMING ITS SIZE IS MXR).
      WRITE (LUN, 110) MXR, JSP
  110 FORMAT (51H *** MXR TOO SMALL OR NOT SET TO DIM(R) BEFORE CALL,
     $ 21H TO AN MP ROUTINE *** /
     $ 10H *** MXR =, I6, 24H, BUT SHOULD BE AT LEAST, I6, 5H  ***)
      CALL MPERR
C CHECK LEGALITY OF VARIOUS OTHER PARAMETERS IN COMMON /MPCOM/
  120 IF ((MXSPTR.GE.MNSPTR) .AND. (MNSPTR.GT.0) .AND.
     $    (MNSPTR.LE.SPTR) .AND. ((MXSPTR-1).LE.MXR) .AND.
     $    (RNDRL.GE.0) .AND. (RNDRL.LE.3) .AND.
     $    (KTUNFL.GE.0) .AND. (MXUNFL.GE.0)) GO TO 140
      WRITE (LUN, 130)
  130 FORMAT (38H *** ONE OF SPTR, ... , MXUNFL ILLEGAL,
     $        21H IN CALL TO MPCHK ***)
      CALL MPERR
  140 IF ((DECPL .GT. 0) .AND. (MT2 .GT. 3) .AND. (MXINT .GE. 2047)
     $   .AND. (EXWID .GT. 2) .AND. (INRECL .GT. 0)
     $   .AND. (INRECL .LE. 80) .AND. (INBASE .GT. 1)
     $   .AND. (INBASE .LE. 16) .AND. (OUTBAS .GT. 1)
     $   .AND. (OUTBAS .LE. 16) .AND. (CHWORD .GT. 0)) GO TO 160
      WRITE (LUN, 150)
  150 FORMAT (39H *** ONE OF DECPL, ... , CHWORD ILLEGAL,
     $        21H IN CALL TO MPCHK ***)
      CALL MPERR
C UPDATE MXSPTR AND RETURN
  160 MXSPTR = MAX0 (MXSPTR, SPTR)
      RETURN
      END
C $$                   ******  MPCIM  ******
      SUBROUTINE MPCIM (IX, Z)
C CONVERTS INTEGER IX TO MULTIPLE-PRECISION Z.
C ASSUMES THAT ABS(IX) .LE. B**T (OTHERWISE IX CAN NOT USUALLY BE
C REPRESENTED EXACTLY AS A MULTIPLE-PRECISION NUMBER).
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, DUMMY(21), I, IX, MPGD, N, T, TWO, Z(1)
      TWO = 2
C CHECK LEGALITY OF PARAMETERS IN COMMON /MPCOM/
      CALL MPCHK
C T SHOULD BE INCREASED IF ABS(IX) .LT. B**T .
      N = IX
      IF (MPGD(N).GT.T) CALL MPERRM (
     $  29HT TOO SMALL IN CALL TO MPCIM$)
C SET Z(1) TO SIGN OF IX.
      Z(1) = 0
      IF (N.EQ.0) RETURN
      Z(1) = ISIGN (1, N)
C SET EXPONENT TO T
      Z(TWO) = T
C CLEAR FRACTION
      DO 10 I = 2, T
   10 Z(I+1) = 0
C INSERT N
      Z(T+2) = IABS(N)
C NORMALIZE BY CALLING MPMULI
      CALL MPMULI (Z, 1, Z)
      RETURN
      END
C $$                   ******  MPCIS  ******
      SUBROUTINE MPCIS (X, C, S, BOTH)
C IF BOTH = .TRUE., RETURNS C = COS(X) AND S = SIN(X).
C IF BOTH = .FALSE., RETURNS C = COS(X) ONLY (S UNCHANGED).
C X, C AND S ARE MP NUMBERS, BOTH IS LOGICAL.
C X MAY BE PACKED OR UNPACKED, C AND S ARE UNPACKED.
C THE ALGORITHM IS DESCRIBED IN - R. P. BRENT, UNRESTRICTED
C ALGORITHMS FOR ELEMENTARY AND SPECIAL FUNCTIONS, IN INFORMATION
C PROCESSING 80, NORTH HOLLAND, 1980.
C TIME = O(SQRT(T)M(T)).
C ROUNDING OPTIONS ARE IMPLEMENTED AS FOLLOWS -
C   RNDRL = 0 OR 1 - ABSOLUTE ERROR LESS THAN
C                    0.6*B**(-T)  (BUT THE RELATIVE ERROR
C                    MAY BE LARGE IF X IS CLOSE TO A NONZERO
C                    MULTIPLE OF PI/2),
C   RNDRL = 2      - LOWER BOUND ON TRUE RESULT,
C   RNDRL = 3      - UPPER BOUND ON TRUE RESULT.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I2, I3, I4, I5, J, K, MPT, Q, SV, TG, TM, TWO,
     $  B, C(1), DUMMY(21), MPGET, MPTLB, R(1), S(1), T, X(1)
      LOGICAL BOTH
      TWO = 2
      IF (X(1) .NE. 0) GO TO 10
C HERE X = 0
      CALL MPCIM (1, C)
      IF (BOTH) S(1) = 0
      RETURN
C HERE X .NE. 0
   10 CALL MPSAVN (SV)
C USE TRUNCATED ARITHMETIC INTERNALLY
      CALL MPSETR (0)
C SELECT OPTIMAL Q
      Q = 0
      MPT = MPTLB (1)
   20 Q = Q + 1
C THE CONSTANT 5 WAS DETERMINED EMPIRICALLY
      IF ((MPT*Q*Q) .LT. (5*T)) GO TO 20
C USE SUFFICIENT GUARD DIGITS
      T = T + MAX0 (0, X(TWO))
      CALL MPGD3 (MPTLB(Q), TG)
C ALLOCATE TEMPORARY STORAGE AND MOVE X
      CALL MPNEW (I2)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
C DIVIDE BY SUITABLE POWER OF TWO
      K = 0
   30 IF (R(I2+1) .LE. (-Q)) GO TO 40
      K = K + 1
      CALL MPDIVI (R(I2), 2, R(I2))
      GO TO 30
C ALLOCATE MORE STORAGE AND SET UP INNER LOOP
   40 CALL MPNEW (I3)
      IF (BOTH) CALL MPNEW (I4)
      CALL MPNEW (I5)
      IF (.NOT. BOTH) CALL MPMUL (R(I2), R(I2), R(I2))
      R(I3) = 0
      IF (BOTH) R(I4) = 0
      CALL MPCIM (1, R(I5))
      J = 0
C INNER LOOP STARTS HERE
   50 J = J + 2
C CAN REDUCE T TO TM FOR MULTIPLICATIONS
      TM = MIN0 (TG, MAX0 (2, R(I5+1) + TG))
      T = TM
      CALL MPMUL (R(I5), R(I2), R(I5))
      CALL MPDIVI (R(I5), J-1, R(I5))
      T = TG
      IF (BOTH) CALL MPADD (R(I4), R(I5), R(I4))
      T = TM
      IF (BOTH) CALL MPMUL (R(I5), R(I2), R(I5))
      CALL MPDIVI (R(I5), (-J), R(I5))
      T = TG
      CALL MPADD (R(I3), R(I5), R(I3))
C CHECK FOR UNDERFLOW
      IF (R(I5) .EQ. 0) GO TO 60
C CHECK FOR CONVERGENCE
      IF (R(I5+1) .GT. (-TG)) GO TO 50
C NOW USE DOUBLING IDENTITIES TO GET RESULT
   60 IF (K .LE. 0) GO TO 90
      DO 80 J = 1, K
      IF (.NOT.BOTH) GO TO 70
      CALL MPMUL (R(I3), R(I4), R(I2))
      CALL MPADD (R(I4), R(I2), R(I4))
      CALL MPMULI (R(I4), 2, R(I4))
   70 CALL MPADDI (R(I3), 2, R(I2))
      CALL MPMUL (R(I2), R(I3), R(I3))
   80 CALL MPMULI (R(I3), 2, R(I3))
C ADD 1 TO GET COS
   90 CALL MPADDI (R(I3), 1, R(I3))
C ROUND RESULT(S)
      IF (R(SV+2) .LE. 1) GO TO 100
C FIX UP FOR DIRECTED ROUNDINGS HERE
      CALL MPSETR (IABS(R(SV+2)))
      CALL MPCIM (2*R(SV+2)-5, R(I2))
      R(I2+1) = 1 - R(SV)
      CALL MPADD (R(I3), R(I2), R(I3))
      IF (BOTH) CALL MPADD (R(I4), R(I2), R(I4))
  100 CALL MPRND (R(I3), TG, C, IABS(R(SV)), 0)
      T = R(SV)
      IF (C(1) .EQ. 0) GO TO 110
      IF (C(TWO) .GT. 0) CALL MPCIM (MPGET (R, I3), C)
  110 IF (.NOT. BOTH) GO TO 120
      CALL MPRND (R(I4), TG, S, IABS(R(SV)), 0)
      IF (S(1) .EQ. 0) GO TO 120
      IF (S(TWO) .GT. 0) CALL MPCIM (MPGET (R, I4), S)
C RESTORE T ETC AND RETURN
  120 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCMD  ******
      SUBROUTINE MPCMD (X, DZ)
C CONVERTS MULTIPLE-PRECISION X TO DOUBLE-PRECISION DZ.
C ASSUMES X IN ALLOWABLE RANGE.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, DUMMY(21), I, IE, T, TM, TWO, X(1)
      DOUBLE PRECISION DB, DBLE, DZ, DZ2
      REAL FLOAT
      TWO = 2
C CHECK LEGALITY OF PARAMETERS IN COMMON /MPCOM/
      CALL MPCHK
      DZ = 0D0
C RETURN WITH DZ = 0.0 IF X IS ZERO.
      IF (X(1).EQ.0) RETURN
      DB = DBLE(FLOAT(B))
C LOOP TO COMPUTE DZ.
      DO 10 I = 1, T
      DZ = DB*DZ + DBLE(FLOAT(X(I+2)))
      TM = I
C CHECK IF FULL DOUBLE-PRECISION ACCURACY ATTAINED
      DZ2 = DZ + 1D0
C ON SOME MACHINES (DZ2 .LE. DZ) FAILS
      IF ((DZ2 - DZ) .LE. 0.0D0) GO TO 20
   10 CONTINUE
C NOW ALLOW FOR EXPONENT
   20 IE = X(TWO) - TM
   30 IF (IE. LE. 0) GO TO 40
      IE = IE - 1
      DZ = DZ*DB
      GO TO 30
   40 IF (IE .EQ. 0) GO TO 50
      IE = IE + 1
      DZ = DZ/DB
      GO TO 40
C CHECK REASONABLENESS OF RESULT
C FOLLOWING MESSAGE INDICATES THAT X IS TOO LARGE OR SMALL -
C TRY USING MPCMDE INSTEAD.
   50 IF (DZ.LE.0D0) CALL MPERRM (
     $  39HFLOATING-POINT OVER/UNDERFLOW IN MPCMD$)
C ALLOW FOR SIGN OF X AND RETURN.
      IF (X(1).LT.0) DZ = -DZ
      RETURN
      END
C $$                   ******  MPCMDE  ******
      SUBROUTINE MPCMDE (X, N, DX)
C RETURNS INTEGER N AND DOUBLE-PRECISION DX SUCH THAT MP
C X = DX*OUTBAS**N (APPROXIMATELY), WHERE 1 .LE. ABS(DX) .LT. OUTBAS
C UNLESS DX = 0. (OUTBAS IS IN COMMON /MPCOM/ - DEFAULT VALUE
C IS 10.)
C ROUNDING OPTIONS NOT IMPLEMENTED.
      COMMON R
      INTEGER I2, MPPARN, N, R(1), SV, X(1)
      DOUBLE PRECISION DABS, DBLE, DX
      REAL FLOAT
      CALL MPSAVN (SV)
      IF (X(1).NE.0) GO TO 10
      N = 0
      DX = 0.0D0
      GO TO 20
C USE TRUNCATED ARITHMETIC.
   10 CALL MPSETR (0)
      CALL MPNEW (I2)
      CALL MPCMEF (X, N, R(I2))
      CALL MPCMD (R(I2), DX)
      IF (DABS(DX) .LT. DBLE(FLOAT(MPPARN(20)))) GO TO 20
C HERE DX WAS ROUNDED UP TO OUTBAS
      N = N + 1
      DX = DBLE(FLOAT(R(I2)))
   20 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCMEF  ******
      SUBROUTINE MPCMEF (X, N, Y)
C
C GIVEN MP X, RETURNS INTEGER N AND MP Y SUCH THAT
C X = (OUTBAS**N)*Y  AND  1 .LE. ABS(Y) .LT. OUTBAS
C (UNLESS X .EQ. 0, WHEN N .EQ. 0 AND Y .EQ. 0).
C OUTBAS IS A PARAMETER IN COMMON /MPCOM/, DEFAULT VALUE 10.
C IT IS ASSUMED THAT X IS NOT SO LARGE OR SMALL THAT N OVERFLOWS.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C
C ROUNDING OPTIONS NOT YET FULLY IMPLEMENTED, BUT THE DIRECTED
C ROUNDING OPTIONS (RNDRL = 2 AND 3) GIVE CORRECT RESULTS.
C
      COMMON R
      COMMON /MPCOM/ B, T, M, DUMMY
      INTEGER IY, I2, J, N1, OUTBAS, SV, TWO
      INTEGER B, DUMMY(20), M, N, R(1), T, X(1), Y(1)
      INTEGER MPCHGB, MPCMPI, MPPARN
      TWO = 2
C SAVE T ETC.
      CALL MPSAVN (SV)
      OUTBAS = MPPARN (20)
      IF ((OUTBAS .LT. 2) .OR. (OUTBAS .GT. 16)) CALL MPERRM (
     $  33HILLEGAL OUTBAS ON CALL TO MPCMEF$)
C CHECK FOR X ZERO
      IF (X(1).NE.0) GO TO 10
      N = 0
      Y(1) = 0
      GO TO 110
C X NONZERO HERE.
   10 CALL MPUNPK (X, Y)
      N = 0
      CALL MPNEW (I2)
C LOOP UP TO 100 TIMES (USUALLY ONE IS SUFFICIENT)
      DO 20 J = 1, 100
C ESTIMATE LOG (ABS(Y)) TO BASE OUTBAS
      N1 = MPCHGB (OUTBAS, IABS(B), Y(TWO)-1) +
     $     MPCHGB (OUTBAS, Y(TWO+1), 1)
C FOLLOWING AVOIDS POSSIBILITY OF R(I2) OVERFLOWING BELOW
      IF ((J.EQ.1).AND.(IABS(N1).GT.(M/4))) N1 = N1/2
C LEAVE J LOOP IF N1 SMALL
      IF (IABS(N1).LE.3) GO TO 50
C DIVIDE BY OUTBAS**N1, TAKING CARE FOR DIRECTED ROUNDINGS.
      CALL MPSCAL (Y, OUTBAS, (-N1))
      IF (Y(1) .EQ. 0) GO TO 30
   20 N = N + N1
C ERROR IF FALL THROUGH LOOP
   30 CALL MPERRM (
     $  42HERROR IN MPCMEF, MAYBE EXPONENT TOO LARGE$)
   50 IF (Y(1).EQ.0) GO TO 30
C LOOP DIVIDING BY OUTBAS UNTIL ABS(Y) .LT. 1
   60 IF (Y(TWO).LE.0) GO TO 80
      N = N + 1
      CALL MPDIVI (Y, OUTBAS, Y)
      GO TO 60
C LOOP MULTIPLYING BY OUTBAS UNTIL ABS(Y) .GE. 1
   70 IF (Y(TWO).GT.0) GO TO 90
   80 N = N - 1
      CALL MPMULI (Y, OUTBAS, Y)
      GO TO 70
C CHECK FOR POSSIBILITY THAT ROUNDING UP WAS TO OUTBAS
   90 IY = Y(1)
      Y(1) = 1
      IF (MPCMPI (Y, OUTBAS) .LT. 0) GO TO 100
C IT WAS, SO SET Y TO 1 AND ADD ONE TO EXPONENT
      CALL MPCIM (1, Y)
      N = N + 1
C FIX UP SIGN OF Y.
  100 Y(1) = IY
C RESTORE STACK POINTER ETC. AND RETURN.
  110 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCMF  ******
      SUBROUTINE MPCMF (X, Y)
C FOR MP X AND Y, RETURNS FRACTIONAL PART OF X IN Y,
C I.E., Y = X - INTEGER PART OF X (TRUNCATED TOWARDS 0).
C NOTE THAT RNDRL IN COMMON /MPCOM/ IS IRRELEVANT.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, DUMMY(21), I, T, TWO, X(1), Y(1), Y1, Y2
      TWO = 2
C MOVE X TO Y
      CALL MPSTR (X, Y)
C CHECK IF Y ZERO, WHEN RETURN WITH RESULT ZERO.
      Y1 = Y(1)
      IF (Y1.EQ.0) RETURN
C CAN ALSO RETURN IF EXPONENT NOT POSITIVE, THEN RESULT X.
      Y2 = Y(TWO)
      IF (Y2.LE.0) RETURN
C CHECK FOR ZERO FRACTIONAL PART
      IF (Y2.LT.T) GO TO 10
C HERE THE FRACTIONAL PART OF X IS ZERO.
      Y(1) = 0
      RETURN
C HERE 0 .LT. Y2 .LT. T.  CLEAR INTEGER PART.
   10 DO 20 I = 1, Y2
   20 Y(I+2) = 0
C NORMALIZE RESULT AND RETURN.
      CALL MPNZR (Y1, Y2, Y(1), Y(TWO+1), 0)
      RETURN
      END
C $$                   ******  MPCMI  ******
      SUBROUTINE MPCMI (X, IZ)
C CONVERTS MULTIPLE-PRECISION X TO INTEGER IZ,
C ASSUMING THAT X NOT TOO LARGE (ELSE USE MPCMIM).
C X IS TRUNCATED TOWARDS ZERO, REGARDLESS OF THE VALUE OF RNDRL.
C IZ IS RETURNED AS ZERO IF ABS(INT(X)) .GT. MXINT .
C THE USER MAY CHECK FOR THIS BY TESTING IF
C     ((X(1).NE.0).AND.(X(2).GT.0).AND.(IZ.EQ.0))
C IS TRUE ON RETURN FROM MPCMI.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, IB, MXINT, XS, X2,
     $  B, DUMMY(21), IZ, MPGET, MPPARN, T, X(1)
      XS = X(1)
      IZ = 0
C RETURN ZERO IF X ZERO OR EXPONENT(X) .LE. 0.
      IF (XS.EQ.0) RETURN
      X2 = MPGET (X, 2)
      IF (X2.LE.0) RETURN
      MXINT = MPPARN (16)
      IB = MXINT/B
C LOOP TO CONVERT INTEGER PART OF X TO SINGLE-PRECISION INTEGER.
      DO 10 I = 1, X2
C CHECK IF B*IZ WOULD EXCEED MXINT
      IF (IZ .GT. IB) GO TO 20
      IZ = B*IZ
      IF (I .GT. T) GO TO 10
C CHECK IF X(I+2) + IZ WOULD EXCEED MXINT
      IF (X(I+2) .GT. (MXINT - IZ)) GO TO 20
      IZ = IZ + X(I+2)
   10 CONTINUE
C RESTORE SIGN AND RETURN
      IZ = XS*IZ
      RETURN
C HERE ABS(INT(X)) IS LARGER THAN MXINT, SO RETURN ZERO.
   20 IZ = 0
      RETURN
      END
C $$                   ******  MPCMIM  ******
      SUBROUTINE MPCMIM (X, Y)
C RETURNS Y = INTEGER PART OF X (TRUNCATED TOWARDS 0), FOR MP X AND Y.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C USE IF Y TOO LARGE TO BE REPRESENTABLE AS A SINGLE-PRECISION INTEGER
C (ELSE COULD USE MPCMI).  RNDRL IS IRRELEVANT.
      INTEGER I, IL, MPGET, MPPARN, T, X(1), Y(1)
C CHECK LEGALITY OF B, T ETC.
      CALL MPCHK
      CALL MPUNPK (X, Y)
      IF (Y(1).EQ.0) RETURN
      IL = MPGET (Y, 2) + 1
      T = MPPARN(2)
C IF EXPONENT LARGE ENOUGH RETURN Y = X
      IF (IL.GT.T) RETURN
C IF EXPONENT SMALL ENOUGH RETURN ZERO
      IF (IL.GT.1) GO TO 10
      Y(1) = 0
      RETURN
C SET FRACTION TO ZERO
   10 DO 20 I = IL, T
   20 Y(I+2) = 0
      RETURN
      END
C $$                   ******  MPCMP  ******
      INTEGER FUNCTION MPCMP (X, Y)
C COMPARES THE UNPACKED MULTIPLE-PRECISION NUMBERS X AND Y,
C RETURNING +1 IF X .GT. Y,
C           -1 IF X .LT. Y,
C AND        0 IF X .EQ. Y.
      INTEGER X(1), Y(1), T2, I, MPPARN
C COMPARE SIGNS OF X AND Y.
      IF (X(1) - Y(1)) 10, 30, 20
C X .LT. Y
   10 MPCMP = -1
      RETURN
C X .GT. Y
   20 MPCMP = 1
      RETURN
C SIGN(X) = SIGN(Y), SEE IF ZERO
   30 IF (X(1).EQ.0) GO TO 55
C HAVE TO COMPARE EXPONENTS AND FRACTIONS
      T2 = MPPARN(2) + 2
      DO 50 I = 2, T2
      IF (X(I) - Y(I)) 60, 50, 70
   50 CONTINUE
C NUMBERS EQUAL
   55 MPCMP = 0
      RETURN
C ABS(X) .LT. ABS(Y)  AND SIGNS EQUAL.
   60 MPCMP = -X(1)
      RETURN
C ABS(X) .GT. ABS(Y)  AND SIGNS EQUAL.
   70 MPCMP = X(1)
      RETURN
      END
C $$                   ******  MPCMPA  ******
      INTEGER FUNCTION MPCMPA (X, Y)
C COMPARES ABS(X) WITH ABS(Y) FOR MP X AND Y,
C RETURNING +1 IF ABS(X) .GT. ABS(Y),
C           -1 IF ABS(X) .LT. ABS(Y),
C AND        0 IF ABS(X) .EQ. ABS(Y)
C X AND/OR Y MAY BE PACKED OR UNPACKED.
      INTEGER MPCOMP, X(1), Y(1), XS, YS
      XS = X(1)
      YS = Y(1)
      X(1) = IABS(XS)
      Y(1) = IABS(YS)
      MPCMPA = MPCOMP (X, Y)
      X(1) = XS
      Y(1) = YS
      RETURN
      END
C $$                   ******  MPCMPD  ******
      INTEGER FUNCTION MPCMPD (X, DI)
C COMPARES MP NUMBER X WITH DOUBLE-PRECISION NUMBER DI, RETURNING
C     +1 IF X .GT. DI,
C      0 IF X .EQ. DI,
C     -1 IF X .LT. DI.
C X MAY BE PACKED OR UNPACKED.
C COMMENTS REGARDING ROUNDING ERROR IN SUBROUTINE MPCDM
C ARE RELEVANT.
C X MAY BE PACKED OR UNPACKED.
      COMMON R
      INTEGER I2, MPCOMP, R(1), SV, X(1)
      DOUBLE PRECISION DI
      CALL MPSAVN (SV)
C ALLOCATE TEMPORARY SPACE
      CALL MPNEW (I2)
C CONVERT DI TO MULTIPLE-PRECISION AND COMPARE
      CALL MPCDM (DI, R(I2))
      MPCMPD = MPCOMP (X, R(I2))
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCMPI  ******
      INTEGER FUNCTION MPCMPI (X, I)
C COMPARES MP NUMBER X WITH INTEGER I, RETURNING
C     +1 IF X .GT. I,
C      0 IF X .EQ. I,
C     -1 IF X .LT. I
C X MAY BE PACKED OR UNPACKED.
      COMMON R
      INTEGER I, I2, MPCOMP, R(1), SV, X(1)
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
C CONVERT I TO MULTIPLE-PRECISION AND COMPARE
      CALL MPCIM (I, R(I2))
      MPCMPI = MPCOMP (X, R(I2))
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCMPQ  ******
      INTEGER FUNCTION MPCMPQ (X, I, J)
C RETURNS +1 IF X .GT. I/J,
C          0 IF X .EQ. I/J,
C         -1 IF X .LT. I/J,
C FOR (PACKED OR UNPACKED) MP X AND INTEGER I, J (J NONZERO).
C RESULT IS EXACT, SO RNDRL IS IRRELEVANT.
      COMMON R
      COMMON /MPCOM/ B, T, M, DUMMY
      INTEGER I2, K, L, SV, TG
      INTEGER B, DUMMY(20), I, J, M, R(1), T, X(1)
      INTEGER MPCMPI, MPGD
      CALL MPSAVN (SV)
      K = I
      L = J
C CHECK FOR ZERO DENOMINATOR.
      IF (L) 20, 10, 30
   10 CALL MPERRM (24HJ = 0 IN CALL TO MPCMPQ$)
C HERE J WAS NEGATIVE.
   20 L = -L
      K = -K
C NOW I/J = K/L AND L POSITIVE
   30 CALL MPGCD (K, L)
C CHECK FOR L = 1
      IF (L.NE.1) GO TO 40
C HERE L = 1 SO CAN USE MPCMPI.
      MPCMPQ = MPCMPI (X, K)
      GO TO 50
C HERE L .GT. 1, SO INCREASE T SO L*X CAN BE FORMED EXACTLY.
   40 T = T + MPGD (L)
      TG = T
C INCREASE M SO OVERFLOW CAN NOT OCCUR
      M = M + T
C USE TRUNCATED ARITHMETIC (ACTUALLY EXACT).
      CALL MPSETR (0)
C MOVE X TO TEMPORARY STORAGE AND MULTIPLY BY L
      CALL MPNEW (I2)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPMULI (R(I2), L, R(I2))
C NOW COMPARE L*X WITH K USING MPMULI
      MPCMPQ = MPCMPI (R(I2), K)
C RESTORE EVERYTHING AND RETURN.
   50 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCMPR  ******
      INTEGER FUNCTION MPCMPR (X, RI)
C COMPARES MP NUMBER X WITH REAL NUMBER RI, RETURNING
C     +1 IF X .GT. RI,
C      0 IF X .EQ. RI,
C     -1 IF X .LT. RI.
C X MAY BE PACKED OR UNPACKED.
C COMMENTS REGARDING ROUNDING ERROR IN SUBROUTINE MPCRM
C ARE RELEVANT.
      COMMON R
      INTEGER I2, MPCOMP, R(1), SV, X(1)
      REAL RI
      CALL MPSAVN (SV)
C ALLOCATE TEMPORARY SPACE
      CALL MPNEW (I2)
C CONVERT RI TO MULTIPLE-PRECISION AND COMPARE
      CALL MPCRM (RI, R(I2))
      MPCMPR = MPCOMP (X, R(I2))
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCMR  ******
      SUBROUTINE MPCMR (X, RZ)
C CONVERTS MULTIPLE-PRECISION X TO SINGLE-PRECISION RZ.
C ASSUMES X IN ALLOWABLE RANGE.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, DUMMY(21), I, IE, T, TM, TWO, X(1)
      REAL FLOAT, RB, RZ, RZ2
      TWO = 2
C CHECK LEGALITY OF PARAMETERS IN COMMON /MPCOM/
      CALL MPCHK
      RZ = 0E0
C RETURN WITH RZ = 0.0 IF X IS ZERO.
      IF (X(1).EQ.0) RETURN
      RB = FLOAT(B)
C LOOP TO COMPUTE RZ.
      DO 10 I = 1, T
      RZ = RB*RZ + FLOAT(X(I+2))
      TM = I
C CHECK IF FULL SINGLE-PRECISION ACCURACY ATTAINED
      RZ2 = RZ + 1E0
      IF (RZ2.LE.RZ) GO TO 20
   10 CONTINUE
C NOW ALLOW FOR EXPONENT
   20 IE = X(TWO) - TM
   30 IF (IE. LE. 0) GO TO 40
      IE = IE - 1
      RZ = RZ*RB
      GO TO 30
   40 IF (IE .EQ. 0) GO TO 50
      IE = IE + 1
      RZ = RZ/RB
      GO TO 40
C CHECK REASONABLENESS OF RESULT
C FOLLOWING MESSAGE INDICATES THAT X IS TOO LARGE OR SMALL -
C TRY USING MPCMRE INSTEAD.
   50 IF (RZ.LE.0E0) CALL MPERRM (
     $  39HFLOATING-POINT OVER/UNDERFLOW IN MPCMR$)
C ALLOW FOR SIGN OF X AND RETURN.
      IF (X(1).LT.0) RZ = -RZ
      RETURN
      END
C $$                   ******  MPCMRE  ******
      SUBROUTINE MPCMRE (X, N, RX)
C RETURNS INTEGER N AND SINGLE-PRECISION RX SUCH THAT MP
C X = RX*OUTBAS**N (APPROXIMATELY), WHERE 1 .LE. ABS(RX) .LT. OUTBAS
C UNLESS RX = 0. (OUTBAS IS IN COMMON /MPCOM/ - DEFAULT VALUE
C IS 10.)
C ROUNDING OPTIONS NOT IMPLEMENTED.
      COMMON R
      INTEGER I2, MPPARN, N, R(1), SV, X(1)
      REAL FLOAT, RX
      CALL MPSAVN (SV)
      IF (X(1).NE.0) GO TO 10
      N = 0
      RX = 0E0
      GO TO 20
C USE TRUNCATED ARITHMETIC.
   10 CALL MPSETR (0)
      CALL MPNEW (I2)
      CALL MPCMEF (X, N, R(I2))
      CALL MPCMR (R(I2), RX)
      IF (ABS(RX) .LT. FLOAT(MPPARN(20))) GO TO 20
C HERE RX WAS ROUNDED UP TO OUTBAS
      N = N + 1
      RX = FLOAT(R(I2))
   20 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCMUL  ******
      SUBROUTINE MPCMUL (XR, XI, YR, YI, ZR, ZI)
C SETS Z = X*Y WHERE X = XR + I*XI, ETC. ARE COMPLEX
C MULTIPLE-PRECISION NUMBERS.
C USES TRUNCATED ARITHMETIC, NO GUARD DIGITS.
C ROUNDING OPTIONS NOT IMPLEMENTED.
      COMMON R
      INTEGER I2, I3, I4, SV
      INTEGER R(1), XI(1), XR(1), YI(1), YR(1), ZI(1), ZR(1)
      CALL MPSAVN (SV)
      CALL MPSETR (0)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPMUL (XR, YR, R(I2))
      CALL MPMUL (XI, YI, R(I3))
      CALL MPMUL (XR, YI, R(I4))
      CALL MPMUL (XI, YR, ZI)
      CALL MPADD (R(I4), ZI, ZI)
      CALL MPSUB (R(I2), R(I3), ZR)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCOMP  ******
      INTEGER FUNCTION MPCOMP (X, Y)
C COMPARES THE MULTIPLE-PRECISION NUMBERS X AND Y,
C RETURNING +1 IF X .GT. Y,
C           -1 IF X .LT. Y,
C AND        0 IF X .EQ. Y.
C X AND Y MAY BE PACKED OR UNPACKED.
      COMMON R
      INTEGER R(1), X(1), Y(1), SV, MPCMP, I2, I3
C FOR EFFICIENCY TREAT UNPACKED NUMBERS SEPARATELY
      IF (MAX0 (IABS(X(1)), IABS(Y(1))) .GT. 1) GO TO 10
      MPCOMP = MPCMP (X, Y)
      RETURN
C HERE X AND/OR Y IS PACKED
   10 CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPUNPK (X, R(I2))
      CALL MPUNPK (Y, R(I3))
      MPCOMP = MPCMP (R(I2), R(I3))
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPCOS  ******
      SUBROUTINE MPCOS (X, Y)
C RETURNS Y = COS(X) FOR MP X AND Y, USING MPCIS.
C TIME = O(SQRT(T)M(T)).
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C ROUNDING OPTIONS ARE IMPLEMENTED AS FOR MPCIS.
      INTEGER X(1), Y(1), S(1)
      CALL MPCIS (X, Y, S, .FALSE.)
      RETURN
      END
C $$                   ******  MPCOSH  ******
      SUBROUTINE MPCOSH (X, Y)
C RETURNS Y = COSH(X) FOR MP NUMBERS X AND Y, X NOT TOO LARGE.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C ROUNDING OPTIONS NOT YET IMPLEMENTED, NO GUARD DIGITS USED.
      COMMON R
      INTEGER I2, R(1), SV, X(1), Y(1)
C CHECK FOR X ZERO
      IF (X(1).NE.0) GO TO 10
C COSH(0) = 1
      CALL MPCIM (1, Y)
      RETURN
C SAVE T ETC.
   10 CALL MPSAVN (SV)
C ALLOCATE TEMPORARY STORAGE.
      CALL MPNEW (I2)
C USE TRUNCATED ARITHMETIC, MOVE ABS(X).
      CALL MPSETR (0)
      CALL MPABS (X, R(I2))
C IF ABS(X) TOO LARGE MPEXP WILL PRINT ERROR MESSAGE
C INCREASE M TO AVOID OVERFLOW WHEN COSH(X) REPRESENTABLE
      CALL MPPARC (3, R(SV+1)+2)
      CALL MPEXP (R(I2), R(I2))
      CALL MPREC (R(I2), Y)
      CALL MPADD (R(I2), Y, Y)
C RESTORE M ETC.  IF RESULT OVERFLOWS OR UNDERFLOWS, MPDIVI WILL
C ACT ACCORDINGLY.
      CALL MPRESN (SV)
      CALL MPDIVI (Y, 2, Y)
      RETURN
      END
C $$                   ******  MPCQM  ******
      SUBROUTINE MPCQM (I, J, Q)
C CONVERTS THE RATIONAL NUMBER I/J TO MULTIPLE PRECISION Q.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C SEE SUBROUTINE MPNZR.
      INTEGER I, I1, J, J1, Q(1)
      I1 = I
      J1 = J
C REMOVE ANY COMMON FACTOR OF I AND J.
      CALL MPGCD (I1, J1)
C CHECK SIGN OF DENOMINATOR.
      IF (J1) 20, 10, 30
C DIVISION BY ZERO
   10 CALL MPERRM (23HJ = 0 IN CALL TO MPCQM$)
      RETURN
C MAKE DENOMINATOR POSITIVE TO GIVE CORRECT DIRECTED ROUNDING.
   20 I1 = -I1
      J1 = -J1
   30 CALL MPCIM (I1, Q)
      IF (J1.NE.1) CALL MPDIVI (Q, J1, Q)
      RETURN
      END
C $$                   ******  MPCRM  ******
      SUBROUTINE MPCRM (RX, Z)
C CONVERTS SINGLE-PRECISION NUMBER RX TO MULTIPLE-PRECISION Z.
C SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
C WITH BASE OTHER THAN TWO OR IF B IS NOT A POWER OF TWO WITH
C B**(T-1) SUFFICIENTLY LARGE.  THUS MPCRM SHOULD BE USED ONLY TO
C OBTAIN STARTING APPROXIMATIONS ETC.  FOR ACCURATE INITIALIZATION
C OF MP NUMBERS USE MPCIM, MPCQM, MPQPWR, OR MPIN.
C WARNING - THE PARAMETER RNDRL IN COMMON /MPCOM/ HAS NO EFFECT.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, DUMMY(21), I, IE, ISV, J, RE, RS, SV, T,
     $  THREE, Z(1)
      REAL FLOAT, RB, RJ, RX
      CALL MPSAVN (SV)
      CALL MPSETR (0)
      THREE = 3
C CHECK SIGN
      IF (RX) 20, 10, 30
C IF RX = 0E0 RETURN 0
   10 Z(1) = 0
      GO TO 100
C RX .LT. 0E0
   20 RS = -1
      RJ = -RX
      GO TO 40
C RX .GT. 0E0
   30 RS = 1
      RJ = RX
C WE WANT TO REDUCE RJ TO RANGE 1/16 .LE. RJ .LT. 1.
   40 IE = 0
   50 IF (RJ.LT.1E0) GO TO 60
C INCREASE IE AND DIVIDE RJ BY 16.
      IE = IE + 1
      RJ = 0.0625E0*RJ
      GO TO 50
   60 IF (RJ.GE.0.0625E0) GO TO 70
      IE = IE - 1
      RJ = 16E0*RJ
      GO TO 60
C NOW RJ IS DY DIVIDED BY SUITABLE POWER OF 16.
C SET EXPONENT TO 0
   70 RE = 0
      RB = FLOAT(B)
C CONVERSION LOOP (ASSUME SINGLE-PRECISION OPS. EXACT)
      DO 80 I = 1, T
      RJ = RB*RJ
      ISV = I
      J = INT(RJ)
C CHECK FOR (UNLIKELY) EFFECT OF STRANGE FLOATING-POINT ARITHMETIC.
      IF (J.GE.B) GO TO 110
      IF (RJ.LT.0.0) GO TO 120
      Z(I+2) = J
   80 RJ = RJ - FLOAT(J)
C NORMALIZE RESULT
   90 CALL MPNZR (RS, RE, Z(1), Z(THREE), 0)
C NOW MULTIPLY BY 16**IE
      CALL MPSCAL (Z, 16, IE)
C CAN RETURN NOW
  100 CALL MPRESN (SV)
      RETURN
C HERE A DIGIT IS .GE. B, WHICH SHOULD NEVER HAPPEN
  110 J = B-1
      GO TO 130
C HERE A DIGIT IS NEGATIVE, WHICH SHOULD NEVER HAPPEN
  120 J = 0
C SET REMAINING DIGITS TO J (EITHER B-1 OR 0)
  130 DO 140 I = ISV, T
  140 Z(I+2) = J
      GO TO 90
      END
C $$                   ******  MPDAW  ******
      SUBROUTINE MPDAW (X, Y)
C RETURNS Y = DAWSONS INTEGRAL (X)
C           = EXP(-X**2)*(INTEGRAL FROM 0 TO X OF EXP(U**2)DU),
C FOR PACKED/UNPACKED MULTIPLE-PRECISION X, UNPACKED MP Y.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, DUMMY
      LOGICAL ERR
      INTEGER I, I2, I3, I4, SV, TG, XS
      INTEGER B, DUMMY(20), M, MPTLB, R(1), T, X(1), Y(1)
C SAVE T ETC. AND CHECK FOR X ZERO.
      CALL MPSAVN (SV)
      XS = X(1)
      IF (XS.NE.0) GO TO 10
C DAW(0) = 0
      Y(1) = 0
      GO TO 50
C INCREASE T AND ALLOCATE TEMPORARY STORAGE.
   10 CALL MPGD3 (MPTLB (IABS(T)), TG)
      CALL MPNEW (I2)
C USE TRUNCATED ARITHMETIC, INCREASE M TO AVOID UNDERFLOW.
      CALL MPSETR (0)
      M = M + T
C MOVE ABS(X) TO TEMPORARY STORAGE.
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      R(I2) = IABS(R(I2))
C TRY ASYMPTOTIC SERIES
      CALL MPERF3 (R(I2), R(I2), .TRUE., ERR)
      IF (ERR) GO TO 20
C HERE ASYMPTOTIC SERIES WAS SUCCESSFUL.  FIX UP SIGN.
      R(I2) = XS*R(I2)
      GO TO 40
C ASYMPTOTIC SERIES. NOT ACCURATE ENOUGH SO USE POWER SERIES
   20 CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPMOVE (X, IABS(R(SV)), R(I4), TG)
      T = TG
      CALL MPMUL (R(I4), R(I4), R(I4))
      CALL MPNEG (R(I4), R(I4))
      CALL MPEXP (R(I4), R(I4))
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPMUL (R(I2), R(I4), R(I3))
      CALL MPMUL (R(I2), R(I2), R(I4))
      CALL MPSTR (R(I3), R(I2))
      I = 0
C POWER SERIES LOOP, REDUCE T IF POSSIBLE
   30 T = TG + 2 + R(I3+1) - R(I2+1)
      IF (T.LE.2) GO TO 40
      T = MIN0 (T, TG)
      I = I + 1
      CALL MPMUL (R(I4), R(I3), R(I3))
      CALL MPMULS (R(I3), 2*I-1, 1, I, 2*I+1)
C RESTORE T FOR ADDITION
      T = TG
      CALL MPADD (R(I2), R(I3), R(I2))
      IF (R(I3).NE.0) GO TO 30
C ROUND RESULT
   40 CALL MPRES2 (SV)
      CALL MPRND (R(I2), TG, Y, IABS(R(SV)), 1)
C RESTORE EVERYTHING AND RETURN.
   50 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPDGA  ******
      INTEGER FUNCTION MPDGA (X, N)
C RETURNS THE N-TH DIGIT OF THE MP NUMBER X FOR 1 .LE. N .LE. T.
C RETURNS ZERO IF X IS ZERO OR N .LE. 0 OR N .GT. T.
      INTEGER MPPARN, N, X(1)
      MPDGA = 0
      IF ((X(1).NE.0).AND.(N.GT.0).AND.(N.LE.MPPARN(2))) MPDGA = X(N+2)
      RETURN
      END
C $$                   ******  MPDGB  ******
      SUBROUTINE MPDGB (I, X, N)
C SETS THE N-TH DIGIT OF THE MP NUMBER X TO I.
C N MUST BE IN THE RANGE 1 .LE. N .LE T,
C I MUST BE IN THE RANGE 0 .LE. I .LT. B
C (AND I .NE. 0 IF N .EQ. 1).
C THE SIGN AND EXPONENT OF X ARE UNCHANGED.
      INTEGER I, MPPARN, N, X(1)
      IF ((N.LE.0).OR.(N.GT.MPPARN(2))) CALL MPERRM (
     $  40HDIGIT POSITION ILLEGAL IN CALL TO MPDGB$)
      IF ((I.LT.0).OR.(I.GE.MPPARN(1)).OR.((I+N).LE.1)) CALL
     $  MPERRM (37HDIGIT VALUE ILLEGAL IN CALL TO MPDGB$)
      X(N+2) = I
      RETURN
      END
C $$                   ******  MPDIGA  ******
      INTEGER FUNCTION MPDIGA (X)
C RETURNS THE NUMBER OF MP DIGITS (SECOND WORD IN COMMON /MPCOM/).
C X IS A DUMMY MP ARGUMENT.
      INTEGER MPPARN, X(1)
      MPDIGA = MPPARN (2)
      RETURN
      END
C $$                   ******  MPDIGB  ******
      SUBROUTINE MPDIGB (I, X)
C SETS THE NUMBER OF MP DIGITS (SECOND WORD OF COMMON /MPCOM/) TO I.
C I SHOULD BE AN INTEGER SUCH THAT I .GE. 2
C AND I+2 .LE. MT2 (WHERE MT2 IS IN COMMON /MPCOM/).
C X IS A DUMMY MP ARGUMENT (AUGMENT EXPECTS ONE).
      INTEGER I, X(1)
      CALL MPPARC (2, I)
      CALL MPCHK
      RETURN
      END
C $$                   ******  MPDIGS  ******
      INTEGER FUNCTION MPDIGS (N)
C RETURNS THE NUMBER OF MP DIGITS (TO BASE B) REQUIRED FOR THE
C EQUIVALENT OF AT LEAST N FLOATING (BASE OUTBAS) PLACES,
C B**(MPDIGS-1) .GE. OUTBAS**(N-1) .
C IF OUTBAS HAS ITS DEFAULT VALUE OF 10, RESULT IS THE NUMBER
C OF BASE B DIGITS TO GIVE THE EQUIVALENT OF AT LEAST N FLOATING
C DECIMAL PLACES.
      INTEGER MPCHGB, MPPARN, N
      MPDIGS = MAX0 (2, MPCHGB (MPPARN(1), MPPARN(20), N-1) + 1)
      RETURN
      END
C $$                   ******  MPDIGV  ******
      INTEGER FUNCTION MPDIGV (X)
C RETURNS 0, ... , 9, 10, ... , 15 IF X IS THE CHARACTER
C         0, ... , 9,  A, ... , F,
C AND THE VALUE RETURNED IS LESS THAN INBASE (DEFAULT VALUE TEN),
C RETURNS -1 OTHERWISE.
      INTEGER I, INBASE, J, MPDIGW, MPPARN, X
      LOGICAL MPIS
      INBASE = MPPARN (19)
      IF ((INBASE .LT. 2) .OR. (INBASE .GT. 16)) CALL MPCHK
      DO 10 I = 1, INBASE
      J = I - 1
      IF (MPIS (X, MPDIGW(J))) GO TO 20
   10 CONTINUE
      MPDIGV = -1
      RETURN
C HERE DIGIT FOUND
   20 MPDIGV = J
      RETURN
      END
C $$                   ******  MPDIGW  ******
      INTEGER FUNCTION MPDIGW (N)
C RETURNS CHARACTER 0, ... , 9, A, ... , F IF N IS
C                   0, ... , 9, 10, ... , 15 RESPECTIVELY,
C RETURNS CHARACTER * OTHERWISE.
      INTEGER D(17), I, N
      DATA D(1), D(2), D(3), D(4) /1H0, 1H1, 1H2, 1H3/
      DATA D(5), D(6), D(7), D(8) /1H4, 1H5, 1H6, 1H7/
      DATA D(9), D(10), D(11), D(12) /1H8, 1H9, 1HA, 1HB/
      DATA D(13), D(14), D(15), D(16) /1HC, 1HD, 1HE, 1HF/
      DATA D(17) /1H*/
      I = MIN0 (N, 16)
      IF (I .LT. 0) I = 16
      MPDIGW = D(I+1)
      RETURN
      END
C $$                   ******  MPDIM  ******
      SUBROUTINE MPDIM (X, Y, Z)
C SETS Z = X - MIN (X, Y) = MAX (0, X-Y) FOR MP X AND Y,
C ROUNDING AS FOR MPSUB.  X AND/OR Y MAY BE PACKED OR UNPACKED.
      INTEGER X(1), Y(1), Z(1)
C AVOID POSSIBILITY OF OVERFLOW IF RESULT IS ZERO.
      IF ((X(1).LE.0).AND.(Y(1).GE.0)) GO TO 10
      CALL MPKSUB (X, Y, Z)
      IF (Z(1).GE.0) RETURN
   10 Z(1) = 0
      RETURN
      END
C $$                   ******  MPDIV  ******
      SUBROUTINE MPDIV (X, Y, Z)
C
C SETS Z = X/Y, FOR MP X, Y AND Z.
C USES MPDIVL FOR SMALL T, MPREC AND MPMUL FOR LARGE T, SO TIME
C IS O(M(T)).  OVER/UNDERFLOW IS DETECTED BY SUBROUTINE MPNZR.
C
C ROUNDING IS DETERMINED BY RNDRL IN COMMON /MPCOM/ AS FOLLOWS -
C RNDRL = 0 - ERROR LESS THAN 1 UNIT IN LAST PLACE (ULP), SO EXACT
C             IF RESULT CAN BE EXACTLY REPRESENTED.
C RNDRL = 1 - SEE MPNZR.
C RNDRL = 2 OR 3 - DIRECTED ROUNDINGS - SEE SUBROUTINE MPNZR.
C
      COMMON R
      COMMON /MPCOM/ B, T, M, DUMMY
      INTEGER CROSS, I2, I3, SV, TG
      INTEGER B, DUMMY(20), M, MPGD, R(1), T, X(1), Y(1), Z(1)
C FOLLOWING CROSSOVER POINT DETERMINED EMPIRICALLY
      DATA CROSS /80/
C SAVE T, M, RNDRL ETC.
      CALL MPSAVN (SV)
C CHECK FOR DIVISION BY ZERO
      IF (Y(1) .EQ. 0) CALL MPERRM (
     $  44HATTEMPTED DIVISION BY ZERO IN CALL TO MPDIV$)
C CHECK FOR X = 0
      IF (X(1).NE.0) GO TO 10
      Z(1) = 0
      GO TO 30
C SEE IF T SMALL ENOUGH THAT MPDIVL IS FASTER THAN MPREC
C OR MUST USE MPDIVL TO ENSURE CORRECT ROUNDED RESULT
   10 TG = T + 1 + MPGD(100)
      IF ((TG.LT.CROSS) .OR. (R(SV+2).NE.0)) GO TO 20
C HERE USE MPREC AND MPMUL.  INCREASE T AND M TEMPORARILY.
      T = TG
      M = M + T
C ALLOCATE TEMPORARY SPACE
      CALL MPNEW (I2)
C MOVE Y AND COMPUTE RECIPROCAL, TAKING CARE FOR DIRECTED ROUNDING
      CALL MPMOVE (Y, IABS(R(SV)), R(I2), TG)
      CALL MPREVR (-X(1))
      CALL MPREC (R(I2), R(I2))
C RESTORE RNDRL AND MOVE X FOR MULTIPLICATION
      CALL MPSETR (IABS(R(SV+2)))
      CALL MPNEW (I3)
      CALL MPMOVE (X, IABS(R(SV)), R(I3), TG)
      CALL MPMUL (R(I3), R(I2), R(I2))
C RESTORE M (SO MPNZR CAN DETECT OVERFLOW/UNDERFLOW)
      M = R(SV+1)
C ROUND RESULT (TO NEAREST IF RNDRL = 0 OR 1)
      CALL MPRND (R(I2), TG, Z, IABS(R(SV)), 0)
      GO TO 30
C HERE FASTER OR NECESSARY TO USE MPDIVL
   20 CALL MPDIVL (X, Y, Z)
C RESTORE EVERYTHING
   30 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPDIVI  ******
      SUBROUTINE MPDIVI (X, IY, Z)
C DIVIDES MP X BY THE SINGLE-PRECISION INTEGER IY GIVING MP Z.
C THIS IS MUCH FASTER THAN DIVISION BY AN MP NUMBER.
C ROUNDING IS DEFINED BY PARAMETER RNDRL IN COMMON /MPCOM/ -
C SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, DUMMY
      INTEGER I2, J, KG, MPGD, RE, RS, TWO,
     $  B, DUMMY(12), IY, LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR,
     $  MXSPTR, R(1), RNDRL, SPTR, T, X(1), Z(1)
      TWO = 2
C COMPUTE NUMBER OF GUARD DIGITS REQUIRED.
      KG = MIN0 (1, RNDRL)
      IF (RNDRL.EQ.1) KG = 1 + MPGD (IY)
C ALLOCATE T+KG WORDS FOR ACCUMULATOR IF NECESSARY.
      I2 = SPTR
      IF (KG.GT.0) CALL MPNEW2 (I2, T + KG)
C GET SIGN OF X
      RS = X(1)
      J = IABS(IY)
C CHECK SIGN OF DIVISOR
      IF (IY) 20, 10, 30
   10 CALL MPERRM (45HATTEMPTED DIVISION BY ZERO IN CALL TO MPDIVI$)
C ALLOW FOR NEGATIVE DIVISOR
   20 RS = -RS
C CHECK FOR ZERO DIVIDEND
   30 IF (RS.NE.0) GO TO 40
      Z(1) = 0
      GO TO 100
   40 RE = X(TWO)
C CHECK FOR DIVISION BY +-B (THIS IS COMMON - SEE MPOUT2)
      IF (J.NE.B) GO TO 70
      RE = RE - 1
C MOVE X TO Z.
   50 CALL MPSTR (X, Z)
C FIX UP SIGN AND EXPONENT OF RESULT.
   60 Z(1) = RS
      Z(TWO) = RE
C CHECK FOR UNDERFLOW
      IF (RE.LE.(-M)) GO TO 90
C UPDATE MNEXPN
      MNEXPN = MIN0 (RE, MNEXPN)
      GO TO 100
C CHECK FOR DIVISION BY +-1
   70 IF (J.EQ.1) GO TO 50
C GENUINE DIVISION HERE.  CHECK NUMBER OF GUARD DIGITS.
      IF (KG.GT.0) GO TO 80
C HERE CAN USE Z(3), ... , Z(T+2) AS ACCUMULATOR.
      CALL MPDIV2 (X(TWO+1), J, 0, RE, Z(TWO+1))
      GO TO 60
C HERE USE R(I2), ... , R(SPTR-1) AS ACCUMULATOR
   80 CALL MPDIV2 (X(TWO+1), J, KG, RE, R(I2))
      CALL MPNZR (RS, RE, Z(1), R(I2), KG)
      GO TO 100
C UNDERFLOW HERE
   90 CALL MPUNFL (Z)
C RESTORE STACK POINTER AND RETURN
  100 SPTR = I2
      RETURN
      END
C $$                   ******  MPDIVL  ******
      SUBROUTINE MPDIVL (X, Y, Z)
C DIVIDES X BY Y, GIVING RESULT Z, FOR MP X, Y AND Z.
C USES LONG DIVISION METHOD, TIME O(T**2).   AN ALTERNATIVE METHOD
C (IMPLEMENTED IN MPDIV) WITH TIME O(M(T)) IS TO USE MPREC AND
C MPMUL. WITH THE PRESENT IMPLEMENTATION OF MPMUL, THIS IS FASTER
C (BY UP TO A FACTOR OF ABOUT 2) FOR LARGE T, BUT MPDIVL IS FASTER
C FOR SMALL T (SEE DATA CROSS /.../ IN MPDIV AND MPREC).
C ROUNDING IS DETERMINED BY RNDRL IN COMMON /MPCOM/ -
C SEE SUBROUTINE MPNZR.
      COMMON R
      INTEGER I2, I3, KG, R(1), SV, TWO, X(1), Y(1), Z(1)
      TWO = 2
C CHECK FOR DIVISION BY ZERO.
      IF (Y(1) .EQ. 0) CALL MPERRM (
     $  35HDIVISION BY ZERO IN CALL TO MPDIVL$)
C CHECK FOR X ZERO.
      IF (X(1).NE.0) GO TO 10
      Z(1) = 0
      RETURN
C HERE X AND Y ARE NONZERO.  DETERMINE NUMBER OF GUARD DIGITS.
   10 CALL MPSAVN (SV)
      KG = MIN0 (2, R(SV+2)+1)
      IF (R(SV+2).EQ.1) KG = R(SV) + 2
C ALLOCATE TEMPORARY STORAGE
      CALL MPNEW2 (I2, R(SV) + KG)
      CALL MPNEW (I3)
C MOVE X TO TEMPORARY STORAGE AS MPDIV3 OVERWRITES FIRST ARGUMENT.
      CALL MPSTR (X, R(I3))
C DO LONG DIVISION
      CALL MPDIV3 (R(I3+1), Y(TWO), R(I2), KG)
C NORMALIZE AND ROUND RESULT
      CALL MPNZR (X(1)*Y(1), X(TWO)+1-Y(TWO), Z, R(I2), KG)
C RESTORE STACK POINTER AND RETURN.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPDIV2  ******
      SUBROUTINE MPDIV2 (X, J, KG, RE, A)
C CALLED BY MPDIVI, NOT FOR INDEPENDENT USE.
C ASSUMES X(1) ... X(T) REPRESENTS A BASE B NUMBER, X(1) .GT. 0,
C J .GT. 0.   DIVIDES BY J, RESULT IN A(1) ... A(T+KG).  THE RESULT
C IS LEFT SHIFTED SO A(1) .GT. 0 AND RE DECREMENTED ACCORDINGLY.
C ASSUMES KG. GE. 0, ALSO KG .GT. 0 IF RNDRL .GT. 0 .
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR, MXEXPN,
     $  MNEXPN, RNDRL, KTUNFL, MXUNFL, DECPL, MT2, MXINT, DUMMY
      INTEGER B2, C, C2, I, IQ, IQJ, IR, J1, J11, J2, K, KH, KHH, R1,
     $  A(1), B, DECPL, DUMMY(7), J, KG, KTUNFL, LUN, M, MNEXPN,
     $  MNSPTR, MT2, MXEXPN, MXINT, MXR, MXSPTR, MXUNFL, RE, RNDRL,
     $  SPTR, T, X(1)
      C = 0
      I = 0
      KHH = T + KG
C IF J*B NOT REPRESENTABLE AS AN INTEGER HAVE TO SIMULATE
C LONG DIVISION.
      B2 = MXINT/B
      IF (J.GE.B2) GO TO 70
C LOOK FOR FIRST NONZERO DIGIT IN QUOTIENT
   10 I = I + 1
      C = B*C
      IF (I.LE.T) C = C + X(I)
      R1 = C/J
      IF (R1) 150, 10, 20
C ADJUST EXPONENT AND GET T+KG DIGITS IN QUOTIENT
   20 RE = RE + 1 - I
      A(1) = R1
      C = B*(C - J*R1)
      KH = 2
      IF (I.GE.T) GO TO 40
      KH = T + 1 - I
      DO 30 K = 2, KH
      I = I + 1
      C = C + X(I)
      A(K) = C/J
   30 C = B*(C - J*A(K))
      IF (C.LT.0) GO TO 150
      KH = KH + 1
   40 IF (KH.GT.KHH) GO TO 60
      DO 50 K = KH, KHH
      A(K) = C/J
   50 C = B*(C - J*A(K))
      IF (C.LT.0) GO TO 150
C ADJUST LAST DIGIT FOR DIRECTED ROUNDING
   60 IF ((RNDRL.GT.1).AND.(C.GT.0)) A(KHH) = 1
      RETURN
C HERE NEED SIMULATED DOUBLE-PRECISION DIVISION
   70 C2 = 0
      J1 = J/B
      J2 = J - J1*B
      J11 = J1 + 1
C LOOK FOR FIRST NONZERO DIGIT
   80 I = I + 1
      C = B*C + C2
      C2 = 0
      IF (I.LE.T) C2 = X(I)
      IF (C-J1)  80, 90, 100
   90 IF (C2.LT.J2) GO TO 80
C COMPUTE T+KG QUOTIENT DIGITS
  100 RE = RE + 1 - I
      K = 1
      GO TO 120
C MAIN LOOP FOR LARGE ABS(IY) CASE
  110 K = K + 1
      IF (K.GT.KHH) GO TO 60
      I = I + 1
C GET APPROXIMATE QUOTIENT FIRST
  120 IR = C/J11
C NOW REDUCE SO OVERFLOW DOES NOT OCCUR
      IQ = C - IR*J1
      IF (IQ.LT.B2) GO TO 130
C HERE IQ*B WOULD POSSIBLY OVERFLOW SO INCREASE IR
      IR = IR + 1
      IQ = IQ - J1
  130 IQ = IQ*B - IR*J2
      IF (IQ.GE.0) GO TO 140
C HERE IQ NEGATIVE SO IR WAS TOO LARGE
      IR = IR - 1
      IQ = IQ + J
  140 IF (I.LE.T) IQ = IQ + X(I)
      IQJ = IQ/J
C A(K) = QUOTIENT, C = REMAINDER
      A(K) = IQJ + IR
      C = IQ - J*IQJ
      IF (C.GE.0) GO TO 110
C CARRY NEGATIVE SO OVERFLOW MUST HAVE OCCURRED
  150 CALL MPERRM (40HINTEGER OVERFLOW IN MPDIV2, B TOO LARGE$)
      RETURN
      END
C $$                   ******  MPDIV3  ******
      SUBROUTINE MPDIV3 (X, Y, D, KG)
C CALLED BY MPDIVL.  ASSUMES X(2), ... X(T+1) AND
C Y(2), ... , Y(T+1) CONTAIN BASE B INTEGERS, X(2) .GT. 0,
C Y(2) .GT. 0, KG .GE. 0.  ALSO ASSUMES KG .GE. 2 IF RNDRL .GT. 0.
C RETURNS FIRST T+KG DIGITS OF QUOTIENT X/Y IN D(1), ... , D(T+KG).
C DESTROYS X(1), ... , X(T+1), USES BUT RESTORES Y(1).
C ARGUMENTS MUST NOT OVERLAP.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B1, C, I, IR, J, K, Q, TG, TWO, T1, T2, Y1S,
     $  B, D(1), DUMMY(21), KG, MPPARN, T, X(1), Y(1)
      TWO = 2
C SAVE Y(1) AND SET TO ZERO.
      Y1S = Y(1)
      Y(1) = 0
C SET UP OUTER LOOP.
      X(1) = 0
      B1 = B*(B-1)
      T1 = T + 1
      T2 = T1 + 1
      TG = T + KG
C OUTER LOOP
      DO 70 J = 1, TG
      D(J) = 0
C COMPARE X AND Y (USUALLY ONLY ONCE FOR EACH J).
   10 DO 20 I = 1, T1
      IF (X(I) - Y(I)) 50, 20, 30
   20 CONTINUE
C HERE B*Y .GT. X .GE. Y,   COMPUTE LOWER BOUND ON QUOTIENT X/Y.
   30 Q = MAX0 (1, (B*X(1) + X(TWO))/(Y(TWO) + 1))
C COMPUTE SHARPER LOWER BOUND IF OVERFLOW IMPOSSIBLE.
      IF ((X(1)+1) .LT. (MPPARN(16)/(B*B))) Q =
     $  MAX0 (Q, (B*(B*X(1)+X(TWO))+X(TWO+1))/
     $  (B*Y(TWO)+Y(TWO+1)+1))
C INCREMENT J-TH QUOTIENT DIGIT
      D(J) = D(J) + Q
      I = T2
C K IS (B + SIGNED CARRY), 0 .LT. K .LE. B.
      K = B
C INNER LOOP
      DO 40 IR = 1, T1
      I = I - 1
      C = B1 + K + X(I) - Q*Y(I)
      K = C/B
   40 X(I) = C - B*K
C THERE SHOULD BE NO CARRY OFF END.  CHECK JUST IN CASE.
      IF (K.EQ.B) GO TO 10
      CALL MPERRM (36HINTEGER OVERFLOW OCCURRED IN MPDIV3$)
C SHIFT X LEFT
   50 DO 60 I = 1, T
   60 X(I) = X(I+1)
C LAST STATEMENT OF OUTER LOOP.
   70 X(T1) = 0
C RESTORE Y(1).
      Y(1) = Y1S
C RETURN IF RNDRL .LE. 1
      IF (MPPARN(11).LE.1) RETURN
C IF REMAINDER NONZERO MAKE SURE A GUARD DIGIT NONZERO FOR
C DIRECTED ROUNDING (ASSUMES KG .GE. 2 HERE)
      DO 80 I = 1, T
   80 D(TG) = MAX0 (D(TG), X(I))
      RETURN
      END
C $$                   ******  MPDUMP  ******
      SUBROUTINE MPDUMP (X)
C DUMPS OUT THE MP NUMBER X (SIGN, EXPONENT, FRACTION DIGITS),
C USEFUL FOR DEBUGGING PURPOSES.
C EMBEDDED BLANKS SHOULD BE INTERPRETED AS ZEROS. (THEY COULD BE
C AVOIDED BY USING J INSTEAD OF I FORMAT, BUT THIS IS NONSTANDARD.)
C X MAY BE PACKED OR UNPACKED.
      COMMON R
      INTEGER B, I2, LUN, MPPARN, R(1), SV, T2, X(1)
      LOGICAL ERR
C CHECK LEGALITY OF PARAMETERS IN COMMON /MPCOM/
      CALL MPCHK
      LUN = MPPARN (4)
      IF (X(1).NE.0) GO TO 10
C IF X = 0 JUST WRITE SIGN AS REMAINDER UNDEFINED
      CALL MPIO (X, 1, LUN, 7H(1X,I2), ERR)
      RETURN
C HERE X IS NONZERO, SO UNPACK IF NECESSARY
   10 CALL MPSAVN (SV)
      B = MPPARN (1)
      T2 = MPPARN (2) + 2
      CALL MPNEW (I2)
      CALL MPUNPK (X, R(I2))
      IF (B.LE.10) CALL MPIO (R(I2), T2, LUN,
     $  30H(1X,I2,I12,4X,50I1/(19X,50I1)), ERR)
      IF ((B.GT.10).AND.(B.LE.100)) CALL MPIO (R(I2), T2, LUN,
     $  30H(1X,I2,I12,4X,25I2/(19X,25I2)), ERR)
      IF ((B.GT.100).AND.(B.LE.1000)) CALL MPIO (R(I2), T2, LUN,
     $  30H(1X,I2,I12,4X,17I3/(19X,17I3)), ERR)
      IF ((B.GT.1000).AND.(B.LE.10000)) CALL MPIO (R(I2), T2, LUN,
     $  30H(1X,I2,I15,4X,12I4/(22X,12I4)), ERR)
      IF (B.GT.10000) CALL MPIO (R(I2), T2, LUN,
     $  30H(1X,I2,I23,4X,4I10/(30X,4I10)), ERR)
      IF (ERR) CALL MPERRM (33HERROR RETURN FROM MPIO IN MPDUMP$)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPEI  ******
      SUBROUTINE MPEI (X, Y)
C RETURNS Y = EI(X) = -E1(-X)
C           = (PRINCIPAL VALUE INTEGRAL FROM -INFINITY TO X OF
C              EXP(U)/U DU),
C FOR MP NUMBERS X AND Y,
C USING THE POWER SERIES FOR SMALL ABS(X), THE ASYMPTOTIC SERIES FOR
C LARGE ABS(X), AND THE CONTINUED FRACTION FOR INTERMEDIATE NEGATIVE
C X.  RELATIVE ERROR IN Y IS SMALL EXCEPT IF X IS VERY CLOSE TO THE
C ZERO  0.37250741078136663446... OF EI(X),
C AND THEN THE ABSOLUTE ERROR IN Y IS O(B**(1-T)).
C IN ANY CASE THE ERROR IN Y COULD BE INDUCED BY AN
C O(B**(1-T)) RELATIVE PERTURBATION IN X.
C TIME IS O(T.M(T)).
C ROUNDING OPTIONS NOT YET IMPLEMENTED, GUARD DIGITS NOT ALWAYS USED.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, I2, I3, I4, J, K, SV, TD, TM, TM2, TS1, TS2, XS
      INTEGER B, DUMMY(21), MPT, R(1), T, X(1), Y(1)
      INTEGER MPCHGB, MPCMPA, MPCMPQ, MPGET, MPTLB
C SAVE T ETC.
      CALL MPSAVN (SV)
      XS = X(1)
C EI(0) IS UNDEFINED.
      IF (XS .EQ. 0) CALL MPERRM (23HX ZERO IN CALL TO MPEI$)
C PREPARE TO INCREASE T.
      TM2 = (11*T+19)/10
      TM = (6*T+9)/5
      I = 0
C INCREASE T AND ALLOCATE TEMPORARY SPACE.
      T = TM
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
C USE TRUNCATED ARITHMETIC
      CALL MPSETR (0)
C MOVE X AND RESTORE T.
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TM)
      CALL MPABS (R(I2), R(I3))
      T = R(SV)
      MPT = MPTLB(IABS(T))
C SEE IF ABS(X) LARGE ENOUGH TO USE ASYMPTOTIC SERIES
C 7/10 .GT. LN(2)
      IF (MPCMPQ (R(I3), 7*MPT, 10) .GT. 0) GO TO 40
C SEE IF X NEGATIVE AND CONTINUED FRACTION USABLE
C THE CONSTANT 1/15 WAS DETERMINED EMPIRICALLY AND MAY BE
C DECREASED (BUT NOT INCREASED) IF DESIRED.
      IF ((XS.LT.0) .AND. (MPCMPQ (R(I3), MPT, 15) .GT. 0)) GO TO 60
C USE POWER SERIES HERE, BUT NEED TO INCREASE T IF X NEGATIVE
C TO COMPENSATE FOR CANCELLATION.
      T = T + 1
      TS1 = T
      TS2 = T
      IF (XS.GT.0) GO TO 10
C IF X NEGATIVE RESULT ABOUT B**(-TD) AND TERMS ABOUT B**TD SO
C NEED UP TO 2*TD EXTRA DIGITS TO COMPENSATE FOR CANCELLATION
C MPCHGB(...)/3 UNDERESTIMATES LN(B).
      CALL MPMULQ (R(I3), 3, MPCHGB(2,MAX0(2,B/2),2), R(I4))
      CALL MPCMI (R(I4), TD)
      TD = TD + 1
      TS2 = T + TD
      TS1 = MIN0 (TS2 + TD, TM)
      TS2 = MIN0 (TS2, TM2)
C USE TS2 DIGITS FOR LN AND EULERS CONSTANT COMPUTATION
      T = TS2
C NOW PREPARE TO SUM POWER SERIES
   10 CALL MPLN (R(I3), R(I4))
C MPEI COULD BE SPEEDED UP IF EULERS CONSTANT WERE
C PRECOMPUTED AND SAVED
      CALL MPEUL (R(I2))
      CALL MPADD (R(I2), R(I4), R(I2))
C NOW USE TS1 DIGITS FOR SUMMING POWER SERIES
      T = TS1
C RESTORE SIGN OF R(I3)
      R(I3) = XS
      CALL MPADD (R(I2), R(I3), R(I2))
      CALL MPSTR (R(I3), R(I4))
C LOOP TO SUM POWER SERIES, REDUCING T IF POSSIBLE
   20 IF (XS.GE.0) T = TS1 + 2 + R(I4+1) - R(I2+1)
      IF ((XS.LT.0).AND.(R(I4+1).LE.0)) T = TS2 + 2 + R(I4+1)
      T = MIN0 (T, TS1)
      IF (T.LE.2) GO TO 30
      CALL MPMUL (R(I3), R(I4), R(I4))
      I = I + 1
      CALL MPMULS (R(I4), I, 1, I+1, I+1)
C RESTORE T FOR ADDITION
      T = TS1
      CALL MPADD (R(I2), R(I4), R(I2))
      IF (R(I4).NE.0) GO TO 20
C RESTORE T, MOVE RESULT AND RETURN
   30 T = R(SV)
      CALL MPSTR (R(I2), Y)
      GO TO 100
C HERE WE CAN USE ASYMPTOTIC SERIES, AND NO NEED TO INCREASE T
   40 CALL MPREC (X, R(I3))
C MPEXP GIVES ERROR MESSAGE IF X TOO LARGE HERE
      CALL MPEXP (X, Y)
      IF (Y(1).EQ.0) GO TO 100
      CALL MPMUL (Y, R(I3), Y)
      CALL MPSTR (Y, R(I2))
C LOOP TO SUM ASYMPTOTIC SERIES, REDUCING T IF POSSIBLE
   50 T = R(SV) + 2 + R(I2+1) - MPGET (Y, 2)
C RETURN IF TERMS SMALL ENOUGH TO BE NEGLIGIBLE
      IF (T.LE.2) GO TO 100
      T = MIN0 (T, R(SV))
      CALL MPSTR (R(I2), R(I4))
      CALL MPMUL (R(I2), R(I3), R(I2))
      I = I + 1
      CALL MPMULI (R(I2), I, R(I2))
C RETURN IF TERMS INCREASING
      IF (MPCMPA (R(I2), R(I4)) .GE. 0) GO TO 100
C RESTORE T FOR ADDITION
      T = R(SV)
      CALL MPADD (Y, R(I2), Y)
      IF (R(I2).NE.0) GO TO 50
      GO TO 100
C HERE 0.1*T*LN(B) .LT. -X .LE T*LN(B), SO USE CONTINUED FRACTION.
   60 K = T
      J = 0
C USE EQUIVALENT OF 6 DECIMAL PLACES FOR FORWARD RECURRENCE.
C WE COULD USE SINGLE-PRECISION REAL HERE IF TRUSTED.
      T = MIN0 (T, MAX0 (2, MPCHGB (IABS(B), 10, 5) + 1))
      CALL MPNEG (X, R(I2))
      CALL MPCIM (1, R(I3))
C USE FORWARD RECURRENCE TO FIND OUT HOW MANY TERMS ARE
C NEEDED IN BACKWARD RECURRENCE
   70 J = J + 1
      CALL MPDIVI (R(I2), J, R(I4))
      CALL MPADD (R(I3), R(I4), R(I3))
      CALL MPMUL (X, R(I3), R(I4))
      CALL MPSUB (R(I2), R(I4), R(I2))
      IF (R(I3) .EQ. 0) GO TO 70
C SCALING HERE
   80 IF (R(I3+1) .LE. 1) GO TO 70
      R(I3+1) = R(I3+1) - 1
      R(I2+1) = R(I2+1) - 1
      K = K - 2
      IF (K .GT. 0) GO TO 80
C RESTORE T FOR BACKWARD RECURRENCE
      T = R(SV)
      CALL MPABS (X, R(I3))
C NOW USE BACKWARD RECURRENCE WITH MP ARITHMETIC
      CALL MPCIM (1, R(I2))
   90 CALL MPDIVI (R(I3), J, R(I4))
      CALL MPADD (R(I2), R(I4), R(I2))
      CALL MPMUL (X, R(I2), R(I4))
      CALL MPSUB (R(I3), R(I4), R(I3))
C SCALE TO AVOID OVERFLOW
      R(I2+1) = R(I2+1) - R(I3+1)
      R(I3+1) = 0
      J = J - 1
      IF (J.GT.0) GO TO 90
      CALL MPDIV (R(I2), R(I3), R(I2))
      CALL MPEXP (X, Y)
      CALL MPMUL (Y, R(I2), Y)
      Y(1) = -Y(1)
C RESTORE EVERYTHING AND RETURN.
  100 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPEPS  ******
      SUBROUTINE MPEPS (X)
C
C SETS MP X TO THE (MULTIPLE-PRECISION) MACHINE PRECISION,
C THAT IS
C         X = 1.01*(B**(1-T))   (ROUNDED UP) IF RNDRL = 0,
C              0.5*(B**(1-T))   (ROUNDED UP) IF RNDRL = 1,
C                   B**(1-T)                 IF RNDRL = 2 OR 3.
C
C X IS AN UPPER BOUND ON THE SMALLEST POSITIVE REPRESENTABLE
C NUMBER SUCH THAT THE RELATIVE ERROR IN THE BASIC MP OPERATIONS
C (ADDITION, SUBTRACTION, MULTIPLICATION AND DIVISION) IS AT
C MOST X (UNLESS THE RESULT UNDERFLOWS).
C
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, DUMMY
      INTEGER B, DUMMY(12), LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR, MXSPTR,
     $  RNDRL, RSV, SPTR, T, TWO, X(1)
      TWO = 2
C CHECK B, T ETC.
      CALL MPCHK
C SET X TO B**(1-T)
      CALL MPCIM (1, X)
      X(TWO) = 2 - T
      CALL MPUPDT (X(TWO))
      IF (RNDRL.GT.1) RETURN
C HERE RNDRL = 0 OR 1.
      RSV = RNDRL
C SET RNDRL FOR ROUNDING UP
      RNDRL = 3
      IF (RSV .EQ. 0) CALL MPMULQ (X, 101, 100, X)
      IF (RSV .NE. 0) CALL MPDIVI (X, 2, X)
      RNDRL = RSV
      RETURN
      END
C $$                   ******  MPEQ  ******
      LOGICAL FUNCTION MPEQ (X, Y)
C RETURNS LOGICAL VALUE OF (X .EQ. Y) FOR MP X AND Y.
C X AND/OR Y MAY BE PACKED OR UNPACKED.
      INTEGER MPCOMP, X(1), Y(1)
      MPEQ = (MPCOMP(X,Y) .EQ. 0)
      RETURN
      END
C $$                   ******  MPERF  ******
      SUBROUTINE MPERF (X, Y)
C RETURNS Y = ERF(X) = SQRT(4/PI)*(INTEGRAL FROM 0 TO X OF
C EXP(-U**2) DU) FOR MP X AND Y.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, DUMMY
      LOGICAL ERR
      INTEGER IRX, I2, I3, SV, TG, TWO, XS,
     $  B, DUMMY(20), M, R(1), T, X(1), Y(1),
     $  MPCHGB, MPCMPQ, MPGD, MPTLB
      TWO = 2
C SAVE T ETC.
      CALL MPSAVN (SV)
C CHECK FOR ZERO ARGUMENT.
      XS = X(1)
      IF (XS.NE.0) GO TO 10
C ERF(0) = 0
      Y(1) = 0
      GO TO 60
C INCREASE T, ALLOCATE TEMPORARY STORAGE, AND RESTORE T.
   10 CALL MPGD3 (MPTLB(IABS(T)), TG)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
C USE TRUNCATED ARITHMETIC INTERNALLY.
      CALL MPSETR (0)
      M = M + T
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      R(I2) = IABS (R(I2))
      CALL MPMUL (R(I2), R(I2), R(I3))
C 7/10 .GT. LN(2)
      IF (MPCMPQ (R(I3), 7*MPTLB(IABS(T)), 10) .LT. 0) GO TO 20
C HERE ABS(X) SO LARGE THAT ERF(X) = +-1 TO FULL ACCURACY
      CALL MPCIM (XS, R(I3))
      GO TO 50
C TRY USING ASYMPTOTIC SERIES.
C CAN POSSIBLY REDUCE T TEMPORARILY.
   20 CALL MPMULQ (R(I3), 10, MPCHGB(2,IABS(B),7), R(I3))
      CALL MPCMI (R(I3), IRX)
      T = MIN0(T, MAX0(4*MPGD(100), T-IRX))
      CALL MPERF3 (R(I2), R(I2), .FALSE., ERR)
      IF (.NOT. ERR) GO TO 30
C ASYMPTOTIC SERIES INSUFFICIENT, SO USE POWER SERIES
      T = TG
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPERF2 (R(I2), R(I2))
C IN BOTH CASES MULTIPLY BY SQRT(4/PI)*EXP(-X**2)
   30 CALL MPMOVE (X, IABS(R(SV)), R(I3), IABS(T))
      CALL MPMUL (R(I3), R(I3), R(I3))
      R(I3) = -R(I3)
      CALL MPEXP(R(I3), R(I3))
      CALL MPMUL (R(I3), R(I2), R(I2))
      CALL MPPI (R(I3))
      CALL MPROOT (R(I3), -2, R(I3))
      CALL MPMUL (R(I3), R(I2), R(I2))
      IF (.NOT. ERR) GO TO 40
C USED POWER SERIES SO CAN RETURN
      CALL MPMULI (R(I2), 2, R(I3))
      GO TO 50
C USED POWER SERIES.
   40 CALL MPMULI (R(I2), -2, R(I2))
      CALL MPMOVE (R(I2), IABS(T), R(I2), TG)
      T = TG
      CALL MPADDI (R(I2), 1, R(I3))
      R(I3) = XS*R(I3)
C ROUND RESULT.
   50 CALL MPRES2 (SV)
      CALL MPRND (R(I3), IABS(T), Y, IABS(R(SV)), 1)
C ENSURE THAT RESULT IN -1 TO +1.
      IF ((Y(1).NE.0) .AND. (Y(TWO).GT.0)) CALL MPCIM (XS, Y)
C RESTORE EVERYTHING AND RETURN
   60 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPERFC  ******
      SUBROUTINE MPERFC (X, Y)
C RETURNS Y = ERFC(X) = 1 - ERF(X) FOR MP NUMBERS X AND Y,
C USING MPERF AND MPERF3.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, DUMMY
      LOGICAL ERR
      INTEGER IT, I2, I3, MPCHGB, MPTLB, SV, TG,
     $  B, DUMMY(17), LUN, M, MXR, R(1), SPTR, T, X(1), Y(1)
C SAVE T ETC., CHECK SIGN OF ARGUMENT X.
      CALL MPSAVN (SV)
      IF (X(1).GT.0) GO TO 10
C FOR X .LE. 0 NO SIGNIFICANT LOSS OF ACCURACY IN USING ERF(X)
      CALL MPREVR (1)
      CALL MPERF (X, Y)
      CALL MPRES2 (SV)
      Y(1) = -Y(1)
      CALL MPADDI (Y, 1, Y)
      GO TO 40
C INCREASE T, ALLOCATE SOME SPACE, USE TRUNCATION INTERNALLY.
   10 CALL MPGD3 (MPTLB (IABS(T)), TG)
      CALL MPNEW (I2)
      CALL MPSETR (0)
C TRY ASYMPTOTIC SERIES
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPERF3 (R(I2), R(I2), .FALSE., ERR)
      IF (ERR) GO TO 20
C ASYMPTOTIC SERIES WORKED, SO MULTIPLY BY
C SQRT(4/PI)*EXP(-X**2)
      CALL MPNEW (I3)
      CALL MPMOVE (X, IABS(R(SV)), R(I3), TG)
      CALL MPMUL (R(I3), R(I3), R(I3))
      R(I3) = -R(I3)
      CALL MPEXP (R(I3), R(I3))
      CALL MPMUL (R(I3), R(I2), R(I2))
      CALL MPPI (R(I3))
      CALL MPROOT (R(I3), -2, R(I3))
      CALL MPMUL (R(I3), R(I2), R(I2))
      CALL MPMULI (R(I2), 2, R(I2))
      GO TO 30
C HERE ASYMPTOTIC SERIES INACCURATE SO HAVE TO
C USE MPERF, INCREASING PRECISION TO COMPENSATE FOR
C CANCELLATION.  AN ALTERNATIVE METHOD (POSSIBLY FASTER) IS
C TO USE THE CONTINUED FRACTION FOR EXP(X**2)*ERFC(X).
   20 T = R(SV)
      CALL MPMUL (X, X, R(I2))
C LN(B) .GT. MPCHGB (2, B, 80) / 120
      CALL MPMULQ (R(I2), 120, MPCHGB(2,IABS(B),80), R(I2))
      CALL MPCMI (R(I2), IT)
C COMPUTE NEW T FOR MPERF COMPUTATION
      T = T + IT
      SPTR = I2
      CALL MPGD3 (1, TG)
      CALL MPNEW (I2)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPERF (R(I2), R(I2))
      R(I2) = -R(I2)
      CALL MPADDI (R(I2), 1, R(I2))
C ROUND RESULT.
   30 CALL MPRES2 (SV)
      CALL MPRND (R(I2), TG, Y, IABS(R(SV)), 1)
C RESTORE EVERYTHING AND RETURN.
   40 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPERF2  ******
      SUBROUTINE MPERF2 (X, Y)
C RETURNS Y = EXP(X**2)*(INTEGRAL FROM 0 TO X OF EXP(-U*U) DU)
C FOR MP NUMBERS X AND Y, USING THE POWER SERIES FOR SMALL X.
C CALLED BY MPERF, NOT RECOMMENDED FOR INDEPENDENT USE.
C ROUNDING OPTIONS NOT IMPLEMENTED, USES NO GUARD DIGITS.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, I2, I3, MPCMPQ, MPTLB, SV, TWO, XS,
     $  B, DUMMY(21), R(1), T, X(1), Y(1)
      TWO = 2
C SAVE T ETC., CHECK FOR ZERO ARGUMENT.
      CALL MPSAVN (SV)
      IF (X(1).NE.0) GO TO 10
C RETURN 0 IF X .EQ. 0
      Y(1) = 0
      GO TO 40
C ALLOCATE TEMPORARY SPACE.
   10 CALL MPNEW (I2)
C USE TRUNCATION INTERNALLY
      CALL MPSETR (0)
      CALL MPMUL (X, X, R(I2))
C 7/10 .GT. LN(2)
      IF (MPCMPQ (R(I2), 7*MPTLB(IABS(T)), 10) .GT. 0) GO TO 30
C USE THE POWER SERIES HERE
      CALL MPSTR (X, Y)
      CALL MPMULI (R(I2), 2, R(I2))
      CALL MPNEW (I3)
      CALL MPSTR (X, R(I3))
      I = 1
C LOOP TO SUM SERIES, REDUCING T IF POSSIBLE
   20 T = R(SV) + 2 + R(I3+1) - Y(TWO)
      IF (T.LE.2) GO TO 40
      T = MIN0 (T, R(SV))
      CALL MPMUL (R(I2), R(I3), R(I3))
      I = I + 2
      CALL MPDIVI (R(I3), I, R(I3))
C RESTORE T FOR ADDITION
      T = R(SV)
      CALL MPADD (Y, R(I3), Y)
      IF (R(I3).NE.0) GO TO 20
      GO TO 40
C HERE ABS(X) LARGE, SO INTEGRAL IS +-SQRT(PI/4)
C IF ABS(X) TOO LARGE MPEXP GIVES ERROR MESSAGE
   30 CALL MPEXP (R(I2), R(I2))
      XS = X(1)
      CALL MPPI (Y)
      CALL MPSQRT (Y, Y)
      CALL MPDIVI (Y, 2*XS, Y)
      CALL MPMUL (Y, R(I2), Y)
C RESTORE EVERYTHING AND RETURN
   40 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPERF3  ******
      SUBROUTINE MPERF3 (X, Y, IND, ERROR)
C IF IND = .FALSE., RETURNS Y = EXP(X**2)*(INTEGRAL FROM X TO
C                INFINITY OF EXP(-U**2) DU),
C IF IND = .TRUE., RETURNS Y = EXP(-X**2)*(INTEGRAL FROM 0 TO
C                X OF EXP(U**2) DU),
C IN BOTH CASES USING THE ASYMPTOTIC SERIES.
C X AND Y ARE MP NUMBERS, IND AND ERROR ARE LOGICAL.
C ERROR IS RETURNED AS .FALSE. IF X IS LARGE ENOUGH FOR
C THE ASYMPTOTIC SERIES TO GIVE FULL ACCURACY,
C OTHERWISE ERROR IS RETURNED AS .TRUE. AND Y AS ZERO.
C THE CONDITION ON X FOR ERROR .EQ. .FALSE. IS APPROXIMATELY THAT
C X .GT. SQRT(T*LOG(B)).
C CALLED BY MPERF, MPERFC AND MPDAW, NOT RECOMMENDED FOR
C INDEPENDENT USE.
C ROUNDING OPTIONS NOT IMPLEMENTED, USES NO GUARD DIGITS.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, IE, I2, I3, SV,
     $  B, DUMMY(21), R(1), T, X(1), Y(1),
     $  MPCMPI, MPCMPQ, MPGET, MPTLB
      LOGICAL IND, ERROR
C SAVE T ETC, USE TRUNCATION INTERNALLY.
      CALL MPSAVN (SV)
      CALL MPSETR (0)
C GET SOME TEMPORARY SPACE
      CALL MPNEW (I2)
      ERROR = .FALSE.
C CHECK THAT CAN GET AT LEAST T-2 DIGITS ACCURACY
      IF (MPCMPI (X, 1) .LE. 0) GO TO 10
      IF (MPGET (X, 2) .GE. T) GO TO 30
      CALL MPMUL (X, X, R(I2))
      IF (MPCMPQ (R(I2), 7*MPTLB(T-2), 10) .GT. 0) GO TO 30
C HERE X IS TOO SMALL FOR ASYMPTOTIC SERIES TO GIVE
C FULL ACCURACY, SO RETURN WITH Y = 0 AND ERROR = .TRUE..
   10 Y(1) = 0
      ERROR = .TRUE.
C RESTORE T ETC. AND RETURN.
   20 CALL MPRESN (SV)
      RETURN
C HERE WORTH TRYING ASYMPTOTIC SERIES.
   30 CALL MPREC (X, Y)
C ALLOCATE MORE TEMPORARY SPACE
      CALL MPNEW (I3)
      CALL MPMUL (Y, Y, R(I2))
      CALL MPDIVI (R(I2), 2, R(I2))
      IF (.NOT. IND) R(I2) = -R(I2)
      CALL MPDIVI (Y, 2, Y)
      CALL MPSTR (Y, R(I3))
      I = 1
C LOOP TO SUM SERIES, REDUCING T IF POSSIBLE
   40 IE = R(I3+1)
      T = R(SV) + 2 + IE - MPGET (Y, 2)
      IF (T.LE.2) GO TO 20
      T = MIN0 (T, R(SV))
      CALL MPMUL (R(I2), R(I3), R(I3))
      CALL MPMULI (R(I3), I, R(I3))
      I = I + 2
C RESTORE T FOR ADDITION
      T = R(SV)
C CHECK IF TERMS ARE GETTING LARGER - IF SO X IS TOO
C SMALL FOR ASYMPTOTIC SERIES TO BE ACCURATE
      IF (R(I3+1).GT.IE) GO TO 10
      CALL MPADD (Y, R(I3), Y)
      IF (R(I3).NE.0) GO TO 40
      GO TO 20
      END
C $$                   ******  MPERR  ******
      SUBROUTINE MPERR
C THIS ROUTINE IS CALLED WHEN A FATAL ERROR CONDITION IS ENCOUNTERED,
C AND AFTER A MESSAGE HAS BEEN WRITTEN ON LOGICAL UNIT LUN.
      COMMON /MPCOM/ SOME, LUN, REST
      INTEGER SOME(3), LUN, REST(19)
      WRITE (LUN, 10) SOME, REST
   10 FORMAT (' *** EXECUTION TERMINATED BY CALL TO MPERR',
     $        ' IN MP Linux version 20010829 ***'/
     $        14H *** B, T, M =, I22, 2I20/
     $        24H *** MXR, SPTR, MXSPTR =, I12, 2I20/
     $        29H *** MNSPTR, MXEXPN, MNEXPN =, I7, 2I20/
     $        28H *** RNDRL, KTUNFL, MXUNFL =, I8, 2I20/
     $        24H *** DECPL, MT2, MXINT =, I12, 2I20/
     $        36H *** EXWID, INRECL, INBASE, OUTBAS =, 4I4/
     $        28H *** EXPCH, CHWORD, ONESCP =, 11X, A1, 2I4//)
C ANSI VERSION USES STOP, UNIVAC 1108 VERSION USES
C RETURN 0 IN ORDER TO GIVE A TRACE-BACK.
      IF (.TRUE.) STOP
      RETURN
      END
C $$                   ******  MPERRM  ******
      SUBROUTINE MPERRM (A)
C THE ARGUMENT A IS A HOLLERITH STRING TERMINATED BY $.
C MPERRM WRITES THE STRING OUT ON UNIT LUN, THEN CALLS MPERR.
C ONLY THE FIRST 71 CHARACTERS OF A ARE SIGNIFICANT, AND
C ARE PRECEEDED AND FOLLOWED BY THREE ASTERISKS.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, DUMMY
      INTEGER A(1), I, I2, J, LEN, R(1), SV
      INTEGER B, T, M, LUN, DUMMY (19)
      LOGICAL ERR
      CALL MPCHK
      CALL MPSAVN (SV)
C GET SPACE FOR UNPACKING A
      CALL MPNEW2 (I2, 80)
C UNPACK A TO FIND ITS LENGTH AND ALLOW PRINTING IN A1 FORMAT.
      CALL MPUPK (A, R(I2+5), 71, LEN)
C INSERT LEADING AND TRAILING ASTERISKS.
      CALL MPUPK (5H *** , R(I2), 5, J)
      I = I2 + LEN
      CALL MPUPK (4H ***, R(I+5), 4, J)
C WRITE USING MPIO.
      CALL MPIO (R(I2), LEN+9, LUN, 6H(80A1), ERR)
C AND TERMINATE EXECUTION BY CALLING MPERR.
C (DO NOT CALL MPRESN BECAUSE POSSIBLE RECURSION.)
      CALL MPERR
      RETURN
      END
C $$                   ******  MPEUL  ******
      SUBROUTINE MPEUL (G)
C RETURNS MP G = EULERS CONSTANT (GAMMA = 0.57721566...)
C TO ALMOST FULL MULTIPLE-PRECISION ACCURACY.
C THE METHOD IS BASED ON BESSEL FUNCTION IDENTITIES AND WAS
C DISCOVERED BY EDWIN MC MILLAN AND R. BRENT.  IT IS FASTER THAN THE
C METHOD OF SWEENEY (MATH. COMP. 17, 1963, 170) USED IN EARLIER
C VERSIONS OF MPEUL.  TIME O(T**2).
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, DUMMY
      INTEGER I2, I3, I4, I5, K, N, SV, TG
      INTEGER B, DUMMY(17), G(1), LUN, M, MXR, R(1), SPTR, T
      INTEGER MPTLB
C SAVE T ETC.
      CALL MPSAVN (SV)
C INCREASE T AS NECESSARY TO GET ACCURATE RESULT
      N = MPTLB (IABS(T))
      CALL MPGD3 (N, TG)
C USE TRUNCATION INTERNALLY
      CALL MPSETR (0)
C COMPUTE N SO TRUNCATION ERROR (BOUNDED BY PI*EXP(-4N)) IS LESS
C THAN 0.01*(B**(-T)).
C 1/8 + 1/20 = 7/40 .GT. LN(2)/4
      N = N/8 + N/20 + 4
C COMPUTE LN(N).
      CALL MPNEW (I2)
      CALL MPLNI (N, R(I2))
C ALLOCATE MORE TEMPORARY SPACE
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPNEW (I5)
C SET UP MAIN LOOP
      R(I2) = -R(I2)
      CALL MPSTR (R(I2), R(I5))
      CALL MPCIM (1, R(I4))
      CALL MPSTR (R(I4), R(I3))
      K = 0
C MAIN LOOP STARTS HERE
   10 K = K + 1
C REDUCE T HERE IF POSSIBLE
      IF (K.GT.N) T = MIN0 (T, TG + R(I4+1) - R(I3+1))
C TEST FOR CONVERGENCE
      IF (T.LT.2) GO TO 20
      CALL MPMULS (R(I4), N, N, K, K)
      CALL MPMULS (R(I5), N, N, K, 1)
      CALL MPADD (R(I5), R(I4), R(I5))
      CALL MPDIVI (R(I5), K, R(I5))
C INCREASE T HERE
      T = TG
      CALL MPADD (R(I3), R(I4), R(I3))
      CALL MPADD (R(I2), R(I5), R(I2))
C END OF MAIN LOOP
      IF (R(I4).NE.0) GO TO 10
C COMPUTE FINAL QUOTIENT, RELEASING SOME SPACE FIRST
   20 T = TG
      SPTR = I4
      CALL MPDIV (R(I2), R(I3), R(I2))
C RESTORE RNDRL ETC AND ROUND RESULT
      CALL MPRES2 (SV)
      CALL MPRND (R(I2), TG, G, IABS(R(SV)), 1)
C RESTORE SPTR ETC.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPEXP  ******
      SUBROUTINE MPEXP (X, Y)
C RETURNS Y = EXP(X) FOR PACKED OR UNPACKED MP X, UNPACKED MP Y.
C TIME IS O(SQRT(T)M(T)).
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, DUMMY
      INTEGER I2, K, RP, SV, TG
      INTEGER B, DUMMY(19), LUN, M, R(1), T, X(1), Y(1)
      INTEGER MPGD, MPGET
C SAVE T ETC.
      CALL MPSAVN (SV)
C CHECK FOR X = 0
      IF (X(1).NE.0) GO TO 10
      CALL MPCIM (1, Y)
      GO TO 50
C CHECK IF ABS(X) .LT. 1
   10 IF (MPGET (X, 2) .GT. 0) GO TO 20
C USE MPEXP1 HERE
      T = T + MPGD (100)
      TG = T
      CALL MPNEW (I2)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPEXP1 (R(I2), R(I2))
      CALL MPADDI (R(I2), 1, R(I2))
      GO TO 40
C INCREASE T AS NECESSARY.
   20 RP = MAX0 (MPGET (X, 2), 0)
      T = T + 1 + RP + MPGD (100)
      TG = T
C USE TRUNCATION RATHER THAN ROUNDING INTERNALLY
      IF (R(SV+2) .EQ. 1) CALL MPSETR (0)
      CALL MPNEW (I2)
C MOVE X AND DIVIDE BY B**RP
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      R(I2+1) = R(I2+1) - RP
C USE EXP1 TO COMPUTE EXP(...) - 1
      CALL MPEXP1 (R(I2), R(I2))
      CALL MPADDI (R(I2), 1, R(I2))
C SEE IF RESULT ALREADY OBTAINED (RP .LE. 0)
      IF (RP.LE.0) GO TO 40
C HERE HAVE TO RAISE RESULT TO B-TH POWER RP TIMES
C UNDERFLOW/OVERFLOW WILL OCCUR HERE IF X OUT OF ALLOWABLE
C RANGE.
      DO 30 K = 1, RP
   30 CALL MPPWRA (R(I2), IABS(B), R(I2))
C ROUND RESULT TO TS DIGITS, RESTORE T ETC. AND RETURN
   40 CALL MPRND (R(I2), TG, Y, IABS(R(SV)), 0)
   50 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPEXPA  ******
      INTEGER FUNCTION MPEXPA (X)
C RETURNS THE EXPONENT OF THE PACKED OR UNPACKED MP NUMBER X
C (OR LARGE NEGATIVE EXPONENT -M IF X IS ZERO).
      INTEGER X(1), MPGET, MPPARN
C RETURN -M IF X ZERO, X(2) OTHERWISE
      MPEXPA = - MPPARN (3)
      IF (X(1) .NE. 0) MPEXPA = MPGET (X, 2)
      RETURN
      END
C $$                   ******  MPEXPB  ******
      SUBROUTINE MPEXPB (I, X)
C SETS EXPONENT OF PACKED OR UNPACKED MP NUMBER X TO I
C UNLESS X IS ZERO (WHEN EXPONENT IS UNCHANGED).
      COMMON /MPCOM/ B, T, M, DUMMY
      INTEGER B, DUMMY(20), I, M, T, TWO, X(1)
      TWO = 2
C RETURN IF X IS ZERO
      IF (X(1).EQ.0) RETURN
C SET EXPONENT OF X TO I
      X(TWO) = I
C UPDATE MXEXPN AND MNEXPN.
      CALL MPUPDT (I)
C CHECK FOR OVERFLOW AND UNDERFLOW
      IF (I.GT.M) CALL MPOVFL (X)
      IF (I.LE.(-M)) CALL MPUNFL (X)
      RETURN
      END
C $$                   ******  MPEXP1  ******
      SUBROUTINE MPEXP1 (X, Y)
C ASSUMES THAT X AND Y ARE MP NUMBERS,  -1 .LT. X .LT. 1.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C RETURNS Y = EXP(X) - 1 USING AN O(SQRT(T).M(T)) ALGORITHM
C DESCRIBED IN - R. P. BRENT, THE COMPLEXITY OF MULTIPLE-
C PRECISION ARITHMETIC (IN COMPLEXITY OF COMPUTATIONAL PROBLEM
C SOLVING, UNIV. OF QUEENSLAND PRESS, BRISBANE, 1976, 126-165).
C ASYMPTOTICALLY FASTER METHODS EXIST, BUT ARE NOT USEFUL
C UNLESS T IS VERY LARGE. SEE COMMENTS TO MPATAN AND MPPIGL.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, KTUNFL, DUMMY
      INTEGER I, I2, I3, I4, KTU, LA, MPGET, MPTLB, Q, SV, TG,
     $  B, DUMMY(11), KTUNFL, LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR,
     $  MXSPTR, R(1), RNDRL, SPTR, T, X(1), Y(1),
     $  LIM, MPPARN, MUL
C CHECK FOR X = 0
      Y(1) = X(1)
      IF (X(1) .EQ. 0) RETURN
C SAVE T, M ETC.
      CALL MPSAVN (SV)
C CHECK THAT ABS(X) .LT. 1
      IF (MPGET (X, 2) .GT. 0) CALL MPERRM (
     $  41HABS(X) NOT LESS THAN 1 IN CALL TO MPEXP1$)
C COMPUTE APPROXIMATELY OPTIMAL Q.
      Q = 0
      IF (MPGET (X, 2) .LT. (-T)) GO TO 30
      LA = MPTLB (T/3)
C INTEGER SQUARE ROOT APPROXIMATION HERE
   20 Q = Q + 1
      IF ((Q*Q) .LE. LA) GO TO 20
      Q = MAX0 (0, Q + MPGET (X, 2)*MPTLB(1))
C INCREASE T AS NECESSARY.
   30 CALL MPGD3 (Q, TG)
C ALLOCATE TEMPORARY SPACE
   40 CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
C USE TRUNCATION RATHER THAN ROUNDING INTERNALLY.
      IF (RNDRL.EQ.1) RNDRL = 0
C INCREASE M (TO AVOID UNDERFLOW PROBLEMS) AND MOVE X
      M = M + 2*T
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      KTU = KTUNFL
C HALVE Q TIMES
C CAN NOT USE MPSCAL HERE AS POTENTIALLY RECURSIVE
      IF (Q .LE. 0) GO TO 60
      LIM = MPPARN(16)/2
      MUL = 1
      DO 50 I = 1, Q
      MUL = 2*MUL
      IF ((MUL .LT. LIM) .AND. (MUL .NE. B) .AND.
     $  (I .NE. Q)) GO TO 50
      CALL MPDIVI (R(I2), MUL, R(I2))
      MUL = 1
   50 CONTINUE
C IF UNDERFLOW OCCURED SET Q = 0 AND TRY AGAIN WITH NEW T ETC.
      IF (KTU .EQ. KTUNFL) GO TO 60
      Q = 0
      CALL MPRESN (SV)
      CALL MPSAVN (SV)
      CALL MPGD3 (MPTLB(IABS(T)), TG)
      GO TO 40
   60 CALL MPSTR (R(I2), R(I4))
      CALL MPSTR (R(I2), R(I3))
      I = 1
      TG = T
C SUM SERIES, REDUCING T WHERE POSSIBLE
   70 T = TG + 2 + R(I3+1) - R(I4+1)
      IF (T.LE.2) GO TO 80
      T = MIN0 (T, TG)
      IF (RNDRL.NE.0) T = TG
      CALL MPMUL (R(I2), R(I3), R(I3))
      I = I + 1
      CALL MPDIVI (R(I3), I, R(I3))
      T = TG
      CALL MPADD (R(I3), R(I4), R(I4))
C CAN ONLY FALL THROUGH NEXT STATEMENT IF UNDERFLOW OCCURRED.
      IF (KTU.EQ.KTUNFL) GO TO 70
C RESTORE WORKING PRECISION
   80 T = TG
C CHECK IF ROUNDING UP REQUIRED
      IF (RNDRL.NE.3) GO TO 90
C ROUNDING UP HERE, SO ADD ABS(LAST TERM)
      R(I3) = IABS(R(I3))
      CALL MPADD (R(I3), R(I4), R(I4))
C FINISHED IF Q .LE. 0
   90 IF (Q.LE.0) GO TO 110
C APPLY (X+1)**2 - 1 = X(2 + X) FOR Q ITERATIONS
      DO 100 I = 1, Q
      CALL MPADDI (R(I4), 2, R(I2))
  100 CALL MPMUL (R(I2), R(I4), R(I4))
C ROUND RESULT
  110 CALL MPRND (R(I4), TG, Y, IABS(R(SV)), 0)
C RESTORE STACK POINTER ETC AND RETURN
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPFIN  ******
      SUBROUTINE MPFIN (LUNIT, X)
C READS MP X FROM UNIT LUNIT IN FREE FORMAT.
      COMMON R
      LOGICAL ERR
      INTEGER INRECL, I2, LUNIT, MPPARN, R(1), SV, X(1)
      CALL MPSAVN (SV)
      INRECL = MPPARN (18)
      CALL MPNEW2 (I2, INRECL)
C FORMAT (80A1) ASSUMES INRECL .LE. 80
      CALL MPIO (R(I2), INRECL, (-LUNIT), 6H(80A1), ERR)
      IF (ERR) CALL MPERR
      CALL MPIN (R(I2), X, INRECL, ERR)
      IF (ERR) CALL MPERRM (
     $  42HERROR RETURN FROM MPIN, CALLED FROM MPFIN$)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPFLOR  ******
      SUBROUTINE MPFLOR (X, Y)
C SETS Y = FLOOR (X), I.E. THE LARGEST INTEGER NOT EXCEEDING X.
C X AND Y ARE MP NUMBERS.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/
C (THIS IS ONLY RELEVANT IF X IS LARGE AND NEGATIVE) -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      INTEGER I2, MPCOMP, R(1), SV, X(1), Y(1)
C SAVE T ETC. AND TRUNCATE X (TOWARDS ZERO) TO AN INTEGER.
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPCMIM (X, R(I2))
C IF X NEGATIVE AND NOT AN INTEGER NEED TO SUBTRACT 1
      IF ((X(1).LT.0) .AND. (MPCOMP (X, R(I2)).NE.0))
     $          CALL MPADDI (R(I2), -1, R(I2))
C MOVE RESULT, RESTORE EVERYTHING AND RETURN.
      CALL MPSTR (R(I2), Y)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPFOUT  ******
      SUBROUTINE MPFOUT (X, N)
C
C FLOATING-POINT OUTPUT ROUTINE.  WRITES MP NUMBER X ON
C DEFAULT LOCICAL UNIT (LUN) IN FLOATING-POINT FORMAT WITH N
C SIGNIFICANT DECIMAL DIGITS, N .GE. 2.
C X MAY BE PACKED OR UNPACKED IF MPFOUT IS CALLED DIRECTLY.
C
C EXPONENT FIELD WIDTH IS DETERMINED BY EXWID - DEFAULT IS
C 6 (INCLUDING EXPONENT CHARACTER AND SIGN).
C
C EXPONENT CHARACTER IS DETERMINED BY EXPCH (DEFAULT IS E).
C
C OUTPUT BASE DEFAULTS TO 10, BUT MAY BE ANY INTEGER IN RANGE
C 2, ... , 16 (SEE COMMENT ON OUTBAS IN MPPARN).
C
C FOR ROUNDING OPTIONS SEE COMMENTS IN SUBROUTINE MPOUTE.
C
      COMMON R
      LOGICAL ERR, MPIS
      INTEGER E, FWIDTH, I, I2, I3, J, K, LAS, OUTBAS,
     $  SV, N, R(1), X(1), MPDIGW, MPPARN,
     $  DOLLAR, MINUS, PLUS, STAR
      DATA DOLLAR, MINUS, PLUS, STAR /1H$, 1H-, 1H+, 1H*/
C DO NOTHING IF N.LT.2
      IF (N.LT.2) RETURN
      CALL MPSAVN (SV)
C FIELD WIDTH IS EXWID + N + 2
      FWIDTH = MPPARN(17) + N + 2
      OUTBAS = MPPARN (20)
      E = MPPARN (21)
C CHANGE EXPONENT CHARACTER IF IT IS A DIGIT.
      DO 10 I = 1, OUTBAS
   10 IF (MPIS (E, MPDIGW(I-1))) E = DOLLAR
C ALLOCATE FWIDTH WORDS FOR WORKING SPACE, CHECK B, T ETC.
      CALL MPNEW2 (I2, FWIDTH)
C CONVERT TO PRINTABLE FORM.
      CALL MPOUTE (X, R(I2), J, N+2)
C SET UP EXPONENT IN CHARACTER FORM.
      I3 = I2 + N + 2
      R(I3) = E
      R(I3+1) = PLUS
      IF (J .LT. 0) R(I3+1) = MINUS
      J = IABS (J)
      LAS = I2 + FWIDTH - 3
C LOOP FOR EACH DIGIT OF EXPONENT
   20 K = MOD (J, OUTBAS)
      J = J/OUTBAS
      R(LAS+2) = MPDIGW(K)
      LAS = LAS - 1
      IF (LAS .GE. I3) GO TO 20
      IF (J .EQ. 0) GO TO 40
C HERE EXPONENT IS TOO LARGE TO FIT IN OUTPUT FIELD.
      LAS = I2 + FWIDTH - 3
      DO 30 I = I3, LAS
   30 R(I+2) = STAR
C CALL MPIO TO WRITE CHARACTER FORM OF X.
   40 CALL MPIO (R(I2), FWIDTH, MPPARN(4), 9H(1X,70A1), ERR)
      IF (ERR) CALL MPERRM (
     $  43HERROR RETURN FROM MPIO, CALLED FROM MPFOUT$)
C RESTORE STACK POINTER AND RETURN.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPGAM  ******
      SUBROUTINE MPGAM (X, Y)
C COMPUTES MP Y = GAMMA(X) FOR MP ARGUMENT X, USING
C MPGAMQ IF ABS(X) .LE. MXINT/240-1 AND 240*X IS AN INTEGER,
C OTHERWISE USING MPLNGM`.  SPACE REQUIRED IS O(T**2), SEE COMMENTS
C IN SUBROUTINE MPLNGM.  TIME = O(T**3).
C ROUNDING OPTIONS NOT IMPLEMENTED, USES NO GUARD DIGITS.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, DUMMY
      INTEGER IX, I2, I3, KT, N, SV,
     $  B, DUMMY(17), LUN, M, MXR, R(1), SPTR, T, X(1), Y(1),
     $  MPCMPI, MPCMPQ, MPGET, MPPARN, MPTLB
C SAVE T ETC., ALLOCATE TEMPORARY SPACE, USE TRUNCATION.
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPSETR (0)
      CALL MPABS (X, R(I3))
      IF (MPCMPI (R(I3), MPPARN(16)/240 - 1) .GT. 0) GO TO 20
C SEE IF 240*X IS ALMOST AN INTEGER.
      CALL MPMULI (X, 240, R(I3))
      CALL MPCMI (R(I3), IX)
C COMPARE WITH IX AND IX+1 BECAUSE R(I3) COULD BE JUST
C BELOW AN INTEGER.
      DO 10 KT = 1, 2
      CALL MPADDI (R(I3), -IX, R(I2))
      IF ((R(I2).EQ.0).OR.
     $    (((R(I3+1)-R(I2+1)).GE.(T-1)).AND.
     $     (R(I3+2).GE.R(I2+2)))) GO TO 30
   10 IX = IX + 1
C HERE X IS LARGE OR NOT SIMPLE RATIONAL,
C CHECK IF ABS(X) VERY SMALL.
      IF (MPGET (X, 2) .LE. (-T)) GO TO 90
C NOW CHECK SIGN OF X
   20 IF (X(1).LT.0) GO TO 40
C X IS POSITIVE SO USE MPLNGM DIRECTLY AFTER RELEASING SOME SPACE.
      SPTR = I2
      CALL MPLNGM (X, Y)
C SEE IF MPEXP WILL GIVE OVERFLOW
      CALL MPNEW (I2)
      CALL MPDIVI (Y, IABS(M), R(I2))
C LN(2) .LT. 7/10
      IF (MPCMPQ (R(I2), MPTLB(7), 10) .GE. 0) GO TO 70
C USUALLY SAFE TO CALL MPEXP HERE.
      CALL MPEXP (Y, Y)
      GO TO 100
C X = IX/240 SO USE MPGAMQ UNLESS X ZERO OR NEGATIVE INTEGER.
   30 IF ((IX.LE.0).AND.(MOD(IABS(IX), 240) .EQ. 0)) GO TO 50
      SPTR = I2
      CALL MPGAMQ (IX, 240, Y)
      GO TO 100
C HERE X IS NEGATIVE, SO USE REFLECTION FORMULA
   40 CALL MPABS  (X, Y)
C SUBTRACT EVEN INTEGER TO AVOID ERRORS NEAR POLES
      CALL MPDIVI (Y, 2, R(I3))
      CALL MPCMF (R(I3), R(I3))
      CALL MPMULI (R(I3), 2, R(I3))
      CALL MPADDQ (R(I3), 1, 2, R(I2))
      CALL MPCMI (R(I2), N)
C CHECK FOR INTEGER OVERFLOW IN MPCMI
      IF ((R(I3).NE.0).AND.(R(I3+1).GT.0).AND.(N.EQ.0)) GO TO 70
      CALL MPADDI (R(I3), -N, R(I3))
C NOW ABS(R(I3)) .LE. 1/2 AND SIGN DETERMINED BY N
      IF (R(I3).NE.0) GO TO 60
   50 CALL MPERRM (44HX ZERO OR NEGATIVE INTEGER IN CALL TO MPGAM$)
   60 CALL MPPI (R(I2))
      CALL MPMUL (R(I3), R(I2), R(I3))
      CALL MPSIN (R(I3), R(I3))
      CALL MPMUL (R(I3), Y, R(I3))
      IF (R(I3).EQ.0) GO TO 70
      CALL MPDIV (R(I2), R(I3), R(I2))
      R(I2) = -((-1)**N)*R(I2)
C RELEASE SOME SPACE BEFORE CALL TO MPLNGM.
      SPTR = I3
      CALL MPLNGM (Y, Y)
      Y(1) = -Y(1)
      CALL MPEXP (Y, Y)
      CALL MPMUL (Y, R(I2), Y)
      GO TO 100
C HERE X WAS TOO LARGE OR TOO CLOSE TO A POLE
   70 WRITE (LUN, 80)
   80 FORMAT (26H *** OVERFLOW IN MPGAM ***)
      CALL MPOVFL (Y)
      GO TO 100
C HERE ABS(X) IS VERY SMALL
   90 CALL MPREC (X, Y)
C RESTORE EVERYTHING AND RETURN.
  100 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPGAMQ  ******
      SUBROUTINE MPGAMQ (I, J, X)
C RETURNS X = GAMMA (I/J) WHERE X IS MULTIPLE-PRECISION AND
C I, J ARE SMALL INTEGERS.   THE METHOD USED IS REDUCTION OF
C THE ARGUMENT TO (0, 1) AND THEN A DIRECT
C EXPANSION OF THE DEFINING INTEGRAL TRUNCATED AT A
C SUFFICIENTLY HIGH LIMIT, USING 2T DIGITS TO
C COMPENSATE FOR CANCELLATION.
C TIME IS O(T**2) IF I/J IS NOT TOO LARGE.
C IF I/J .GT. 100 (APPROXIMATELY) IT IS FASTER TO USE
C MPGAM (IF ENOUGH SPACE IS AVAILABLE).
C MPGAMQ IS VERY SLOW IF I/J IS VERY LARGE, BECAUSE
C THE RELATION GAMMA(X+1) = X*GAMMA(X) IS USED REPEATEDLY.
C MPGAMQ COULD BE SPEEDED UP BY USING THE ASYMPTOTIC SERIES OR
C CONTINUED FRACTION FOR (INTEGRAL FROM N TO INFINITY OF
C U**(I/J-1)*EXP(-U)DU).
C ROUNDING OPTIONS NOT YET IMPLEMENTED.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER IBTN, ID, IJ, IL, IN, IS, IS2, I2, I3, JS, MXINT, N, SV
      INTEGER B, DUMMY(21), I, J, R(1), T, TS2, TS3, X(1)
      INTEGER MPCHGB, MPPARN, MPTLB
C SAVE T ETC.
      CALL MPSAVN (SV)
C USE TRUNCATED ARITHMETIC.
      CALL MPSETR (0)
      MXINT = MPPARN (16)
      IF (J .EQ. 0) CALL MPERRM (24HJ = 0 IN CALL TO MPGAMQ$)
C Bug reported 890208 by Z Liu - replace
C     IS = ISIGN (I, J)
C by the following line (else sign of I is ignored)
      IS = I*ISIGN (1, J)
C end of bug report
      JS = IABS (J)
C NOW JS IS POSITIVE.  REDUCE TO LOWEST TERMS.
      CALL MPGCD (IS, JS)
      IJ = MXINT/JS
C SEE IF JS = 1, 2, OR .GT. 2
      IF (JS - 2) 20, 10, 40
C JS = 2 HERE, FOR SPEED TREAT AS SPECIAL CASE
   10 CALL MPPI (X)
      CALL MPSQRT (X, X)
      GO TO 30
C JS = 1 HERE, CHECK THAT IS IS POSITIVE
   20 IF (IS .LE. 0) CALL MPERRM (
     $  39HI/J ZERO OR NEGATIVE IN CALL TO MPGAMQ$)
C I/J = POSITIVE INTEGER HERE
      CALL MPCIM (1, X)
   30 IS2 = 1
      GO TO 60
C JS .GT. 2 HERE SO REDUCE TO (0, 1)
   40 IS2 = MOD (IS, JS)
      IF (IS2.LT.0) IS2 = IS2 + JS
C NOW 0 .LT. IS2 .LT. JS.   COMPUTE UPPER LIMIT OF INTEGRAL
C N .GE. T*LN(B)
      N = MPTLB ((7*T + 9)/10)
      IBTN = MXINT/N
      TS3 = T + 2
C INCREASE T TO COMPENSATE FOR CANCELLATION
C INCREASE .GE. N/LN(B)
      T = T + MPCHGB (IABS(B), 2, (3*N+1)/2)
      TS2 = T
C ALLOCATE TEMPORARY SPACE
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPCIM (N, R(I2))
      CALL MPSTR (R(I2), R(I3))
      IL = 0
      IN = JS - IS2
      ID = IS2
C MAIN LOOP
   50 IL = IL + 1
C IF TERMS DECREASING MAY DECREASE T
      IF (IL.GE.N) T = R(I3+1) + TS3
      T = MAX0 (2, MIN0 (T, TS2))
C CHECK IF IN-JS OR ID+JS MIGHT OVERFLOW.
      IF (MAX0 (IABS(IN), ID) .GT. (MXINT-JS)) GO TO 70
      IN = IN - JS
      ID = ID + JS
      CALL MPMULS (R(I3), N, IN, IL, ID)
      T = MAX0 (T, TS3)
      CALL MPADD (R(I2), R(I3), R(I2))
C LOOP UNTIL EXPONENT SMALL
      IF ((R(I3).NE.0).AND.(R(I3+1).GE.(-R(SV)))) GO TO 50
C RESTORE T
      T = R(SV)
      CALL MPMULQ (R(I2), JS, IS2, X)
      CALL MPQPWR (N, 1, IS2-JS, JS, R(I3))
      CALL MPMUL (X, R(I3), X)
C NOW X IS GAMMA (IS2/JS), SO USE THE RECURRENCE RELATION
C REPEATEDLY TO GET GAMMA (I/J)  (SLOW IF I/J IS LARGE).
   60 IN = 1
      ID = 1
      IF (IS - IS2) 100, 110, 80
C J MUST HAVE BEEN TOO LARGE.
   70 CALL MPERRM (30HJ TOO LARGE IN CALL TO MPGAMQ$)
C RESTORE T ETC. AND RETURN.
  110 CALL MPRESN (SV)
      RETURN
   80 IN = IN*IS2
      ID = ID*JS
      IS2 = IS2 + JS
      IF ((ID.LE.IJ).AND.(IABS(IN).LE.(MXINT/IABS(IS2)))
     $   .AND.(IS.NE.IS2)) GO TO 80
   90 CALL MPMULQ (X, IN, ID, X)
      GO TO 60
  100 IN = IN*JS
      ID = ID*IS
      IS = IS + JS
      IF ((IN.LE.IJ).AND.(IABS(ID).LE.(MXINT/IABS(IS)))
     $   .AND.(IS.NE.IS2)) GO TO 100
      GO TO 90
      END
C $$                   ******  MPGCD  ******
      SUBROUTINE MPGCD (K, L)
C RETURNS K = K/GCD AND L = L/GCD, WHERE GCD IS THE
C GREATEST COMMON DIVISOR OF K AND L.
C SAVE INPUT PARAMETERS IN LOCAL VARIABLES
      INTEGER I, IS, J, JS, K, L
      I = K
      J = L
      IS = IABS(I)
      JS = IABS(J)
      IF (JS.EQ.0) GO TO 30
C EUCLIDEAN ALGORITHM LOOP
   10 IS = MOD (IS, JS)
      IF (IS.EQ.0) GO TO 20
      JS = MOD (JS, IS)
      IF (JS.NE.0) GO TO 10
      JS = IS
C HERE JS IS THE GCD OF I AND J
   20 K = I/JS
      L = J/JS
      RETURN
C IF J = 0 RETURN (1, 0) UNLESS I = 0, THEN (0, 0)
   30 K = 1
      IF (IS.EQ.0) K = 0
      L = 0
      RETURN
      END
C $$                   ******  MPGCDA  ******
      SUBROUTINE MPGCDA (X, Y, Z)
C RETURNS Z = GREATEST COMMON DIVISOR OF X AND Y.
C GCD (X, 0) = GCD (0, X) = ABS(X), GCD (X, Y) .GE. 0.
C X, Y AND Z ARE INTEGERS REPRESENTED AS MP NUMBERS,
C AND MUST SATISFY ABS(X) .LT. B**T, ABS(Y) .LT. B**T
C X AND/OR Y MAY BE PACKED OR UNPACKED, Z IS UNPACKED.
C TIME O(T**2).  THE PARAMETER RNDRL IS IRRELEVANT AS RESULT EXACT.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, IQ, IS, I2, I3, I4, J, SV
      INTEGER B, DUMMY(21), MPCMP, R(1), T, X(1), Y(1), Z(1)
      LOGICAL MPINTG
C SAVE T ETC., ALLOCATE WORKING SPACE, USE TRUNCATED ARITHMETIC.
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPSETR (0)
      CALL MPUNPK (X, R(I2))
      CALL MPUNPK (Y, R(I3))
      R(I2) = IABS (R(I2))
      R(I3) = IABS (R(I3))
C CHECK THAT X AND Y ARE EXACT INTEGERS
      IF (.NOT. (MPINTG (R(I2)) .AND. MPINTG (R(I3))))
     $  CALL MPERRM (37HX OR Y NON-INTEGER IN CALL TO MPGCDA$)
C CHECK FOR X OR Y ZERO
      IF (X(1).NE.0) GO TO 20
   10 T = R(SV)
      CALL MPSTR (R(I3), Z)
      GO TO 140
   20 IF (Y(1).NE.0) GO TO 30
      CALL MPSTR (R(I2), Z)
      GO TO 140
C CHECK THAT ABS(X), ABS(Y) .LT. B**T
   30 IF (MAX0 (R(I2+1), R(I3+1)) .GT. T) CALL MPERRM (
     $  35HX OR Y TOO LARGE IN CALL TO MPGCDA$)
C START OF MAIN EUCLIDEAN ALGORITHM LOOP
   60 IF (R(I2).EQ.0) GO TO 10
      IF (MPCMP (R(I2), R(I3))) 70, 10, 80
C EXCHANGE POINTERS ONLY
   70 IS = I2
      I2 = I3
      I3 = IS
C CHECK FOR SMALL EXPONENT
   80 IF (R(I2+1).LE.2) GO TO 110
C REDUCE T (TRAILING DIGITS MUST BE ZERO)
      T = R(I2+1)
      CALL MPSTR (R(I3), R(I4))
C FORCE EXPONENTS TO BE EQUAL
      R(I4+1) = R(I2+1)
C GET FIRST TWO DIGITS
      IQ = B*R(I2+2) + R(I2+3)
      IF (MPCMP (R(I2), R(I4)) .GE. 0) GO TO 90
C REDUCE EXPONENT BY ONE
      R(I4+1) = R(I4+1) - 1
C UNDERESTIMATE QUOTIENT
      IQ = IQ/(R(I4+2)+1)
      GO TO 100
C LEHMERS METHOD WOULD SAVE SOME MP OPERATIONS BUT NOT VERY
C MANY UNLESS WE COULD USE DOUBLE-PRECISION SAFELY.
C SEE AMERICAN MATH. MONTHLY 45 (1938), 227 - 233.
   90 IQ = MAX0 (1, IQ/(B*R(I4+2) + R(I4+3) + 1))
  100 CALL MPMULI (R(I4), IQ, R(I4))
      CALL MPSUB (R(I2), R(I4), R(I2))
      GO TO 60
C HERE SAFE TO USE INTEGER ARITHMETIC
  110 CALL MPCMI (R(I2), I)
      CALL MPCMI (R(I3), J)
      T = R(SV)
  120 I = MOD (I, J)
      IF (I.EQ.0) GO TO 130
      J = MOD (J, I)
      IF (J.NE.0) GO TO 120
      J = I
  130 CALL MPCIM (J, Z)
C RESTORE EVERYTHING AND RETURN.
  140 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPGCDB  ******
      SUBROUTINE MPGCDB (X, Y)
C RETURNS (X, Y) AS (X/Z, Y/Z) WHERE Z IS THE GCD OF X AND Y.
C X AND Y ARE INTEGERS REPRESENTED AS MP NUMBERS,
C AND MUST SATISFY ABS(X) .LT. B**T, ABS(Y) .LT. B**T
C TIME O(T**2). THE PARAMETER RNDRL IS IRRELEVANT AS RESULT IS EXACT.
      COMMON R
      INTEGER IS, IZ, I2, SV
      INTEGER R(1), X(1), Y(1)
      INTEGER MPCMPI, MPCOMP, MPPARN
C SAVE T ETC., USE TRUNCATED ARITH., ALLOCATE TEMPORARY SPACE.
      CALL MPSAVN (SV)
      CALL MPSETR (0)
      CALL MPNEW (I2)
C FIND GCD OF X AND Y USING MPGCDA
      CALL MPGCDA (X, Y, R(I2))
C CHECK FOR X AND Y EQUAL (WHEN MAY COINCIDE)
      IF (MPCOMP (X, Y) .NE. 0) GO TO 10
      IS = X(1)
      CALL MPCIM (IS, X)
      CALL MPSTR (X, Y)
      GO TO 30
C CHECK IF GCD IS SMALL.
   10 IF (MPCMPI (R(I2), MPPARN (16)) .GT. 0) GO TO 20
C HERE IT IS SAFE TO CONVERT GCD TO SINGLE-PRECISION INTEGER.
      CALL MPCMI (R(I2), IZ)
      IF (IZ.EQ.1) GO TO 30
      CALL MPDIVI (X, IZ, X)
      CALL MPDIVI (Y, IZ, Y)
      GO TO 30
C HERE GCD IS LARGE.
   20 CALL MPDIV (X, R(I2), X)
      CALL MPDIV (Y, R(I2), Y)
C RESTORE EVERYTHING AND RETURN.
   30 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPGD  ******
      INTEGER FUNCTION MPGD (N)
C RETURNS CEILING (LN (MAX (1, ABS(N))) / LN(B)),
C I.E. THE MINIMUM VALUE OF J .GE. 0 SUCH THAT
C     B**J .GE. ABS(N) .
C THIS FUNCTION IS USEFUL FOR COMPUTING THE NUMBER OF GUARD DIGITS
C REQUIRED FOR VARIOUS MULTIPLE-PRECISION CALCULATIONS.
      COMMON /MPCOM/ B, DUMMY
      INTEGER B, DUMMY(22), J, K, N
C CHECK THAT B IS LEGAL.
      IF (B.LT.2) CALL MPCHK
C SET UP LOOP
      J = 0
      K = IABS(N) - 1
      GO TO 20
C LOOP TO COMPUTE RESULT
   10 J = J + 1
      K = K/B
   20 IF (K.GT.0) GO TO 10
C RETURN RESULT J
      MPGD = J
      RETURN
      END
C $$                   ******  MPGD3  ******
      SUBROUTINE MPGD3 (N, TG)
C SETS T = T + 1 + MPGD (100*N) IF SAFE TO CALL
C MPGD, EFFECTIVELY ALMOST THE SAME IF NOT.
C ALSO SETS TG = NEW VALUE OF T.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, DUMMY(21), I, MPGD, MPPARN, N, T, TG
C CHECK WHETHER SAFE TO FORM 100*N
      IF (IABS(N) .GE. (MPPARN(16)/100)) GO TO 10
C HERE IT IS
      I = MPGD (100*N)
      GO TO 20
C HERE IT IS NOT, SO CALL MPGD TWICE
   10 I = MPGD (N) + MPGD (100)
C SET T AND TG
   20 T = T + I + 1
      TG = T
      RETURN
      END
C $$                   ******  MPGE  ******
      LOGICAL FUNCTION MPGE (X, Y)
C RETURNS LOGICAL VALUE OF (X .GE. Y) FOR MP X AND Y.
C X AND/OR Y MAY BE PACKED OR UNPACKED.
      INTEGER MPCOMP, X(1), Y(1)
      MPGE = (MPCOMP(X,Y) .GE. 0)
      RETURN
      END
C $$                   ******  MPGET  ******
      INTEGER FUNCTION MPGET (X, N)
C RETURNS X(N).  NECESSARY TO AVOID SOME COMPILER DIAGNOSTICS.
C ALSO USEFUL TO AVOID PFORT VERIFIER UNSAFE REFERENCE WARNINGS.
      INTEGER N, X(1)
      MPGET = X(N)
      RETURN
      END
C $$                   ******  MPGT  ******
      LOGICAL FUNCTION MPGT (X, Y)
C RETURNS LOGICAL VALUE OF (X .GT. Y) FOR MP X AND Y.
C X AND/OR Y MAY BE PACKED OR UNPACKED.
      INTEGER MPCOMP, X(1), Y(1)
      MPGT = (MPCOMP(X,Y) .GT. 0)
      RETURN
      END
C $$                   ******  MPHANK  ******
      SUBROUTINE MPHANK (X, NU, Y, ERROR)
C TRIES TO COMPUTE THE BESSEL FUNCTION J(NU,X) USING HANKELS
C ASYMPTOTIC SERIES.  NU IS A NONNEGATIVE INTEGER NOT TOO LARGE.
C ERROR IS LOGICAL, X AND Y ARE MP NUMBERS.
C RETURNS ERROR = .FALSE. IF SUCCESSFUL (RESULT IN Y),
C         ERROR = .TRUE.  IF UNSUCCESSFUL (Y UNCHANGED)
C TIME = O(T**3).
C CALLED BY MPBESJ, NOT RECOMMENDED FOR INDEPENDENT USE.
C ROUNDING OPTIONS NOT IMPLEMENTED, USES NO GUARD DIGITS.
      COMMON R
      INTEGER IE, I2, I3, I4, I5, I6, I7, K, LG, SV
      INTEGER NU, R(1), X(1), Y(1)
      INTEGER MPCMPI, MPPARN, MPTLB
      LOGICAL ERROR
C SAVE T ETC., USE TRUNCATION INTERNALLY.
      CALL MPSAVN (SV)
      CALL MPSETR (0)
      ERROR = .TRUE.
C GIVE ERROR RETURN IF NU IS NEGATIVE.
      IF (NU.LT.0) GO TO 20
C ALLOCATE TEMPORARY SPACE.
      CALL MPNEW (I2)
C WORK WITH ABS(X)
      CALL MPABS (X, R(I2))
C CHECK IF ABS(X) CLEARLY TOO SMALL FOR ASYMPTOTIC SERIES
      IF (MPCMPI (R(I2), MPTLB(IABS(R(SV)))/3) .LE. 0) GO TO 20
C ALLOCATE MORE TEMPORARY SPACE.
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPNEW (I5)
      CALL MPNEW (I6)
      CALL MPNEW (I7)
      CALL MPPWR (X, -2, R(I3))
      CALL MPDIVI (R(I3), -64, R(I3))
      CALL MPCIM (1, R(I4))
      R(I5) = 0
      CALL MPSTR (R(I4), R(I6))
      IE = 1
      K = 0
      LG = MPPARN(16)/2
C LOOP TO SUM TWO ASYMPTOTIC SERIES
   10 K = K + 2
C RETURN WITH ERROR = .TRUE. IF K TOO LARGE.
      IF ((NU+K) .GE. LG) GO TO 20
C ERROR RETURN IF TERMS INCREASING
      IF (R(I6+1).GT.IE) GO TO 20
      IE = R(I6+1)
      CALL MPMULS (R(I6), 2*(NU+K)-3, 2*(NU-K)+3, K-1, 1)
      CALL MPADD (R(I5), R(I6), R(I5))
      CALL MPMULS (R(I6), 2*(NU+K)-1, 2*(NU-K)+1, K, 1)
      CALL MPMUL (R(I6), R(I3), R(I6))
      CALL MPADD (R(I4), R(I6), R(I4))
C LOOP IF TERMS NOT SUFFICIENTLY SMALL YET
      IF ((R(I6).NE.0).AND.(R(I6+1).GT.(-R(SV)))) GO TO 10
C END OF ASYMPTOTIC SERIES, NOW COMPUTE RESULT
      CALL MPDIV (R(I5), R(I2), R(I5))
      CALL MPDIVI (R(I5), 8, R(I5))
C COMPUTE PI/4 (SLIGHTLY MORE ACCURATE THAN CALLING
C MPPI AND DIVIDING BY FOUR)
      CALL MPART1 (5, R(I6))
      CALL MPMULI (R(I6), 4, R(I6))
      CALL MPART1 (239, R(I3))
      CALL MPSUB (R(I6), R(I3), R(I3))
C AVOID TOO MUCH CANCELLATION IN SUBTRACTING MULTIPLE OF PI
      CALL MPMULI (R(I3), MOD (2*NU+1, 8), R(I6))
      CALL MPSUB (R(I2), R(I6), R(I6))
      CALL MPCIS (R(I6), R(I6), R(I7), .TRUE.)
      CALL MPMUL (R(I4), R(I6), R(I4))
      CALL MPMUL (R(I5), R(I7), R(I5))
      CALL MPSUB (R(I4), R(I5), R(I4))
      CALL MPMUL (R(I3), R(I2), R(I3))
      CALL MPMULI (R(I3), 2, R(I3))
      CALL MPROOT (R(I3), -2, R(I3))
      CALL MPMUL (R(I3), R(I4), R(I3))
C CORRECT SIGN OF RESULT
      IF (MOD (NU, 2) .NE. 0) R(I3) = R(I3)*X(1)
      ERROR = .FALSE.
      CALL MPSTR (R(I3), Y)
C RESTORE EVERYTHING AND RETURN
   20 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPIMUL  ******
      SUBROUTINE MPIMUL (IX, Y, Z)
C MULTIPLIES SINGLE-PRECISION INTEGER IX BY MP Y GIVING MP Z.
C ROUNDING DEFINED BY PARAMETER RNDRL IN COMMON /MPCOM/ -
C SEE SUBROUTINE MPNZR.
      INTEGER IX, Y(1), Z(1)
      CALL MPMULI (Y, IX, Z)
      RETURN
      END
C $$                   ******  MPIN  ******
      SUBROUTINE MPIN (C, X, N, ERROR)
C
C CONVERTS THE DECIMAL NUMBER (READ UNDER NA1 FORMAT)
C IN C(1) ... C(N) TO A MULTIPLE-PRECISION NUMBER
C IN X.   IF C REPRESENTS A VALID NUMBER, ERROR IS RETURNED
C AS .FALSE.  IF C DOES NOT REPRESENT A VALID NUMBER, ERROR
C IS RETURNED AS .TRUE. AND X AS ZERO.
C LEADING AND TRAILING BLANKS ARE ALLOWED, EMBEDDED BLANKS
C (EXCEPT BETWEEN THE NUMBER AND ITS SIGN) ARE FORBIDDEN.
C IF THERE IS NO DECIMAL POINT ONE IS ASSUMED TO LIE JUST TO
C THE RIGHT OF THE LAST DECIMAL DIGIT.
C
C NUMBERS MAY HAVE DECIMAL EXPONENTS, PROVIDED TWICE THE
C EXPONENT IS REPRESENTABLE AS A SINGLE-PRECISION INTEGER.
C THE EXPONENT MAY BE PRECEEDED BY ANY CHARACTER EXCEPT A
C DIGIT, BLANK OR PERIOD.  THE EXPONENT HAS AN OPTIONAL SIGN,
C AND THE SPECIAL CHARACTER PRECEEDING IT MAY BE OMITTED IF A
C SIGN IS PRESENT.
C
C EXAMPLES -
C
C       VALID NUMBERS              INVALID NUMBERS
C
C   -   123456789                    12 345
C     3.14159                       123.456E -67
C    -44.                             1.2.3
C  .0001234                            E123
C  123.456D789                         64.4E+
C -.1234566-789                      ++12.3
C   +999+88                           11E3.
C
C FOR EFFICIENCY CHOOSE B A POWER OF 10.
C X IS AN MP NUMBER, C AN INTEGER ARRAY, N INTEGER, ERROR LOGICAL.
C
C ROUNDING DETERMINED BY RNDRL IN COMMON /MPCOM/ AS FOLLOWS -
C
C   RNDRL = 0 OR 1 - ROUND TO (APPROXIMATELY) NEAREST REPRESENTABLE
C                    BASE B, T-DIGIT NUMBER.  ERROR IS LESS THAN
C                    0.6 UNITS IN THE LAST (BASE B) PLACE.
C   RNDRL = 2      - ROUND DOWN (TOWARDS -INFINITY) TO A BASE B,
C                    T-DIGIT NUMBER.
C   RNDRL = 3      - ROUND UP (TOWARDS +INFINITY) TO A BASE B,
C                    T-DIGIT NUMBER.
C
C THE DEFAULT INPUT BASE IS 10 (I.E. DECIMAL NUMBERS), BUT
C ANY BASE IN THE RANGE 2, ... , 16 MAY BE USED.  THE BASE IS
C DETERMINED BY THE PARAMETER INBASE IN COMMON /MPCOM/ -
C SEE MPPARN AND MPSET.
C
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER EX, I, IB, INBASE, IP, I2, J, K, MXINT, S, SEX, SV, TG,
     $  B, C(1), DUMMY(21), N, R(1), T, X(1),
     $  MPDIGV, MPGD, MPPARN, BLANK, MINUS, PERIOD, PLUS
      LOGICAL DE, DF, ERROR, FIRST, MPIS, POINT, SECOND
      DATA BLANK, MINUS, PERIOD, PLUS /1H , 1H-, 1H., 1H+/
C SAVE T ETC.
      CALL MPSAVN (SV)
      MXINT = MPPARN (16)
C GET INPUT BASE (DEFAULT SET BY MPSET IS 10).
      INBASE = MPPARN (19)
C CHECK THAT 2 .LE. INBASE .LE. 16   AND  N .GT. 0.
      IF ((2 .GT. INBASE) .OR. (INBASE .GT. 16) .OR. (N.LE.0)) GO TO 30
C INCREASE T AS NECESSARY, ALLOCATE TEMPORARY SPACE.
      T = T + MPGD (MXINT)
      CALL MPGD3 (N, TG)
      CALL MPNEW (I2)
C USE TRUNCATION RATHER THAN ROUNDING INTERNALLY.
      IF (R(SV+2) .EQ. 1) CALL MPSETR (0)
      FIRST = .TRUE.
      SECOND = .FALSE.
      R(I2) = 0
      S = 1
      ERROR = .FALSE.
      DE = .FALSE.
      DF = .TRUE.
      POINT = .FALSE.
      IP = 0
      K = 0
      EX = 0
      SEX = 1
      IB = MXINT/(2*INBASE)
C SCAN C FROM LEFT, SKIPPING BLANKS
   10 K = K + 1
      IF (.NOT. MPIS (C(K), BLANK)) GO TO 60
   20 IF (K.LT.N) GO TO 10
C ERROR HERE.
   30 X(1) = 0
      ERROR = .TRUE.
C RESTORE EVERYTHING AND RETURN.
   40 CALL MPRESN (SV)
      RETURN
C SIGN HERE.
   50 IF (.NOT. FIRST) GO TO 130
      IF (MPIS (C(K), MINUS)) S = -1
C TAKE CARE FOR DIRECTED ROUNDINGS.
      CALL MPREVR (-S)
      FIRST = .FALSE.
      GO TO 20
C SCAN NUMBER BEFORE EXPONENT FIELD.
   60 IF (MPIS (C(K), MINUS) .OR. MPIS (C(K), PLUS)) GO TO 50
      FIRST = .FALSE.
      J = MPDIGV (C(K))
      IF (J .GE. 0) GO TO 80
C NOT SIGN OR DIGIT HERE.
      IF (.NOT. MPIS (C(K), PERIOD)) GO TO 70
      IF (POINT) GO TO 30
      POINT = .TRUE.
      GO TO 90
   70 IF (MPIS (C(K), BLANK)) GO TO 100
C MUST BE EXPONENT INDICATOR
      GO TO 140
C DIGIT, SO CONTINUE FORMING NUMBER
   80 CALL MPMULI (R(I2), INBASE, R(I2))
      CALL MPADDI (R(I2), J, R(I2))
      DF = .FALSE.
      IF (POINT) IP = IP + 1
   90 K = K + 1
      IF (K .LE. N) GO TO 60
C CHECK THAT AT LEAST ONE DIGIT BEFORE EXPONENT, AND AT LEAST
C ONE DIGIT IN EXPONENT (IF PRESENT).
  100 IF (DE .OR. DF) GO TO 30
      IF (K .GT. N) GO TO 120
C CHECK THAT ALL CHARACTERS TO RIGHT ARE BLANKS
      DO 110 I = K, N
      IF (.NOT. MPIS (C(I), BLANK)) GO TO 30
  110 CONTINUE
C END OF INPUT FIELD, SCALE APPROPRIATELY.
  120 CALL MPSCAL (R(I2), INBASE, EX*SEX - IP)
C ROUND RESULT AND FIX UP SIGN.
      CALL MPRND (R(I2), TG, X, IABS(R(SV)), 0)
      X(1) = S*X(1)
      GO TO 40
C DEAL WITH SIGN OF EXPONENT
  130 IF (SECOND) GO TO 30
      SECOND = .TRUE.
      IF (MPIS (C(K), MINUS)) SEX = -1
C EXPONENT FOLLOWS.
  140 DE = .TRUE.
  150 K = K + 1
      IF (K.GT.N) GO TO 100
      IF (MPIS (C(K), PLUS) .OR. MPIS (C(K), MINUS)) GO TO 130
      SECOND = .TRUE.
      J = MPDIGV (C(K))
      IF (J .LT. 0) GO TO 100
C CHECK IF EXPONENT TOO LARGE
      IF (EX.GE.IB) GO TO 30
C OTHERWISE INCORPORATE NEXT DIGIT
      EX = INBASE*EX + J
      DE = .FALSE.
      GO TO 150
      END
C $$                   ******  MPINE  ******
      SUBROUTINE MPINE (C, X, N, J, ERROR)
C SAME AS MPIN EXCEPT THAT X IS MULTIPLIED BY INBASE**J.
C THE DEFAULT VALUE OF INBASE IS TEN, BUT THIS MAY BE CHANGED
C (SEE COMMENTS IN MPPARM).
      INTEGER C(1), J, MPPARN, N, X(1)
      LOGICAL ERROR
      CALL MPIN (C, X, N, ERROR)
      CALL MPSCAL (X, MPPARN (19), J)
      RETURN
      END
C $$                   ******  MPINF  ******
      SUBROUTINE MPINF (X, N, UNIT, IFORM, ERR)
C READS N WORDS FROM LOGICAL UNIT IABS(UNIT) USING FORMAT IN IFORM,
C THEN CONVERTS TO MP NUMBER X USING ROUTINE MPIN.
C IFORM SHOULD CONTAIN A FORMAT WHICH ALLOWS FOR READING N WORDS
C IN A1 FORMAT, E.G. 6H(80A1)
C ERR RETURNED AS TRUE IF MPIN COULD NOT INTERPRET INPUT AS
C AN MP NUMBER OR IF N NOT POSITIVE, OTHERWISE FALSE.
C (SEE ALSO COMMENTS IN MPIO.)
C IF ERR IS TRUE THEN X IS RETURNED AS ZERO.
C SPACE REQUIRED = N + O(T) WORDS.
C FOR ROUNDING OPTIONS SEE COMMENTS IN MPIN.
      COMMON R
      INTEGER IFORM(1), I2, N, R(1), SV, UNIT, X(1)
      LOGICAL ERR
      CALL MPSAVN (SV)
C ALLOCATE N WORDS ON STACK.
      CALL MPNEW2 (I2, N)
C READ N WORDS UNDER FORMAT IFORM.
      CALL MPIO (R(I2), N, (-UNIT), IFORM, ERR)
      X(1) = 0
C CONVERT TO MP NUMBER UNLESS READ ERROR
      IF (.NOT. ERR) CALL MPIN (R(I2), X, N, ERR)
C RESTORE STACK POINTER AND RETURN.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPINIT  ******
      SUBROUTINE MPINIT (X)
C
C DECLARES BLANK COMMON AND COMMON /MPCOM/ (USED BY MP PACKAGE) AND
C CALLS MPSET2 TO INITIALIZE PARAMETERS.  X IS A DUMMY INTEGER ARGUMENT.
C THE AUGMENT DECLARATION
C       INITIALIZE MP
C CAUSES A CALL TO MPINIT(MP) TO BE GENERATED.
C
C *** ASSUMES OUTPUT UNIT 6, 43 DECIMAL PLACES, MAXIMUM OF
C *** 25 MP DIGITS, WORKING SPACE 500 WORDS.  IF THE AUGMENT
C *** DESCRIPTION DECK IS CHANGED THIS ROUTINE SHOULD
C *** BE CHANGED ACCORDINGLY, AND VICE VERSA.
C *** IF WORDLENGTH IS GREATER THAN 16 BITS, SPACE CAN BE SAVED AS
C *** LESS THAN 25 MP DIGITS WILL BE REQUIRED FOR 43 DECIMAL PLACE
C *** ACCURACY.
      COMMON R
      COMMON /MPCOM/ MPPARS
      INTEGER X(1), MPPARS(23)
C
C THE STATEMENTS
      INTEGER R(500)
      CALL MPSET2 (6, 43, 27, 1, 500)
C ARE A SPECIAL CASE OF
C     INTEGER R(MXR)
C     CALL MPSET2 (LUN, DECPL, T+2, MNSPTR, MXR)
C WHERE
C LUN IS THE LOGICAL UNIT FOR OUTPUT,
C DECPL IS THE EQUIVALENT NUMBER OF DECIMAL PLACES REQUIRED,
C T IS THE NUMBER OF MP DIGITS, AND
C THE WORKING AREA FREE FOR USE BY MP IS WORDS
C MNSPTR, MNSPTR+1, ... , MXR OF BLANK COMMON.
C
C TO CHANGE THE PRECISION, MODIFY THE DIMENSIONS IN THE
C DECLARE STATEMENTS IN THE AUGMENT DESCRIPTION DECK -
C THE DIMENSION (MT2) FOR TYPE MULTIPLE SHOULD BE AT LEAST T+2, AND
C FOR TYPE MULTIPAK SHOULD BE EXACTLY INT ((MT2+1)/2).
C SEE FUNCTION MPDIGS FOR THE NUMBER OF MP DIGITS REQUIRED TO GIVE
C THE EQUIVALENT OF ANY DESIRED NUMBER OF FLOATING DECIMAL PLACES.
C
C *** ON SOME SYSTEMS A DECLARATION OF BLANK COMMON AND COMMON /MPCOM/
C *** IN THE MAIN PROGRAM MAY BE NECESSARY.  IF SO, DECLARE
C ***       COMMON MPWORK
C ***       COMMON /MPCOM/ MPPARS
C ***       INTEGER MPWORK (500), MPPARS (23)
C *** (OR, MORE GENERALLY,
C ***       INTEGER MPWORK (MXR), MPPARS (23)        )
C *** IN THE MAIN PROGRAM.
      RETURN
      END
C $$                   ******  MPINTG  ******
      LOGICAL FUNCTION MPINTG (X)
C RETURNS .TRUE. IF THE MP NUMBER X IS AN EXACT INTEGER,
C         .FALSE.  OTHERWISE.
      COMMON R
      INTEGER I2, R(1), SV, X(1)
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPCMF (X, R(I2))
      MPINTG = (R(I2) .EQ. 0)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPIO  ******
      SUBROUTINE MPIO (C, N, UNIT, IFORM, ERR)
C
C IF UNIT .GT. 0 WRITES C(1), ... , C(N) IN FORMAT IFORM
C IF UNIT .LE. 0 READS  C(1), ... , C(N) IN FORMAT IFORM
C IN BOTH CASES USES LOGICAL UNIT IABS(UNIT).
C IF IFORM = 1HU THEN UNFORMATTED I/O IS PERFORMED.
C
C ERR IS RETURNED AS TRUE IF N NON-POSITIVE, OTHERWISE FALSE.
C WE WOULD LIKE TO RETURN ERR AS TRUE IF READ/WRITE ERROR DETECTED,
C BUT THIS CAN NOT BE DONE WITH ANSI STANDARD FORTRAN (1966).
C
C UNIVAC ASCII FORTRAN (FTN 5R1AE) DOES NOT WORK IF IFORM
C IS DECLARED WITH DIMENSION 1.  MOST FORTRANS DO THOUGH.
C
C     INTEGER N (UNIVAC FORTRAN V DOES NOT ALLOW)
      INTEGER C(N), IFORM(N), IU, U, UNIT
      LOGICAL ERR, MPIS
      DATA U /1HU/
      ERR = (N.LE.0)
      IF (ERR) RETURN
      IU = IABS(UNIT)
      IF (MPIS (IFORM(1), U)) GO TO 10
      IF (UNIT .GT. 0) WRITE (IU, IFORM) C
      IF (UNIT .LE. 0) READ  (IU, IFORM) C
      RETURN
C UNFORMATTED I/O HERE
   10 IF (UNIT .GT. 0) WRITE (IU) C
      IF (UNIT .LE. 0) READ (IU) C
      RETURN
      END
C $$                   ******  MPKADD  ******
      SUBROUTINE MPKADD (X, Y, Z)
C ADDS X AND Y, FORMING RESULT IN Z, WHERE X AND Y ARE PACKED OR
C UNPACKED MP NUMBERS, Z IS AN UNPACKED MP NUMBER.
C FOR FURTHER DETAILS SEE MPADD.
      INTEGER X(1), Y(1), Z(1)
      EXTERNAL MPADD
      CALL MPK3V (MPADD, X, Y, Z)
      RETURN
      END
C $$                   ******  MPKDIV  ******
      SUBROUTINE MPKDIV (X, Y, Z)
C DIVIDES X AND Y, FORMING RESULT IN Z, WHERE X AND Y ARE
C PACKED OR UNPACKED MP NUMBERS, Z IS UNPACKED.
C FOR FURTHER DETAILS SEE MPDIV.
      INTEGER X(1), Y(1), Z(1)
      EXTERNAL MPDIV
      CALL MPK3V (MPDIV, X, Y, Z)
      RETURN
      END
C $$                   ******  MPKDVI  ******
      SUBROUTINE MPKDVI (X, N, Y)
C RETURNS Y = X/N, FOR PACKED OR UNPACKED MP X,
C INTEGER N, UNPACKED MP Y.
C FOR FURTHER DETAILS SEE MPDIVI.
      INTEGER N, X(1), Y(1)
      EXTERNAL MPDIVI
      CALL MPK3V2 (MPDIVI, X, N, Y)
      RETURN
      END
C $$                   ******  MPKIML  ******
      SUBROUTINE MPKIML (N, X, Y)
C RETURNS Y = X*N, FOR PACKED OR UNPACKED MP X,
C INTEGER N, UNPACKED MP Y.
C FOR FURTHER DETAILS SEE MPMULI.
      INTEGER N, X(1), Y(1)
      EXTERNAL MPMULI
      CALL MPK3V2 (MPMULI, X, N, Y)
      RETURN
      END
C $$                   ******  MPKMLI  ******
      SUBROUTINE MPKMLI (X, N, Y)
C RETURNS Y = X*N, FOR PACKED OR UNPACKED MP X,
C INTEGER N, UNPACKED MP Y.
C FOR FURTHER DETAILS SEE MPMULI.
      INTEGER N, X(1), Y(1)
      EXTERNAL MPMULI
      CALL MPK3V2 (MPMULI, X, N, Y)
      RETURN
      END
C $$                   ******  MPKMUL  ******
      SUBROUTINE MPKMUL (X, Y, Z)
C MULTIPLIES X AND Y, FORMING RESULT IN Z, WHERE X AND Y ARE
C PACKED OR UNPACKED MP NUMBERS, Z IS UNPACKED.
C FOR FURTHER DETAILS SEE MPMUL.
      INTEGER X(1), Y(1), Z(1)
      EXTERNAL MPMUL
      CALL MPK3V (MPMUL, X, Y, Z)
      RETURN
      END
C $$                   ******  MPKSUB  ******
      SUBROUTINE MPKSUB (X, Y, Z)
C SUBTRACTS X AND Y, FORMING RESULT IN Z, WHERE X AND Y ARE PACKED
C OR UNPACKED MP NUMBERS, Z IS AN UNPACKED MP NUMBER.
C FOR FURTHER DETAILS SEE MPSUB.
      INTEGER X(1), Y(1), Z(1)
      EXTERNAL MPSUB
      CALL MPK3V (MPSUB, X, Y, Z)
      RETURN
      END
C $$                   ******  MPK3V  ******
      SUBROUTINE MPK3V (MPXX, X, Y, Z)
C CALLS MPXX (X, Y, Z) AFTER UNPACKING X AND Y.
C X AND Y ARE PACKED OR UNPACKED MP NUMBERS,
C Z IS UNPACKED MP NUMBER, MPXX IS A SUBROUTINE
C TAKING THREE (UNPACKED) MP ARGUMENTS.
      COMMON R
      INTEGER I2, I3, R(1), SV, X(1), Y(1), Z(1)
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPUNPK (X, R(I2))
      CALL MPUNPK (Y, R(I3))
      CALL MPXX (R(I2), R(I3), Z)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPK3V2  ******
      SUBROUTINE MPK3V2 (MPXX, X, N, Y)
C CALLS MPXX (X, N, Y) AFTER UNPACKING X.
C X IS PACKED OR UNPACKED MP NUMBER, N INTEGER,
C Y UNPACKED MP NUMBER, MPXX A SUBROUTINE
C TAKING THREE ARGUMENTS (MP, INTEGER, MP).
      COMMON R
      INTEGER I2, N, R(1), SV, X(1), Y(1)
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPUNPK (X, R(I2))
      CALL MPXX (R(I2), N, Y)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPLE  ******
      LOGICAL FUNCTION MPLE (X, Y)
C RETURNS LOGICAL VALUE OF (X .LE. Y) FOR MP X AND Y.
C X AND/OR Y MAY BE PACKED OR UNPACKED.
      INTEGER MPCOMP, X(1), Y(1)
      MPLE = (MPCOMP(X,Y) .LE. 0)
      RETURN
      END
C $$                   ******  MPLG10  ******
      SUBROUTINE MPLG10 (X, Y)
C RETURNS Y = LOG10(X), FOR MP X AND Y, USING MPLN AND MPLNI.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C FOR COMMENTS ON TIME, SEE SUBROUTINE MPLN.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      INTEGER I2, I3, R(1), SV, TG, X(1), Y(1)
C SAVE T ETC.
      CALL MPSAVN (SV)
C USE TRUNCATION RATHER THAN ROUNDING.
      IF (R(SV+2).EQ.1) CALL MPSETR (0)
C INCREASE T AND ALLOCATE WORKING SPACE.
      CALL MPGD3 (1, TG)
      CALL MPNEW (I2)
C COMPUTE LN(X)/LN(10), TAKING CARE FOR DIRECTED ROUNDINGS.
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPLN (R(I2), R(I2))
      CALL MPNEW (I3)
      CALL MPREVR (R(I2))
      CALL MPLNI (10, R(I3))
      CALL MPREVR (R(I2))
      CALL MPDIV (R(I2), R(I3), R(I2))
C ROUND RESULT, RESTORE T ETC. AND RETURN.
      CALL MPRND (R(I2), TG, Y, IABS(R(SV)), 1)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPLI  ******
      SUBROUTINE MPLI (X, Y)
C RETURNS Y = LI(X) = LOGARITHMIC INTEGRAL OF X
C           = (PRINCIPAL VALUE INTEGRAL FROM 0 TO X OF
C              DU/LOG(U)),
C USING MPEI.  X AND Y ARE MP NUMBERS, X .GE. 0, X .NE. 1.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C ERROR IN Y COULD BE INDUCED BY AN O(B**(1-T)) RELATIVE
C PERTURBATION IN X FOLLOWED BY SIMILAR PERTURBATION IN Y.
C THUS RELATIVE ERROR IN Y IS SMALL UNLESS X IS CLOSE TO
C 1 OR TO THE ZERO 1.45136923488338105028... OF LI(X).
C TIME IS O(T.M(T)).
C ROUNDING OPTIONS NOT YET IMPLEMENTED.
      INTEGER MPCMPI, SV, X(1), Y(1)
      IF (X(1)) 10, 20, 30
C HERE X NEGATIVE, GIVE ERROR MESSAGE
   10 CALL MPERRM (25HX .LT. 0 IN CALL TO MPLI$)
C LI(0) = 0
   20 Y(1)= 0
      RETURN
C HERE X IS POSITIVE, SEE IF EQUAL TO 1
   30 IF (MPCMPI (X, 1) .EQ. 0) CALL MPERRM (
     $  25HX .EQ. 1 IN CALL TO MPLI$)
C HERE X POSITIVE AND .NE. 1, SO USE EI(LN(X)), TRUNCATED ARITHMETIC.
      CALL MPSAVN (SV)
      CALL MPSETR (0)
      CALL MPLN (X, Y)
      CALL MPEI (Y, Y)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPLN  ******
      SUBROUTINE MPLN (X, Y)
C RETURNS Y = LN(X), FOR MP X AND Y, USING MPLNI AND MPLNS.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C RESTRICTION - INTEGER PART OF LN(X) MUST BE REPRESENTABLE AS A
C SINGLE-PRECISION INTEGER.  TIME IS O(SQRT(T).M(T) + T**2).
C FOR SMALL INTEGER X, MPLNI IS FASTER.
C ASYMPTOTICALLY FASTER METHODS EXIST (EG THE GAUSS-SALAMIN
C METHOD, SEE MPLNGS), BUT ARE NOT USEFUL UNLESS T IS LARGE.
C SEE COMMENTS TO MPATAN, MPEXP1 AND MPPIGL.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, DUMMY
      INTEGER I2, I3, J, K, SV, TG
      INTEGER B, DUMMY(22), R(1), X(1), Y(1)
C SAVE T ETC.
      CALL MPSAVN (SV)
C INCREASE WORKING PRECISION.
      CALL MPGD3 (1, TG)
C ALLOCATE TEMPORARY SPACE
      CALL MPNEW (I2)
      CALL MPNEW (I3)
C USE TRUNCATED ARITHMETIC.
      CALL MPSETR (0)
C CHECK THAT X IS POSITIVE
      IF (X(1) .LE. 0) CALL MPERRM (
     $  30HX NONPOSITIVE IN CALL TO MPLN$)
C MOVE X TO LOCAL STORAGE
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
C CHECK IF X IS CLOSE TO 1
      CALL MPADDI (R(I2), -1, R(I3))
      IF (R(I3) .EQ. 0) GO TO 10
      IF (R(I3+1) .GE. 0) GO TO 20
C HERE X CLOSE TO 1, SO USE MPLNS DIRECTLY
   10 CALL MPLNS (R(I3), R(I2))
      GO TO 30
C TAKE OFF EXPONENT AND FIRST TWO DIGITS
   20 J = B*R(I2+2) + R(I2+3)
      K = R(I2+1) - 2
      R(I2+1) = 2
      CALL MPDIVI (R(I2), J, R(I2))
      CALL MPADDI (R(I2), -1, R(I2))
C NOW SHOULD BE SAFE TO CALL MPLNS
      CALL MPLNS (R(I2), R(I2))
C NOW USE MPLNI TO CORRECT RESULT
      CALL MPLNI (IABS(B), R(I3))
      CALL MPMULI (R(I3), K, R(I3))
      CALL MPADD (R(I2), R(I3), R(I2))
      CALL MPLNI (J, R(I3))
      CALL MPADD (R(I2), R(I3), R(I2))
C ROUND RESULT
   30 CALL MPSETR (IABS(R(SV+2)))
      CALL MPRND (R(I2), TG, Y, IABS(R(SV)), 1)
C RESTORE T ETC. AND RETURN.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPLNGM  ******
      SUBROUTINE MPLNGM (X, Y)
C RETURNS MP Y = LN(GAMMA(X)) FOR POSITIVE MP X, USING STIRLINGS
C ASYMPTOTIC EXPANSION.  SLOWER THAN MPGAMQ (UNLESS X LARGE)
C AND USES MORE SPACE, SO USE MPGAMQ AND MPLN IF X IS RATIONAL AND
C NOT TOO LARGE, SAY X .LE. 200.  TIME IS O(T**3).
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C SPACE REQUIRED IS O(T**2) WORDS (MORE PRECISELY, SPACE IS
C NL*T/2 + O(T) WORDS, WHERE
C NL = T*LOG2(B)/12 + O(1)  (SEE BELOW)).
C ROUNDING OPTIONS NOT IMPLEMENTED, USES NO GUARD DIGITS.
      COMMON R
      COMMON /MPCOM/ B, DUMMY
      INTEGER I, IP, I2, I3, I4, I5, MXINT, NL, NL2, NT, P, Q, SV, XL
      INTEGER B, DUMMY(22), R(1), X(1), Y(1)
      INTEGER MPCHGB, MPCMPI, MPPARN, MPTLB
C SAVE T ETC.
      CALL MPSAVN (SV)
C ESTIMATE
C          NL = NUMBER OF TERMS REQUIRED IN STIRLINGS
C APPROXIMATION, AND
C          XL = LOWER BOUND ON X FOR SUFFICIENT ACCURACY.
C THE CONSTANT 12 WAS DETERMINED EMPIRICALLY TO MINIMIZE TIME.
      NL = MPTLB(IABS(R(SV)))/12 + 2
      NT = R(SV) + 1
      MXINT = MPPARN(16)
      NL2 = 2*NL
      Q = 1
      DO 20 I = 2, NL2
   10 IF (Q .LE. (MXINT/I)) GO TO 20
      Q = Q/B + 1
      NT = NT + 1
      GO TO 10
   20 Q = I*Q
      XL = 1
   30 XL = XL + 1
C 6*XL + XL/4 .LE. 2*PI*XL
      IF (MPCHGB (6*XL + XL/4, IABS(B), NT) .GT. NL2) GO TO 30
C CHECK THAT X IS POSITIVE
      IF (X(1) .LE. 0) CALL MPERRM (
     $  27HX .LE. 0 IN CALL TO MPLNGM$)
C ALLOCATE TEMPORARY SPACE, USE TRUNCATED ARITHEMTIC.
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPSETR (0)
C MOVE X AND SET Y = 0
      CALL MPMOVE (X, IABS(R(SV)), R(I3), IABS(R(SV)))
      Y(1) = 0
C SEE IF X LARGE ENOUGH TO USE ASYMPTOTIC SERIES
      IF (MPCMPI (R(I3), XL) .GE. 0) GO TO 50
C HERE X NOT LARGE ENOUGH, SO INCREASE USING THE
C IDENTITY GAMMA(X+1) = X*GAMMA(X) TO CORRECT RESULT
      CALL MPCIM (1, Y)
   40 CALL MPMUL (Y, R(I3), Y)
      CALL MPADDI (R(I3), 1, R(I3))
      IF (MPCMPI (R(I3), XL) .LT. 0) GO TO 40
      CALL MPLN (Y, Y)
      Y(1) = -Y(1)
C COMPUTE FIRST TERMS IN STIRLINGS APPROXIMATION
   50 CALL MPLN (R(I3), R(I4))
      CALL MPADDQ (R(I3), -1, 2, R(I2))
      CALL MPMUL (R(I2), R(I4), R(I4))
      CALL MPSUB (R(I4), R(I3), R(I4))
      CALL MPADD (Y, R(I4), Y)
      CALL MPPI (R(I4))
      CALL MPMULI (R(I4), 2, R(I4))
      CALL MPLN (R(I4), R(I4))
      CALL MPDIVI (R(I4), 2, R(I4))
      CALL MPADD (Y, R(I4), Y)
C IF X VERY LARGE CAN RETURN HERE
      IF (R(I3+1).GE.R(SV)) GO TO 70
      CALL MPPWR (R(I3), -2, R(I4))
      P = (R(SV)+3)/2
C ALLOCATE SPACE FOR BERNOULLI NUMBERS.
      CALL MPNEW2 (I5, NL*P)
C COMPUTE BERNOULLI NUMBERS REQUIRED (MUCH TIME COULD BE
C SAVED IF THESE WERE PRECOMPUTED)
      CALL MPBERN ((-NL), P, R(I5))
C SUM ASYMPTOTIC SERIES
      DO 60 I = 1, NL
      IP = I5 + (I-1)*P
      CALL MPUNPK (R(IP), R(I2))
      CALL MPMULS (R(I2), 1, 1, 2*I, 2*I-1)
      CALL MPMUL (R(I3), R(I4), R(I3))
      CALL MPMUL (R(I3), R(I2), R(I2))
      IF ((R(I2).EQ.0).OR.(R(I2+1).LE.(-R(SV)))) GO TO 70
   60 CALL MPADD (Y, R(I2), Y)
C RESTORE EVERYTHING AND RETURN
   70 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPLNGS  ******
      SUBROUTINE MPLNGS (X, Y)
C RETURNS Y = LN(X) FOR MP X AND Y, USING THE GAUSS-SALAMIN
C ALGORITHM BASED ON THE ARITHMETIC-GEOMETRIC MEAN ITERATION
C (SEE ANALYTIC COMPUTATIONAL COMPLEXITY (ED. BY J. F. TRAUB),
C ACADEMIC PRESS, 1976, 151-176) UNLESS X IS CLOSE TO 1.
C TIME = O(LOG(T)M(T)) + O(T**2) IF ABS(X-1) .GE. 1/B,
C AND AS FOR MPLNS OTHERWISE.
C SLOWER THAN MPLN UNLESS T IS LARGE (.GE. ABOUT 500) SO
C MAINLY USEFUL FOR TESTING PURPOSES.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, DUMMY
      INTEGER I, IT, I2, I3, I4, N, SV, TG, T2
      INTEGER B, DUMMY(17), LUN, M, MXR, R(1), SPTR, T, X(1), Y(1)
      INTEGER MPCHGB, MPGET, MPTLB
C SAVE T ETC.
      CALL MPSAVN (SV)
C CHECK FOR ZERO ARGUMENT.
      IF (X(1) .LE. 0) CALL MPERRM (
     $  27HX .LE. 0 IN CALL TO MPLNGS$)
C SEE IF X CLOSE TO 1.
      CALL MPNEW (I2)
      CALL MPADDI (X, -1, R(I2))
      IF ((R(I2).NE.0).AND.(R(I2+1).GE.0)) GO TO 10
C HERE ABS(X-1) .LT. 1/B SO GAUSS-SALAMIN ALGORITHM COULD BE
C INACCURATE BECAUSE OF CANCELLATION.  THE PRECISION COULD BE
C INCREASED TO COMPENSATE FOR THIS, BUT SIMPLER TO USE MPLNS.
      CALL MPLNS (R(I2), Y)
      GO TO 30
C INCREASE WORKING PRECISION, ALLOCATE SPACE ETC.
   10 SPTR = I2
      CALL MPGD3 (MPTLB (IABS(T)), TG)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPSETR (0)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      T2 = (T+1)/2
C MODIFY EXPONENT
      R(I2+1) = -T2
      CALL MPMULI (R(I2), 4, R(I2))
      CALL MPCIM (1, R(I3))
C COMPUTE NUMBER OF ITERATIONS REQUIRED.
      N = MAX0 (1, MPCHGB (2, MPTLB (T2+1) * (MPTLB (IABS(T))
     $  + 3), 1) - 3)
C ARITHMETIC-GEOMETRIC MEAN LOOP
      DO 20 I = 1, N
      CALL MPADD (R(I2), R(I3), R(I4))
      CALL MPDIVI (R(I4), 2, R(I4))
      CALL MPMUL (R(I2), R(I3), R(I3))
      CALL MPSQRT (R(I3), R(I2))
C FASTER TO EXCHANGE POINTERS THAN MP NUMBERS
      IT = I3
      I3 = I4
   20 I4 = IT
C CHECK THAT CONVERGENCE OCCURRED
      CALL MPSUB (R(I2), R(I3), R(I4))
      IF ((R(I4) .NE. 0) .AND. ((R(I2+1) - R(I4+1)) .LT. (T-3)))
     $  CALL MPERRM (39HITERATION FAILED TO CONVERGE IN MPLNGS$)
C COULD SAVE SOME TIME BY PRECOMPUTING PI AND LN(B)
      CALL MPPI (R(I4))
      CALL MPDIV (R(I4), R(I3), R(I3))
      CALL MPDIVI (R(I3), 2, R(I3))
      CALL MPLNI (IABS(B), R(I4))
      CALL MPMULI (R(I4), MPGET(X, 2) + T2, R(I4))
C ALLOW FOR MODIFIED EXPONENT
      CALL MPSUB (R(I4), R(I3), R(I3))
C ROUND RESULT
      CALL MPSETR (IABS(R(SV+2)))
      CALL MPRND (R(I3), TG, Y, IABS(R(SV)), 1)
C RESTORE T ETC. AND RETURN.
   30 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPLNI  ******
      SUBROUTINE MPLNI (N, X)
C RETURNS MULTIPLE-PRECISION X = LN(N) FOR SMALL POSITIVE
C INTEGER N (2*N MUST BE REPRESENTABLE).  TIME IS O(T**2).
C METHOD IS TO USE A RAPIDLY CONVERGING SERIES AND MPL235.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, IA, IK, IM, IP, IP2, IQ, IQ2, I2, I3, I4, J, MXINT, N1,
     $  N2, SV, TG, B, DUMMY(21), MPPARN, MPTLB, N, R(1), T, X(1)
C CHECK FOR N = 1 AND N .LT. 1
      IF (N-1) 10, 20, 30
   10 CALL MPERRM (32HN NOT POSITIVE IN CALL TO MPLNI$)
C LN(1) = 0
   20 X(1) = 0
      RETURN
C HERE N .GE. 2, INCREASE T AS NECESSARY.
   30 CALL MPSAVN (SV)
      CALL MPGD3 (MPTLB (IABS(T)), TG)
C USE TRUNCATED ARITHMETIC INTERNALLY
      CALL MPSETR (0)
      MXINT = MPPARN (16)
C ALLOCATE WORKING SPACE
      CALL MPNEW (I2)
      IF (N.GT.2) GO TO 40
C N = 2 IS A SPECIAL CASE
      CALL MPL235 (1, 0, 0, R(I2))
      GO TO 150
C HERE N .GE. 3
   40 IF (N .GT. (MXINT/2)) GO TO 80
      J = 3
      IA = 0
      N2 = N/2
   50 IF (J.GT.N2) GO TO 60
      IA = IA + 1
      J = 2*J
      GO TO 50
C NOW J = 3*(2**IA) .LE. N .LT. 6*(2**IA)
   60 J = J/3
      IM = N
      IK = 0
      DO 70 I = 3, 6
      N1 = I*J
      IF (IABS(N1-N).GT.IM) GO TO 70
      IM = IABS(N1-N)
      IK = I
   70 CONTINUE
      N1 = IK*J
C NOW N IS CLOSE TO N1 = IK*(2**IA)
C AND IK = 3, 4, 5 OR 6, SO MPL235 GIVES LN(N1).
      IF (IK.EQ.3) CALL MPL235 (IA, 1, 0, R(I2))
      IF (IK.EQ.4) CALL MPL235 (IA+2, 0, 0, R(I2))
      IF (IK.EQ.5) CALL MPL235 (IA, 0, 1, R(I2))
      IF (IK.EQ.6) CALL MPL235 (IA+1, 1, 0, R(I2))
      IF (N.EQ.N1) GO TO 150
C NOW NEED LN(N/N1).
      N2 = N
      CALL MPGCD (N2, N1)
      IP = N2 - N1
      IQ = N2 + N1
C CHECK FOR POSSIBLE INTEGER OVERFLOW
      IF (IQ.GT.14) GO TO 100
   80 CALL MPERRM (29HN TOO LARGE IN CALL TO MPLNI$)
C REDUCE TO LOWEST TERMS
  100 CALL MPGCD (IP, IQ)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPCQM (2*IP, IQ, R(I4))
      CALL MPSTR (R(I4), R(I3))
      CALL MPADD (R(I2), R(I3), R(I2))
      I = 1
      IF (IQ.GT.(MXINT/IQ)) GO TO 110
      IQ2 = IQ**2
      IP2 = IP**2
C LOOP TO SUM SERIES FOR LN(N2/N1)
  110 I = I + 2
      IF (R(I4).EQ.0) GO TO 140
C REDUCE T IF POSSIBLE, DONE IF CAN REDUCE BELOW 2
      T = TG + R(I4+1) + 2
      IF (T.LE.2) GO TO 140
      T = MIN0 (T, TG)
C SPLIT UP CALL TO MPMULQ IF IQ TOO LARGE
      IF (IQ.GT.(MXINT/IQ)) GO TO 120
      CALL MPMULQ (R(I4), IP2, IQ2, R(I4))
      GO TO 130
C HERE IQ TOO LARGE FOR ONE CALL TO MPMULQ
  120 CALL MPMULQ (R(I4), IP, IQ, R(I4))
      CALL MPMULQ (R(I4), IP, IQ, R(I4))
  130 CALL MPDIVI (R(I4), I, R(I3))
C RESTORE T AND ACCUMULATE SUM
      T = TG
      CALL MPADD (R(I3), R(I2), R(I2))
      GO TO 110
  140 T = TG
C RESTORE RNDRL AND ROUND RESULT
  150 CALL MPSETR (IABS(R(SV+2)))
      CALL MPRND (R(I2), TG, X, IABS(R(SV)), 1)
C RESTORE T ETC.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPLNS  ******
      SUBROUTINE MPLNS (X, Y)
C RETURNS MP Y = LN(1+X) IF X IS AN MP NUMBER SATISFYING THE
C CONDITION ABS(X) .LT. 1/B, ERROR OTHERWISE.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C USES NEWTONS METHOD TO SOLVE THE EQUATION
C EXP1(-Y) = X, THEN REVERSES SIGN OF Y.
C (HERE EXP1(Y) = EXP(Y) - 1 IS COMPUTED USING MPEXP1).
C TIME IS O(SQRT(T).M(T)) AS FOR MPEXP1.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER IT0, I2, I3, I4, I5, SV, TG, TS2, TS3
      INTEGER B, DUMMY(21), MPGD, MPGET, R(1), T, X(1), Y(1)
C SAVE T ETC. THEN INCREASE, USE TRUNCATION INTERNALLY.
      CALL MPSAVN (SV)
      T = MAX0 (5, T + 1 + MPGD (100))
      TG = T
      CALL MPSETR (0)
C ALLOCATE TEMPORARY SPACE.
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPNEW (I5)
C CHECK FOR X = 0 EXACTLY
      IF (X(1).NE.0) GO TO 10
      Y(1) = 0
      GO TO 50
C CHECK THAT ABS(X) .LT. 1/B
   10 IF (MPGET (X, 2) .GE. 0) CALL MPERRM (
     $  33HABS(X) .GE. 1/B IN CALL TO MPLNS$)
C GET STARTING APPROXIMATION TO -LN(1+X).
      CALL MPMOVE (X, IABS(R(SV)), R(I3), TG)
      CALL MPSTR (R(I3), R(I5))
      CALL MPDIVI (R(I5), 4, R(I2))
      CALL MPADDQ (R(I2), -1, 3, R(I2))
      CALL MPMUL (R(I5), R(I2), R(I2))
      CALL MPADDQ (R(I2), 1, 2, R(I2))
      CALL MPMUL (R(I5), R(I2), R(I2))
      CALL MPADDI (R(I2), -1, R(I2))
      CALL MPMUL (R(I5), R(I2), R(I5))
C START NEWTON ITERATION USING SMALL T, LATER INCREASE
      T = MAX0 (5, 13 - 2*B)
      IT0 = (T + 5)/2
   20 CALL MPEXP1 (R(I5), R(I4))
      CALL MPMUL (R(I3), R(I4), R(I2))
      CALL MPADD (R(I4), R(I2), R(I4))
      CALL MPADD (R(I3), R(I4), R(I4))
      CALL MPSUB (R(I5), R(I4), R(I5))
      IF (T.GE.TG) GO TO 40
C FOLLOWING LOOP COMPUTES NEXT VALUE OF T TO USE.
C BECAUSE NEWTONS METHOD HAS 2ND ORDER CONVERGENCE,
C WE CAN ALMOST DOUBLE T EACH TIME.
      TS3 = T
      T = TG
   30 TS2 = T
      T = (T+IT0)/2
      IF (T.GT.TS3) GO TO 30
      T = TS2
      GO TO 20
C CHECK THAT NEWTON ITERATION WAS CONVERGING AS EXPECTED
   40 IF ((R(I4).NE.0).AND.((2*R(I4+1)).GT.(IT0-T)))
     $  CALL MPERRM (41HNEWTON ITERATION NOT CONVERGING IN MPLNS$)
C REVERSE SIGN AND ROUND RESULT.
      R(I5) = -R(I5)
      CALL MPSETR (IABS(R(SV+2)))
      CALL MPRND (R(I5), TG, Y, IABS(R(SV)), 1)
C RESTORE STACK POINTER ETC. AND RETURN
   50 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPLT  ******
      LOGICAL FUNCTION MPLT (X, Y)
C RETURNS LOGICAL VALUE OF (X .LT. Y) FOR MP X AND Y.
C X AND/OR Y MAY BE PACKED OR UNPACKED.
      INTEGER MPCOMP, X(1), Y(1)
      MPLT = (MPCOMP(X,Y) .LT. 0)
      RETURN
      END
C $$                   ******  MPL235  ******
      SUBROUTINE MPL235 (I, J, K, X)
C CALLED BY MPLNI, NOT RECOMMENDED FOR INDEPENDENT USE.
C RETURNS MP X = LN((2**I)*(3**J)*(5**K)), FOR INTEGER I, J AND K.
C THE METHOD REQUIRES TIME O(T**2).  LN(81/80), LN(25/24) AND
C LN(16/15) ARE CALCULATED FIRST.  MPL235 COULD BE SPEEDED
C UP IF THESE CONSTANTS WERE PRECOMPUTED AND SAVED.
C ASSUMED THAT I, J AND K NOT TOO LARGE.
C ROUNDING OPTIONS NOT IMPLEMENTED AND NO GUARD DIGITS USED.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER C(3), D(3), I2, I3, N, Q, SV, TWO
      INTEGER B, DUMMY(21), I, J, K, MPPARN, R(1), T, X(1)
      DATA D(1), D(2), D(3) /161, 49, 31/
      TWO = 2
C SAVE T ETC. AND ALLOCATE TEMPORARY SPACE
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
C USE TRUNCATION INTERNALLY.
      CALL MPSETR (0)
      X(1) = 0
      IF (MAX0(IABS(I), IABS(J), IABS(K)) .GE. (MPPARN(16)/68))
     $  CALL MPERRM (37HI, J OR K TOO LARGE IN CALL TO MPLNI$)
      C(1) = 3*I + 5*J + 7*K
      C(2) = 5*I + 8*J + 12*K
      C(3) = 7*I + 11*J + 16*K
      DO 20 Q = 1, 3
      T = R(SV)
      CALL MPCQM (2*C(Q), D(Q), R(I2))
      CALL MPSTR (R(I2), R(I3))
      CALL MPADD (X, R(I3), X)
      N = 1
   10 N = N + 2
      IF (R(I2).EQ.0) GO TO 20
C REDUCE T IF POSSIBLE
      T = R(SV) + R(I2+1) + 2 - X(TWO)
      IF (T.LE.2) GO TO 20
      T = MIN0 (T, R(SV))
      CALL MPMULS (R(I2), 1, 1, D(Q), D(Q))
      CALL MPDIVI (R(I2), N, R(I3))
      T = R(SV)
      CALL MPADD (R(I3), X, X)
      GO TO 10
   20 CONTINUE
C RESTORE STACK POINTER ETC. AND RETURN
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPMAX  ******
      SUBROUTINE MPMAX (X, Y, Z)
C SETS Z = MAX (X, Y) WHERE X, Y AND Z ARE MP VARIABLES.
C X AND/OR Y MAY BE PACKED OR UNPACKED, Z IS UNPACKED.
      INTEGER MPCOMP, X(1), Y(1), Z(1)
      IF (MPCOMP (X, Y) .GE. 0) GO TO 10
C HERE X .LT. Y
      CALL MPUNPK (Y, Z)
      RETURN
C HERE X .GE. Y
   10 CALL MPUNPK (X, Z)
      RETURN
      END
C $$                   ******  MPMAXR  ******
      SUBROUTINE MPMAXR (X)
C SETS X TO THE LARGEST POSSIBLE POSITIVE MP NUMBER
      COMMON /MPCOM/ B, T, M, DUMMY
      INTEGER B, DUMMY(20), I, IT, M, T, TWO, X(1)
      TWO = 2
C CHECK LEGALITY OF PARAMETERS IN COMMON /MPCOM/
      CALL MPCHK
      IT = B - 1
C SET FRACTION DIGITS TO B-1
      DO 10 I = 1, T
   10 X(I+2) = IT
C SET SIGN AND EXPONENT, AND UPDATE MXEXPN.
      X(1) = 1
      X(TWO) = M
      CALL MPUPDT (X(TWO))
      RETURN
      END
C $$                   ******  MPMEXA  ******
      INTEGER FUNCTION MPMEXA (X)
C RETURNS THE MAXIMUM ALLOWABLE EXPONENT OF MP NUMBERS (THE THIRD
C WORD OF COMMON /MPCOM/).  X IS A DUMMY MP ARGUMENT.
      INTEGER MPPARN, X(1)
      MPMEXA = MPPARN (3)
      RETURN
      END
C $$                   ******  MPMEXB  ******
      SUBROUTINE MPMEXB (I, X)
C SETS THE MAXIMUM ALLOWABLE EXPONENT OF MP NUMBERS (I.E. THE
C THIRD WORD OF COMMON /MPCOM/) TO I.
C I SHOULD BE GREATER THAN 4*T, AND 4*I SHOULD BE REPRESENTABLE
C AS A SINGLE-PRECISION INTEGER.
C X IS A DUMMY MP ARGUMENT (AUGMENT EXPECTS ONE).
      INTEGER I, X(1)
      CALL MPPARC (3, I)
      RETURN
      END
C $$                   ******  MPMIN  ******
      SUBROUTINE MPMIN (X, Y, Z)
C SETS Z = MIN (X, Y) WHERE X, Y AND Z ARE MP VARIABLES.
C X AND/OR Y MAY BE PACKED OR UNPACKED, Z IS UNPACKED.
      INTEGER MPCOMP, X(1), Y(1), Z(1)
      IF (MPCOMP (X, Y) .GE. 0) GO TO 10
C HERE X .LT. Y
      CALL MPUNPK (X, Z)
      RETURN
C HERE X .GE. Y
   10 CALL MPUNPK (Y, Z)
      RETURN
      END
C $$                   ******  MPMINR  ******
      SUBROUTINE MPMINR (X)
C SETS X TO THE SMALLEST POSITIVE NORMALIZED MP NUMBER B**(-M)
      COMMON /MPCOM/ B, T, M, DUMMY
      INTEGER B, DUMMY(20), I, IL, M, T, TWO, X(1)
      TWO = 2
C CLEAR X
      IL = T + 2
      DO 10 I = 1, IL
   10 X(I) = 0
C SET SIGN, EXPONENT AND FIRST DIGIT
      X(1) = 1
      X(TWO) = 1 - M
      X(TWO+1) = 1
C UPDATE MNEXPN AND RETURN
      CALL MPUPDT (X(TWO))
      RETURN
      END
C $$                   ******  MPMLP  ******
      SUBROUTINE MPMLP (U, V, W, J)
C PERFORMS INNER MULTIPLICATION LOOP FOR MPMUL
C NOTE THAT CARRIES ARE NOT PROPAGATED IN INNER LOOP,
C WHICH SAVES TIME AT THE EXPENSE OF SPACE.
      INTEGER I, J, U(1), V(1), W
      DO 10 I = 1, J
   10 U(I) = U(I) + W*V(I)
      RETURN
      END
C $$                   ******  MPMOD  ******
      SUBROUTINE MPMOD (X, Y, Z)
C
C RETURNS Z = X - INT(X/Y)*Y FOR MP X, Y AND Z,  Y NONZERO.
C HERE INT MEANS INTEGER PART, TRUNCATED TOWARDS ZERO.
C RETURNS ZERO IF Y IS ZERO.
C X AND/OR Y MAY BE PACKED OR UNPACKED, Z IS UNPACKED.
C
C WARNING - TIME IS O(MAX (1, LN(ABS(X/Y))) * (T**2)), WHICH MAY BE
C *******   LARGE IF ABS(X) IS MUCH LARGER THAN ABS(Y).
C
      COMMON R
      COMMON /MPCOM/ B, T, M, DUMMY
      INTEGER I2, I3, I4, I5, MPCMPA, SV, TG
      INTEGER B, DUMMY(20), M, R(1), T, X(1), Y(1), Z(1)
C CHECK FOR Y ZERO.
      IF (Y(1).NE.0) GO TO 10
      Z(1) = 0
      RETURN
C SAVE T ETC.
   10 CALL MPSAVN (SV)
C USE TRUNCATION (ACTUALLY EXACT ARITHMETIC HERE)
      CALL MPSETR (0)
C DOUBLE T SO MULTIPLICATION IS EXACT
      T = 2*T
      TG = T
C ALLOCATE WORKING SPACE
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPNEW (I5)
C MOVE X AND Y, INCREASE M TO AVOID OVER/UNDERFLOW
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPMOVE (Y, IABS(R(SV)), R(I4), TG)
      CALL MPSTR (R(I4), R(I5))
      M = 2*M + 2
C JUMP TO END OF LOOP (SIMULATE WHILE LOOP).
      GO TO 30
C LOOP HERE UNTIL Z RESULT LESS (IN ABSOLUTE VALUE) THAN Y
   20 T = R(SV)
C USE MPDIVL TO BE SURE RESULT TRUNCATED
      CALL MPDIVL (R(I2), R(I5), R(I3))
      CALL MPCMIM (R(I3), R(I3))
      CALL MPMOVE (R(I3), IABS(R(SV)), R(I3), TG)
C INCREASE T SO FOLLOWING MULTIPLICATION AND SUBTRACTION EXACT
      T = TG
      CALL MPMUL (R(I3), R(I4), R(I3))
      CALL MPSUB (R(I2), R(I3), R(I2))
C LOOP TERMINATION CHECK HERE
   30 IF (MPCMPA (R(I2), R(I4)) .GE. 0) GO TO 20
C MOVE RESULT (NO DIGITS LOST), RESTORE EVERYTHING AND RETURN.
      CALL MPMOVE (R(I2), TG, Z, IABS(R(SV)))
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPMOVE  ******
      SUBROUTINE MPMOVE (X, TX, Y, TY)
C ASSUMES MP NUMBER X OF TX .GE. 2 DIGITS,
C MP NUMBER Y OF TY .GE. 2 DIGITS (Y NOT NECESSARILY INITIALIZED).
C MOVES X TO Y, EITHER PADDING WITH TRAILING ZEROS OR ROUNDING
C (AS SPECIFIED BY RNDRL - SEE SUBROUTINE MPNZR) DEPENDING ON
C WHETHER TX IS LESS OR GREATER THAN TY.  THE VALUE OF T IN
C COMMON /MPCOM/ IS RESTORED ON RETURN.
C X MAY BE IN PACKED OR UNPACKED FORMAT, Y IS UNPACKED.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER EX, I, IH, IL, IY, I2, KG, SN, SV
      INTEGER B, DUMMY(21), R(1), T, TX, TY, X(1), Y(1)
      CALL MPSAVN (SV)
C USE LOCAL VARIABLES IN CASE T ACTUAL ARGUMENT
      KG = TX - TY
      IY = TY
      T = TX
C COMPARE TX AND TY.
      IF (KG.GT.0) GO TO 20
C HERE TX .LE. TY
      CALL MPUNPK (X, Y)
      IF (KG.EQ.0) GO TO 40
C HERE TX .LT. TY.
      IL = T + 3
      IH = IY + 2
C PAD WITH TRAILING ZEROS.
      DO 10 I = IL, IH
   10 Y(I) = 0
      GO TO 40
C HERE TX. GT. TY.   CHECK FOR X ZERO.
   20 IF (X(1).NE.0) GO TO 30
C HERE X IS ZERO SO SET Y TO ZERO AND RETURN
      Y(1) = 0
      GO TO 40
C MOVE X TO TEMPORARY STORAGE AND ROUND
   30 CALL MPNEW (I2)
      CALL MPUNPK (X, R(I2))
C REDUCE T FOR CALL TO MPNZR.
      T = IY
      SN = R(I2)
      EX = R(I2+1)
      CALL MPNZR (SN, EX, Y, R(I2+2), KG)
C RESTORE STACK POINTER ETC.
   40 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPMUL  ******
      SUBROUTINE MPMUL (X, Y, Z)
C
C MULTIPLIES X AND Y, RETURNING RESULT IN Z, FOR MP X, Y AND Z.
C THE SIMPLE O(T**2) ALGORITHM IS USED, WITH ROUNDING DEFINED BY THE
C PARAMETER RNDRL IN COMMON /MPCOM/, AS FOLLOWS -
C RNDRL = 0 - TRUNCATE RESULT TOWARDS ZERO,
C             ERROR LESS THAN 1.01 UNITS IN THE LAST PLACE.
C RNDRL = 1, 2 OR 3 - SEE SUBROUTINE MPNZR.
C
C ADVANTAGE IS TAKEN OF ZERO DIGITS IN X, BUT NOT IN Y.
C ASYMPTOTICALLY FASTER ALGORITHMS ARE KNOWN (SEE KNUTH,
C VOL. 2), BUT ARE DIFFICULT TO IMPLEMENT IN FORTRAN IN AN
C EFFICIENT AND MACHINE-INDEPENDENT MANNER.
C IN COMMENTS TO OTHER MP ROUTINES, M(T) IS THE TIME
C TO PERFORM T-DIGIT MP MULTIPLICATION.   THUS
C M(T) = O(T**2) WITH THE PRESENT VERSION OF MPMUL,
C BUT M(T) = O(T.LOG(T).LOG(LOG(T))) IS THEORETICALLY POSSIBLE.
C
C MP OVER/UNDERFLOW IS DETECTED BY SUBROUTINE MPNZR.
C
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER C, I, IH, IP, I2, J, J1, KG, RE, RI, RS, TG, TWO,
     $  B, DUMMY(21), NEXT, R(1), SV, T, XI, X(1), Y(1), Z(1)
      TWO = 2
C FORM SIGN OF PRODUCT
      RS = X(1)*Y(1)
      IF (RS.NE.0) GO TO 10
C SET RESULT TO ZERO
      Z(1) = 0
      RETURN
C COMPUTE NUMBER OF GUARD DIGITS REQUIRED
   10 CALL MPSAVN (SV)
      KG = MIN0 (3, T)
      IF ((R(SV+2) .NE. 0) .OR. (T .GT. ((B*B)/100))) KG = T
C ALLOCATE SPACE FOR ACCUMULATOR, CHECK PARAMETERS ETC.
      TG = T + KG
      CALL MPNEW2 (I2, TG)
      NEXT = I2 + TG
      IH = NEXT - 1
C FORM EXPONENT OF PRODUCT
      RE = X(TWO) + Y(TWO)
C CLEAR ACCUMULATOR
      DO 20 I = I2, IH
   20 R(I) = 0
C PERFORM MULTIPLICATION
      C = 8
      DO 40 I = 1, T
      XI = X(I+2)
C FOR SPEED, PUT THE NUMBER WITH MANY ZEROS FIRST
      IF (XI.EQ.0) GO TO 40
      IP = I + I2
      CALL MPMLP (R(IP), Y(TWO+1), XI, MIN0 (T, TG - I))
      C = C - 1
      IF (C.GT.0) GO TO 40
C CHECK FOR LEGAL BASE B DIGIT
      IF ((XI.LT.0).OR.(XI.GE.B)) GO TO 80
C PROPAGATE CARRIES AT END AND EVERY EIGHTH TIME,
C FASTER THAN DOING IT EVERY TIME.
      DO 30 J = 1, TG
      J1 = NEXT - J
      RI = R(J1) + C
      IF (RI.LT.0) GO TO 70
      C = RI/B
   30 R(J1) = RI - B*C
      IF (C.NE.0) GO TO 80
      C = 8
   40 CONTINUE
      IF (C.EQ.8) GO TO 60
      IF ((XI.LT.0).OR.(XI.GE.B)) GO TO 80
      C = 0
      DO 50 J = 1, TG
      J1 = NEXT - J
      RI = R(J1) + C
      IF (RI.LT.0) GO TO 70
      C = RI/B
   50 R(J1) = RI - B*C
      IF (C.NE.0) GO TO 80
C NORMALIZE AND ROUND RESULT
   60 CALL MPNZR (RS, RE, Z, R(I2), KG)
C RESTORE STACK POINTER AND RETURN
      CALL MPRESN (SV)
      RETURN
   70 CALL MPERRM (39HINTEGER OVERFLOW IN MPMUL, B TOO LARGE$)
   80 CALL MPERRM (38HILLEGAL BASE B DIGIT IN CALL TO MPMUL$)
      RETURN
      END
C $$                   ******  MPMULI  ******
      SUBROUTINE MPMULI (X, IY, Z)
C MULTIPLIES MP X BY SINGLE-PRECISION INTEGER IY GIVING MP Z.
C ROUNDING DEFINED BY PARAMETER RNDRL IN COMMON /MPCOM/ -
C SEE SUBROUTINE MPNZR.
C MULTIPLICATION BY 1 MAY BE USED TO NORMALIZE A NUMBER
C EVEN IF LAST DIGIT IS GREATER THAN B-1.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, DUMMY
      INTEGER C, C1, C2, I, IJ, IKG, IP, IS, IX, I2, J, J1, J2, KG, RE
      INTEGER RI, RS, TG, TWO, T1
      INTEGER B, DUMMY(17), IY, LUN, M, MXR, R(1), SPTR, T, X(1), Z(1)
      INTEGER MPGD, MPPARN
      TWO = 2
C COMPUTE NUMBER OF GUARD DIGITS REQUIRED TO GIVE EXACT PRODUCT.
      KG = MPGD (IY)
C IF IY IS 1 LAST DIGIT MAY BE LARGE (SEE E.G. MPCIM).
      IF (IY.EQ.1) KG = 1
C ALLOCATE T + KG WORDS FOR ACCUMULATOR
      TG = T + KG
      CALL MPNEW2 (I2, TG)
C CHECK FOR X ZERO
      RS = X(1)
      IF (RS.EQ.0) GO TO 110
C CHECK FOR MULTIPLIER ZERO.
      J = IY
      IF (J) 10, 110, 20
C HERE ADJUST SIGN FOR NEGATIVE MULTIPLIER.
   10 J = -J
      RS = -RS
C CHECK FOR MULTIPLICATION BY +-B
   20 IF (J.NE.B) GO TO 30
C CHECK FOR OVERFLOW.
      IF (X(TWO) .GE. M) CALL MPOVFL (Z)
C HERE MULTIPLICATION BY +-B, RESULT DOES NOT OVERFLOW.
      CALL MPSTR (X, Z)
      Z(1) = RS
      Z(TWO) = Z(TWO) + 1
      CALL MPUPDT (Z(TWO))
      GO TO 120
C HAVE TO DO GENUINE MULTIPLICATION HERE.
C SET EXPONENT TO EXPONENT(X) + NUMBER OF GUARD DIGITS.
   30 RE = X(TWO) + KG
C FORM PRODUCT IN ACCUMULATOR
      C = 0
      T1 = T + 1
C IF J*B NOT REPRESENTABLE AS AN INTEGER WE HAVE TO SIMULATE
C DOUBLE-PRECISION MULTIPLICATION.
      IF (J.GT.(MPPARN(16)/B)) GO TO 80
C INNER LOOP FOR SMALL ABS(IY) CASE.
      DO 40 IJ = 1, T
      I = T1 - IJ
      RI = J*X(I+2) + C
      C = RI/B
      IP = SPTR - IJ
   40 R(IP) = RI - B*C
C CHECK FOR INTEGER OVERFLOW
      IF (RI.LT.0) GO TO 100
C HAVE TO TREAT FIRST KG WORDS OF ACCUMULATOR SEPARATELY
      IKG = I2 + KG
      IF (KG.LE.0) GO TO 60
      DO 50 IJ = 1, KG
      I = IKG - IJ
      RI = C
      C = RI/B
   50 R(I) = RI - B*C
   60 IF (C.NE.0) GO TO 100
C NORMALIZE AND ROUND OR TRUNCATE RESULT
   70 CALL MPNZR (RS, RE, Z, R(I2), KG)
      GO TO 120
C HERE J MAY BE TOO LARGE FOR SINGLE-PRECISION MULTIPLICATION
   80 J1 = J/B
      J2 = J - J1*B
C FORM PRODUCT
      DO 90 IJ = 1, TG
      C1 = C/B
      C2 = C - B*C1
      I = T1 - IJ
      IX = 0
      IF (I.GT.0) IX = X(I+2)
      RI = J2*IX + C2
      IS = RI/B
      C = J1*IX + C1 + IS
      IP = SPTR - IJ
   90 R(IP) = RI - B*IS
      IF (C.EQ.0) GO TO 70
C CAN ONLY GET HERE IF INTEGER OVERFLOW OCCURRED OR B**T TOO SMALL.
  100 CALL MPERRM (25HERROR OCCURRED IN MPMULI$)
C SET RESULT TO ZERO
  110 Z(1) = 0
C RESTORE STACK POINTER
  120 SPTR = I2
      RETURN
      END
C $$                   ******  MPMULQ  ******
      SUBROUTINE MPMULQ (X, I, J, Y)
C MULTIPLIES MP X BY I/J, GIVING MP RESULT Y.
C ROUNDING DEFINED BY PARAMETER RNDRL IN COMMON /MPCOM/ AS FOLLOWS -
C RNDRL = 0 - AS FOR MPMULI FOLLOWED BY MPDIVI WITH RNDRL = 0.
C             SEE COMMENTS IN MPDIVI, MPMULI AND MPNZR.  ERROR IS
C             LESS THAN B UNITS IN THE LAST PLACE.
C RNDRL = 1, 2, OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
C OVERFLOW/UNDERFLOW MAY OCCUR IN MPMULI/MPDIVI RESPECTIVELY.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, DUMMY
      INTEGER IS, I2, JS, MPGD, TG, TS
      INTEGER B, DUMMY(12), I, J, LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR
      INTEGER MXSPTR, R(1), RNDRL, SPTR, T, X(1), Y(1)
C CHECK FOR DIVISION BY ZERO.
      IF (J .EQ. 0) CALL MPERRM (
     $  37HATTEMPTED DIVISION BY ZERO IN MPMULQ$)
C CHECK FOR MULTIPLICATION BY ZERO.
      IF (I.NE.0) GO TO 10
      Y(1) = 0
      RETURN
C REDUCE TO LOWEST TERMS
   10 IS = I
      JS = J
      CALL MPGCD (IS, JS)
      IF (IABS(IS).EQ.1) GO TO 30
C CHECK ROUNDING OPTIONS
      IF (RNDRL.GT.0) GO TO 20
C HERE RNDRL = 0, SO USE SIMPLE METHOD.
      CALL MPMULI (X, IS, Y)
      CALL MPDIVI (Y, JS, Y)
      RETURN
C HERE RNDRL. GT. 0, SO USE ENOUGH GUARD DIGITS THAT MULTIPLICATION
C IS EXACT.
   20 TS = T
      T = T + MPGD (IS)
      TG = T
      CALL MPNEW (I2)
      CALL MPMOVE (X, TS, R(I2), TG)
      CALL MPMULI (R(I2), IS, R(I2))
      CALL MPDIVI (R(I2), JS, R(I2))
C ROUND RESULT
      CALL MPMOVE (R(I2), TG, Y, TS)
C RESTORE T AND STACK POINTER
      T = TS
      SPTR = I2
      RETURN
C HERE IS = +-1
   30 CALL MPDIVI (X, IS*JS, Y)
      RETURN
      END
C $$                   ******  MPMULS  ******
      SUBROUTINE MPMULS (X, I, J, K, L)
C SETS X = X*I*J/(K*L) FOR MP X, INTEGER I, J, K, L,
C K*L NONZERO.  CALLS MPMULQ ONCE IF I*J AND K*L NOT TOO LARGE,
C OTHERWISE MPMULQ CALLED TWICE.
C ROUNDING NOT BEST POSSIBLE, BUT DIRECTED ROUNDING
C IS IN THE CORRECT DIRECTION.
      INTEGER IJ, IS, KL, KS, MPPARN, MXINT
      INTEGER I, J, K, L, X(1)
      IF ((J.EQ.0).OR.(L.EQ.0)) GO TO 30
C SEE IF I*J OR K*L MIGHT OVERFLOW.
      MXINT = MPPARN(16)
      IF ((IABS(I) .GT. (MXINT/IABS(J))) .OR.
     $    (IABS(K) .GT. (MXINT/IABS(L)))) GO TO 30
C HERE SAFE TO FORM I*J AND K*L.
      IJ = I*J
      KL = K*L
C WORTHWHILE TO CHECK FOR SPECIAL CASES HERE.
      IF (IJ.NE.1) GO TO 10
      CALL MPDIVI (X, KL, X)
      RETURN
   10 IF (KL.NE.1) GO TO 20
      CALL MPMULI (X, IJ, X)
      RETURN
   20 CALL MPMULQ (X, IJ, KL, X)
      RETURN
C HERE SPLIT UP INTO TWO CALLS, TAKING CARE FOR DIRECTED ROUNDING.
   30 IS = I
      IF (J.LT.0) IS = -IS
      KS = K
      IF (L.LT.0) KS = -KS
      CALL MPMULQ (X, IS, KS, X)
      CALL MPMULQ (X, IABS(J), IABS(L), X)
      RETURN
      END
C $$                   ******  MPNE  ******
      LOGICAL FUNCTION MPNE (X, Y)
C RETURNS LOGICAL VALUE OF (X .NE. Y) FOR MP X AND Y.
C X AND/OR Y MAY BE PACKED OR UNPACKED.
      INTEGER MPCOMP, X(1), Y(1)
      MPNE = (MPCOMP(X,Y) .NE. 0)
      RETURN
      END
C $$                   ******  MPNEG  ******
      SUBROUTINE MPNEG (X, Y)
C SETS Y = -X FOR MP NUMBERS X AND Y
C Y WILL BE PACKED IF X IS.
      INTEGER X(1), Y(1)
      CALL MPSTR (X, Y)
      Y(1) = -Y(1)
      RETURN
      END
C $$                   ******  MPNEW  ******
      SUBROUTINE MPNEW (I)
C RETURNS INDEX I SUCH THAT WORDS I, ... , I+T+1 OF BLANK COMMON
C ARE AVAILABLE FOR USE, UPDATES STACK POINTER SPTR ETC.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, DUMMY(21), I, T
      CALL MPNEW2 (I, T+2)
      RETURN
      END
C $$                   ******  MPNEW2  ******
      SUBROUTINE MPNEW2 (I, J)
C RETURNS I SUCH THAT WORDS I, ... , I+ABS(J)-1 OF BLANK COMMON
C ARE AVAILABLE FOR USE, UPDATES STACK POINTER SPTR ETC.
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR, DUMMY
      INTEGER B, DUMMY(15), I, J, LUN, M, MXR, MXSPTR, MNSPTR, SPTR, T
C ALLOCATE SPACE ON STACK
      I = SPTR
      SPTR = I + IABS(J)
C CHECK FOR STACK OVERFLOW AND UPDATE MXSPTR.
C USEFUL TO CHECK VALIDITY OF PARAMETERS IN COMMON /MPCOM/
C IF TOP LEVEL CALL, TOO.
      IF ((SPTR.GT.MXSPTR) .OR. (MNSPTR.GE.I)) CALL MPCHK
      RETURN
      END
C $$                   ******  MPNZR  ******
      SUBROUTINE MPNZR (RS, EXPN, Z, A, KG)
C
C ASSUMES (T+KG)-DIGIT FRACTION IN A(1), ... , A(T+KG),
C KG .GE. 0, SIGN = RS, EXPONENT = EXPN.
C A(1) AND Z(3) MAY HAVE THE SAME ADDRESS.
C NORMALIZES AND RETURNS MP RESULT IN Z.  A IS DESTROYED.
C
C ROUNDING DEPENDS ON VALUE OF RNDRL (IN COMMON /MPCOM/) AS FOLLOWS -
C
C   0 - ROUND TOWARDS ZERO (I.E. CHOP OR TRUNCATE).  THE RESULTING
C       ERROR IS LESS THAN 1 ULP (UNIT IN THE LAST PLACE).
C       THIS IS THE DEFAULT (IF MPSET USED).  IT IS THE FASTEST OPTION
C       AND IS SATISFACTORY FOR MOST PURPOSES.
C       NOTE - RNDRL = 0 IS ASSUMED IF KG IS ZERO.
C
C   1 - ROUND TO NEAREST, PREFERRING EVEN LAST DIGIT IF TIE.
C       MUST HAVE KG.GT.0 TO BE MEANINGFUL.  ERROR .LE. 1/2 ULP IF
C       KG (THE NUMBER OF GUARD DIGITS) IS LARGE ENOUGH.
C       THIS OPTION GIVES WORST-CASE ERROR BOUNDS HALF AS LARGE AS
C       FOR RNDRL = 0, AND AVERAGE-CASE ERROR CONSIDERABLY BETTER
C       THAN FOR RNDRL = 0.  HOWEVER, IF RNDRL = 0 DOES NOT GIVE
C       SUFFICIENT ACCURACY IS IS USUALLY PREFERABLE TO INCREASE T
C       RATHER THAN USE RNDRL = 1.
C
C   2 - ROUND DOWN (TOWARDS -INFINITY).  (MUST HAVE KG .GT. 0)
C
C   3 - ROUND UP   (TOWARDS +INFINITY).  (MUST HAVE KG .GT. 0)
C       THESE LAST TWO OPTIONS ARE USEFUL FOR INTERVAL ARITHMETIC AS
C       THEY GIVE RIGOROUS LOWER AND UPPER BOUNDS.
C
C NOTE - COMMENTS IN OTHER ROUTINES OFTEN REFER TO THE ABOVE
C        DEFINITIONS OF ROUNDING OPTIONS.  THE COMMENTS REGARDING
C        KG ABOVE REFER ONLY TO THIS SUBROUTINE.
C
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, DUMMY
      INTEGER B2, I, INM, INP, IS, J, K, RE, TG, TWO, T1
      INTEGER A(1), B, DUMMY(12), EXPN, KG, LUN, M, MNEXPN, MNSPTR
      INTEGER MXEXPN, MXR, MXSPTR, RNDRL, RS, SPTR, T, Z(1)
      TWO = 2
C CHECK THAT SIGN = +-1
C THE FOLLOWING MESSAGE IS USUALLY CAUSED BY EXCEEDING
C ARRAY BOUNDS.  CHECK THAT ARRAYS USED FOR MP NUMBERS HAVE
C DIMENSION AT LEAST T+2.
      IF (IABS(RS) .GT. 1) CALL MPERRM (
     $  38HSIGN NOT 0, +1 OR -1 IN CALL TO MPNZR$)
C CHECK FOR ZERO
      IF (RS .NE. 0) GO TO 20
C RETURN ZERO.
   10 Z(1) = 0
      RETURN
C SAVE EXPONENT LOCALLY
   20 RE = EXPN
      T1 = T + 1
      TG = T + KG
C LOOK FOR FIRST NONZERO DIGIT
      DO 30 I = 1, TG
      IS = I - 1
      IF (A(I).GT.0) GO TO 40
   30 CONTINUE
C FRACTION ZERO
      GO TO 10
C SEE IF NUMBER IS NORMALIZED.
   40 IF (IS.EQ.0) GO TO 70
C NORMALIZE BY LEFT SHIFTING AND PADDING ON RIGHT WITH ZEROS.
      RE = RE - IS
      INM = TG - IS
      DO 50 J = 1, INM
      K = J + IS
   50 A(J) = A(K)
      INP = INM + 1
      DO 60 J = INP, TG
   60 A(J) = 0
C CHECK VARIOUS ROUNDING OPTIONS DESCRIBED ABOVE.
   70 IF ((RNDRL.EQ.0).OR.(KG.EQ.0).OR.
     $   ((RNDRL.EQ.2).AND.(RS.GT.0)).OR.
     $   ((RNDRL.EQ.3).AND.(RS.LT.0))) GO TO 160
      IF (RNDRL.EQ.1) GO TO 90
C HERE ROUND AWAY FROM ZERO IF ANY OF A(T+1), ... , A(T+KG) NONZERO.
      DO 80 I = T1, TG
      IF (A(I).NE.0) GO TO 120
   80 CONTINUE
C HERE A(T+1) = ... = A(T+KG) = 0 SO CAN TRUNCATE.
      GO TO 160
C ROUND TO NEAREST HERE.  NEED TO TREAT ODD AND EVEN BASES DIFFERENTLY.
   90 B2 = B/2
      IF ((2*B2).NE.B) GO TO 140
C B EVEN.  ROUND AWAY FROM ZERO IF A(T+1).GE.B2 UNLESS
C A(T) EVEN, A(T+1) = B2, AND A(T+2) = ... = A(T+KG) = 0.
      IF (A(T1) - B2) 160, 100, 120
  100 IF (MOD(A(T),2).NE.0) GO TO 120
      I = T1
  110 I = I + 1
      IF (I.GT.TG) GO TO 160
      IF (A(I).EQ.0) GO TO 110
C ROUND AWAY FROM ZERO
  120 DO 130 J = 1, T
      I = T1 - J
      A(I) = A(I) + 1
      IF (A(I).LT.B) GO TO 160
  130 A(I) = 0
C EXCEPTIONAL CASE, ROUNDED UP TO .10000...
      RE = RE + 1
      A(1) = 1
      GO TO 160
C ODD BASE, ROUND AWAY FROM ZERO IF .A(T+1) ... A(T+KG) .GT. 1/2
  140 DO 150 I = T1, TG
      IF (A(I) - B2) 160, 150, 120
  150 CONTINUE
C CHECK FOR OVERFLOW
  160 IF (RE .GT. M) CALL MPOVFL (Z)
C CHECK FOR UNDERFLOW
      IF (RE.LE.(-M)) GO TO 180
C STORE RESULT IN Z
      Z(1) = RS
      Z(TWO) = RE
      DO 170 I = 1, T
  170 Z(I+2) = A(I)
C UPDATE MAXIMUM AND MINIMUM EXPONENT INDICATORS
      MXEXPN = MAX0 (MXEXPN, RE)
      MNEXPN = MIN0 (MNEXPN, RE)
      RETURN
C UNDERFLOW HERE
  180 CALL MPUNFL (Z)
      RETURN
      END
C $$                   ******  MPOUT  ******
      SUBROUTINE MPOUT (X, C, P, N)
C
C CONVERTS MULTIPLE-PRECISION X TO FP.N FORMAT IN C,
C WHICH MAY BE PRINTED UNDER PA1 FORMAT.  NOTE THAT
C N = -1 IS ALLOWED, AND EFFECTIVELY GIVES IP FORMAT.
C DIGITS AFTER THE DECIMAL POINT ARE BLANKED OUT IF
C THEY COULD NOT BE SIGNIFICANT.
C EFFICIENCY IS HIGHER IF B IS A POWER OF 10 THAN IF NOT.
C X MAY BE PACKED OR UNPACKED.
C DIMENSION OF C MUST BE AT LEAST P.
C C IS AN INTEGER ARRAY, P AND N ARE INTEGERS.
C
C ROUNDING OF DECIMAL OUTPUT IS DETERMINED BY THE PARAMETER
C RNDRL IN COMMON /MPCOM/, AS FOLLOWS -
C
C CALL MPSETR (0) OR 1 - ROUND TO APPROXIMATLELY NEAREST DECIMAL NUMBER
C                  REPRESENTABLE IN THE SPECIFIED FORMAT.
C                  ERROR IN CONVERSION TO DECIMAL IS LESS
C                  THAN 0.6 UNITS IN THE LAST DECIMAL PLACE.
C RNDRL = 2 -      ROUND DOWN (TOWARDS -INFINITY) TO A DECIMAL
C                  NUMBER REPRESENTABLE IN THE SPECIFIED FORMAT.
C RNDRL = 3 -      ROUND UP (TOWARDS +INFINITY) TO A DECIMAL NUMBER
C                  REPRESENTABLE IN THE SPECIFIED FORMAT.
C
C OUTPUT BASE IS USUALLY 10 (DEFAULT SET BY MPSET), BUT
C MAY BE CHANGED TO ANY OF 2, ... , 16 BY CHANGING THE
C PARAMETER OUTBAS IN COMMON /MPCOM/ (SEE MPPARN).
C
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, IB, IP, IR, IS, ISZ, ITP, IZ, I1, I2, I3, J, JD,
     $  JP, NMAX, NP, OUTBAS, SV, TG, TP,
     $  B, C(1), DUMMY(21), N, P, R(1), T, X(1),
     $  MPCHGB, MPDIGW, MPGD, MPPARN,
     $  BLANK, PERIOD, MINUS, STAR
      DATA BLANK, PERIOD, MINUS, STAR /1H , 1H., 1H-, 1H*/
C CHECK B, T, OUTBAS ETC. FOR LEGALITY.
      CALL MPCHK
C SAVE T ETC.
      CALL MPSAVN (SV)
C GET OUTPUT BASE.
      OUTBAS = MPPARN (20)
C CHECK LEGALITY OF PARAMETERS N AND P.
      IF ((N .LT. (-1)) .OR. (P .LE. N) .OR. (P .LE. 0))
     $  CALL MPERRM (36HN AND/OR P ILLEGAL IN CALL TO MPOUT$)
C COMPUTE DISPLACEMENTS.
      NP = P - N
      IP = NP - 1
C COMPUTE POWER OF OUTBAS WHICH WE CAN SAFELY MULTIPLY AND
C DIVIDE BY (THIS SAVES TIME).
      IB = MPPARN(16)/OUTBAS
      TP = OUTBAS
      ITP = 1
   10 IF ((TP .GT. IB).OR.(TP .EQ. B)) GO TO 20
      TP = TP*OUTBAS
      ITP = ITP + 1
      GO TO 10
C COMPUTE GUARD DIGITS REQUIRED, MOVE X ETC.
   20 T = T + 1 + MPGD (MAX0 (50, TP))
      TG = T
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
C USE TRUNCATION (USUALLY) FOR INTERNAL ARITHMETIC
      CALL MPSETR (0)
C PUT FORMATTED ZERO IN C
      DO 30 I = 1, P
      C(I) = BLANK
      IF (I .GE. IP) C(I) = MPDIGW(0)
      IF (I .EQ. NP) C(I) = PERIOD
   30 CONTINUE
C GET SIGN OF X, CHECK FOR ZERO
      IS = R(I2)
      IF (IS .EQ. 0) GO TO 160
      R(I2) = 1
C COMPUTE MAXIMUM NUMBER OF NONZERO DIGITS WHICH WE CAN
C MEANINGFULLY GIVE AFTER DECIMAL POINT.
      NMAX = MAX0 (0, MIN0 (N, MPCHGB (OUTBAS, IABS(B), MIN0 (4*N,
     $  MAX0 (0, R(SV) - R(I2+1))))))
C COMPUTE ROUNDING CONSTANT FOR DECIMAL OUTPUT
      IR = 1
      IF (R(SV+2) .GE. 2) IR = 2*(R(SV+2)-2)
      IF (IS.LT.0) IR = 2 - IR
C CHANGE ROUNDING OPTION IF NECESSARY FOR DIRECTED ROUNDING
      IF (IR .EQ. 2) CALL MPSETR (3)
      CALL MPCQM (IR, 2, R(I3))
      IF (NMAX .GT. 0) CALL MPSCAL (R(I3), OUTBAS, (-NMAX))
C ADD ROUNDING CONSTANT TO ABS(X).
      CALL MPADD (R(I2), R(I3), R(I2))
C IP PLACES BEFORE POINT, SO DIVIDE BY OUTBAS**IP
      IF (IP .GT. 0) CALL MPSCAL (R(I2), OUTBAS, (-IP))
      IZ = 0
C ROUND RESULT TO R(SV)+1 DIGITS FOR DIRECTED ROUNDINGS (SO SUBSEQUENT
C ARITHMETIC EXACT).
      IF (R(SV+2) .LE. 1) GO TO 40
      CALL MPMOVE (R(I2), TG, R(I2), R(SV)+1)
      CALL MPMOVE (R(I2), R(SV)+1, R(I2), TG)
C NOW USE CHOPPED ARITHMETIC
   40 CALL MPSETR (0)
C CHECK THAT NUMBER IS LESS THAN ONE
      IF (R(I2+1) .GT. 0) GO TO 120
      IF (IP .LE. 0) GO TO 90
C PUT DIGITS BEFORE POINT IN
      JD = 1
      DO 80 I = 1, IP
      IF (JD .GT. 1) GO TO 70
      IF ((I+ITP) .LE. (IP+1)) GO TO 50
C MULTIPLY BY OUTBAS, TRUNCATING RESULT
      CALL MPMULI (R(I2), OUTBAS, R(I2))
      JD = OUTBAS
      GO TO 60
C HERE WE CAN MULTIPLY BY A POWER OF OUTBAS TO SAVE TIME
   50 CALL MPMULI (R(I2), TP, R(I2))
      JD = TP
C GET INTEGER PART
   60 CALL MPCMI (R(I2), JP)
C AND FRACTIONAL PART
      CALL MPCMF (R(I2), R(I2))
   70 JD = JD/OUTBAS
C GET NEXT DECIMAL DIGIT
      J = JP/JD
      JP = JP - J*JD
      ISZ = IZ
      IF ((J .GT. 0).OR.(I .EQ. IP)) IZ = 1
      IF (IZ .GT. 0) C(I) = MPDIGW(J)
      IF ((IZ .EQ. ISZ).OR.(IS .GT. 0)) GO TO 80
      IF (I .EQ. 1) GO TO 120
      C(I-1) = MINUS
   80 CONTINUE
   90 IF (NMAX .LE. 0) GO TO 140
C PUT IN DIGITS AFTER DECIMAL POINT
      JD = 1
      DO 110 I = 1, NMAX
      IF (JD .GT. 1) GO TO 100
      CALL MPMULI (R(I2), TP, R(I2))
      CALL MPCMI (R(I2), JP)
      CALL MPCMF (R(I2), R(I2))
      JD = TP
  100 JD = JD/OUTBAS
      J = JP/JD
      JP = JP - J*JD
      I1 = NP + I
  110 C(I1) = MPDIGW(J)
      GO TO 140
C ERROR OCCURRED, RETURN ASTERISKS.
  120 DO 130 I = 1, P
  130 C(I) = STAR
      GO TO 160
C BLANK OUT ANY NONSIGNIFICANT TRAILING ZEROS
  140 IF (NMAX .GE. N) GO TO 160
      I1 = NP + NMAX + 1
      DO 150 I = I1, P
  150 C(I) = BLANK
C RESTORE STACK POINTER ETC. AND RETURN.
  160 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPOUTE  ******
      SUBROUTINE MPOUTE (X, C, J, P)
C
C ASSUMES X IS AN MP NUMBER AND C AN INTEGER ARRAY OF DIMENSION AT
C LEAST P .GE. 4.  ON RETURN J IS THE EXPONENT (TO BASE OUTBAS) OF X
C AND THE FRACTION IS IN C, READY TO BE PRINTED IN A1 FORMAT.
C FOR EXAMPLE, WE COULD PRINT J AND C IN (I10, 1X, PA1) FORMAT.
C THE FRACTION HAS ONE PLACE BEFORE DECIMAL POINT AND P-3 AFTER.
C J AND P ARE INTEGERS.  X MAY BE PACKED OR UNPACKED.
C
C ROUNDING NOT BEST POSSIBLE, BUT DIRECTED ROUNDINGS (RNDRL = 2
C OR 3) GIVE CORRECT BOUNDS - SEE COMMENTS IN MPOUT.
C
C DEFAULT OUTPUT BASE IS 10, BUT THIS MAY BE CHANGED - SEE
C COMMENTS ON OUTBAS IN MPPARN.
C
      COMMON R
      INTEGER C(1), ISN, I2, J, P, R(1), SV, X(1),
     $  BLANK, MINUS
      LOGICAL MPIS
      DATA BLANK, MINUS /1H , 1H-/
      CALL MPSAVN (SV)
      IF (P .LT. 4) CALL MPERRM (27HP .LT. 4 IN CALL TO MPOUTE$)
C ALLOCATE TEMPORARY SPACE.
      CALL MPNEW (I2)
      CALL MPCMEF (X, J, R(I2))
      CALL MPOUT (R(I2), C, P, P-3)
C SEE IF OUTPUT OF MPOUT WAS ROUNDED UP TO OUTBAS
      IF (MPIS (C(1), BLANK) .OR. MPIS (C(1), MINUS)) GO TO 10
C IT WAS, SO ADD 1 TO J AND CONVERT SIGN TO MP
      J = J + 1
      ISN = R(I2)
      CALL MPCIM (ISN, R(I2))
      CALL MPOUT (R(I2), C, P, P-3)
C RESTORE STACK POINTER ETC AND RETURN.
   10 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPOUTF  ******
      SUBROUTINE MPOUTF (X, P, N, IFORM, ERR)
C
C WRITES MP NUMBER X ON LOGICAL UNIT LUN (FOURTH WORD OF
C COMMON /MPCOM/) IN FORMAT IFORM, AFTER CONVERTING TO FP.N
C REPRESENTATION (I.E. P CHARACTERS INCLUDING N AFTER
C THE DECIMAL POINT).  THE DEFAULT OUTPUT BASE IS 10 (DECIMAL),
C BUT THIS MAY BE CHANGED BY CHANGING OUTBAS IN COMMON /MPCOM/.
C IFORM SHOULD CONTAIN A FORMAT WHICH ALLOWS FOR OUTPUT OF P
C WORDS IN A1 FORMAT, PLUS ANY DESIRED HEADINGS, SPACING ETC.
C (HOLLERITH CONSTANTS IN IFORM ARE NONSTANDARD, BUT USUALLY OK.)
C ERR IS RETURNED AS TRUE IF P NOT POSITIVE OR IF MPIO DETECTS
C AN ERROR WHEN WRITING ON UNIT LUN, OTHERWISE FALSE.
C X MAY BE PACKED OR UNPACKED OF MPOUTF IS CALLED DIRECTLY.
C SPACE REQUIRED = P + O(T) WORDS.
C FOR ROUNDING OPTIONS SEE COMMENTS IN SUBROUTINE MPOUT.
C
      COMMON R
      INTEGER IFORM(1), I2, MPPARN, N, P, R(1), SV, X(1)
      LOGICAL ERR
      ERR = .TRUE.
C RETURN WITH ERROR FLAG SET IF OUTPUT FIELD WIDTH P NOT POSITIVE
      IF (P.LE.0) RETURN
      CALL MPSAVN (SV)
C ALLOCATE P WORDS OF STACK SPACE.
      CALL MPNEW2 (I2, P)
C CONVERT X TO BASE OUTBAS
      CALL MPOUT (X, R(I2), P, N)
C AND WRITE ON UNIT LUN WITH FORMAT IFORM
      CALL MPIO (R(I2), P, MPPARN(4), IFORM, ERR)
C RESTORE STACK POINTER AND RETURN.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPOUT2  ******
      SUBROUTINE MPOUT2 (X, C, P, N, OUTBAS)
C THIS ROUTINE IS REDUNDANT, BUT IS INCLUDED FOR COMPATIBILITY
C WITH EARLIER VERSIONS OF THE MP PACKAGE.
      INTEGER X(1), C(1), P, N, OUTBAS, OUTSAV, MPPARN
C SAVE AND CHANGE OUTPUT BASE BEFORE CALLING MPOUT.
      OUTSAV = MPPARN (20)
      CALL MPPARC (20, OUTBAS)
      CALL MPOUT (X, C, P, N)
C RESTORE OUTPUT BASE
      CALL MPPARC (20, OUTSAV)
      RETURN
      END
C $$                   ******  MPOVFL  ******
      SUBROUTINE MPOVFL (X)
C CALLED ON MULTIPLE-PRECISION OVERFLOW, I.E. WHEN THE
C EXPONENT OF MP NUMBER X WOULD EXCEED M.
C EXECUTION IS TERMINATED WITH AN ERROR MESSAGE
C AFTER CALLING MPMAXR(X) AND SETTING MXEXPN = M + 1.
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, DUMMY
      INTEGER B, DUMMY(14), LUN, M, MNSPTR, MXEXPN, MXR, MXSPTR, SPTR,
     $  T, X(1)
C M MAY HAVE BEEN OVERWRITTEN, SO CHECK B, T, M ETC.
      CALL MPCHK
C SET X TO LARGEST POSSIBLE POSITIVE NUMBER
      CALL MPMAXR (X)
C SET MXEXPN TO M + 1 (LARGEST VALID EXPONENT IS M)
      MXEXPN = M + 1
      CALL MPERRM (37HCALL TO MPOVFL, MP OVERFLOW OCCURRED$)
C MPERRM DOES NOT RETURN, SO NEVER GET HERE.
      RETURN
      END
C $$                   ******  MPPACK  ******
      SUBROUTINE MPPACK (X, Y)
C ASSUMES THAT X IS AN MP NUMBER STORED AS USUAL IN AN INTEGER
C ARRAY OF DIMENSION AT LEAST T+2, AND Y IS AN INTEGER ARRAY
C OF DIMENSION AT LEAST INT((T+3)/2).
C X IS STORED IN A COMPACT FORMAT IN Y, AND MAY BE RETRIEVED
C BY CALLING MPUNPK (Y, X).
C IF X IS ALREADY IN COMPACT (PACKED) FORMAT, EFFECT IS
C THE SAME AS FOR MPSTR (X, Y).
C MPPACK AND MPUNPK ARE USEFUL IF SPACE IS CRITICAL, FOR EXAMPLE
C WHEN WORKING WITH LARGE ARRAYS OF MP NUMBERS.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, T, X(1), Y(1), DUMMY(21), I, J, X2, TWO
C CHECK WHETHER X IS IN PACKED FORMAT OR NOT.
      IF (IABS(X(1)) .EQ. 1) GO TO 10
C HERE X IS ZERO OR IN PACKED FORMAT.
      CALL MPSTR (X, Y)
      RETURN
C HERE X IS NONZERO AND IN UNPACKED FORMAT.
   10 J = T/2
      TWO = 2
      X2 = X(TWO)
C NOW PACK TWO DIGITS OF X IN EACH WORD OF Y.
      DO 20 I = 1, J
   20 Y(I+1) = B*X(2*I+1) + X(2*I+2)
C FIX UP LAST DIGIT IF T ODD.
      IF (MOD (T, 2) .NE. 0) Y(J+2) = B*X(T+2)
C MOVE SECOND WORD OF Y, INSERT SIGN AND EXPONENT.
      Y(1) = X(1)*Y(TWO)
      Y(TWO) = X2
      RETURN
      END
C $$                   ******  MPPARA  ******
      INTEGER FUNCTION MPPARA (A)
C RETURNS THE WORD OF COMMON /MPCOM/ CORRESPONDING TO THE HOLLERITH
C STRING A.  FOR DETAILS SEE SUBROUTINE MPPARM.
      INTEGER A(1), N
      CALL MPPARM (A, .FALSE., N)
      MPPARA = N
      RETURN
      END
C $$                   ******  MPPARB  ******
      SUBROUTINE MPPARB (I, A)
C SETS THE WORD OF COMMON /MPCOM/ CORRESPONDING TO THE HOLLERITH STRING
C A TO THE INTEGER VALUE I.  FOR DETAILS SEE SUBROUTINE MPPARM.
      INTEGER A(1), I, J
      J = I
      CALL MPPARM (A, .TRUE., J)
      RETURN
      END
C $$                   ******  MPPARC  ******
      SUBROUTINE MPPARC (N, J)
C SETS THE N-TH WORD OF COMMON /MPCOM/ TO J IF 1 .LE. N .LE. 23,
C ERROR OTHERWISE.  FASTER BUT LESS MNEMONIC THAN MPPARB.
C FOR THE MEANINGS OF WORDS 1 TO 23 OF COMMON /MPCOM/, SEE
C THE COMMENTS IN SUBROUTINE MPPARM.  FOR THEIR DEFAULT
C SETTINGS SEE MPSET.
      COMMON /MPCOM/ MPC
      INTEGER J, MPC(23), N
      IF ((N .LE. 0) .OR. (N .GT. 23)) CALL MPERRM (
     $  28HILLEGAL N IN CALL TO MPPARC$)
      MPC(N) = J
C CHECK LEGALITY OF T ETC. IF CALLED FROM TOP LEVEL,
C I.E. IF SPTR .LE. MNSPTR.
      IF (MPC(6) .LE. MPC(8)) CALL MPCHK
      RETURN
      END
C $$                   ******  MPPARM  ******
      SUBROUTINE MPPARM (HOLL, SET, J)
C
C HOLL IS A HOLLERITH STRING, SET A LOGICAL VALUE, J AN INTEGER.
C IF THE FIRST THREE CHARACTERS OF HOLL AGREE WITH ONE OF -
C
C (1)  BASE   (THE MP BASE),
C (2)  NUMDIG (THE NUMBER OF DIGITS),
C (3)  MAXEXP (THE MAXIMUM ALLOWABLE EXPONENT),
C (4)  LUN    (LOGICAL UNIT FOR OUTPUT),
C (5)  MXR    (DIMENSION OF BLANK COMMON, USED FOR STACK),
C (6)  SPTR   (POINTER TO 1 WORD ABOVE TOP OF STACK),
C (7)  MXSPTR (MAXIMUM VALUE OF SPTR WHICH HAS OCCURRED),
C (8)  MNSPTR (POINTER TO BOTTOM OF STACK, I.E. MINIMUM OF SPTR),
C (9)  MXEXPN (MAXIMUM EXPONENT WHICH HAS OCCURRED),
C (10) MNEXPN (MINIMUM EXPONENT WHICH HAS OCCURRED),
C (11) RNDRL  (INDICATOR FOR TYPE OF ROUNDING - SEE MPNZR),
C (12) KTUNFL (NUMBER OF UNDERFLOWS WHICH HAVE OCCURRED),
C (13) MXUNFL (MAXIMUM UNDERFLOWS ALLOWED + 1, SEE MPUNFL),
C (14) DECPL  (EQUIVALENT NUMBER OF FLOATING DECIMAL PLACES -
C              ACTUALLY THE VALUE OF THE SECOND ARGUMENT IN THE LAST
C              CALL TO MPSET2,
C (15) MT2    (SIZE OF ARRAYS FOR MP NUMBERS - ACTUALLY VALUE OF MT2
C             IN LAST CALL TO MPSET2),
C (16) MXINT  (MAXIMUM POSITIVE INTEGER OF FORM 2**K - 1, SEE MPLARG),
C (17) EXWID  (WIDTH OF EXPONENT FIELD FOR MPFOUT),
C (18) INRECL (INPUT RECORD LENGTH FOR MPFIN, .LE. 80),
C (19) INBASE (INPUT BASE FOR MPIN ETC., 2 .LE. INBASE .LE. 16),
C (20) OUTBAS (OUTPUT BASE FOR MPOUT, MPOUTE, MPFOUT ETC.,
C              2 .LE. OUTBAS .LE. 16),
C (21) EXPCH  (EXPONENT CHARACTER FOR MPFOUT, DEFAULT IS E),
C (22) CHWORD (NUMBER OF CHARACTERS PER WORD, RETURNED BY MPUPW),
C (23) ONESCP (ONES COMPLEMENT INDICATOR - SEE MPSET2 AND MPUPW),
C
C THEN THE CORRESPONDING WORD IN COMMON /MPCOM/ IS EITHER
C SET TO J (IF SET = .TRUE.) OR RETURNED IN J (IF SET = .FALSE.).
C
C MPSET2 SETS THE ABOVE TO REASONABLE DEFAULT VALUES.  FOR DETAILS
C SEE THE COMMENTS IN SUBROUTINE MPSET2.
C
C THE DESCRIPTION ABOVE OF BASE, ... , ONESCP APPLIES TO
C MPPARA, MPPARB, MPPARC AND MPPARN AS WELL AS MPPARM.
C
      INTEGER C(3), D1(23), D2(23), D3(23), HOLL(1), I, J, L, N,
     $  MPPARN
      LOGICAL MPIS, SET
      DATA D1  (1), D2  (1), D3  (1) /1HB, 1HA, 1HS/
      DATA D1  (2), D2  (2), D3  (2) /1HN, 1HU, 1HM/
      DATA D1  (3), D2  (3), D3  (3) /1HM, 1HA, 1HX/
      DATA D1  (4), D2  (4), D3  (4) /1HL, 1HU, 1HN/
      DATA D1  (5), D2  (5), D3  (5) /1HM, 1HX, 1HR/
      DATA D1  (6), D2  (6), D3  (6) /1HS, 1HP, 1HT/
      DATA D1  (7), D2  (7), D3  (7) /1HM, 1HX, 1HS/
      DATA D1  (8), D2  (8), D3  (8) /1HM, 1HN, 1HS/
      DATA D1  (9), D2  (9), D3  (9) /1HM, 1HX, 1HE/
      DATA D1 (10), D2 (10), D3 (10) /1HM, 1HN, 1HE/
      DATA D1 (11), D2 (11), D3 (11) /1HR, 1HN, 1HD/
      DATA D1 (12), D2 (12), D3 (12) /1HK, 1HT, 1HU/
      DATA D1 (13), D2 (13), D3 (13) /1HM, 1HX, 1HU/
      DATA D1 (14), D2 (14), D3 (14) /1HD, 1HE, 1HC/
      DATA D1 (15), D2 (15), D3 (15) /1HM, 1HT, 1H2/
      DATA D1 (16), D2 (16), D3 (16) /1HM, 1HX, 1HI/
      DATA D1 (17), D2 (17), D3 (17) /1HE, 1HX, 1HW/
      DATA D1 (18), D2 (18), D3 (18) /1HI, 1HN, 1HR/
      DATA D1 (19), D2 (19), D3 (19) /1HI, 1HN, 1HB/
      DATA D1 (20), D2 (20), D3 (20) /1HO, 1HU, 1HT/
      DATA D1 (21), D2 (21), D3 (21) /1HE, 1HX, 1HP/
      DATA D1 (22), D2 (22), D3 (22) /1HC, 1HH, 1HW/
      DATA D1 (23), D2 (23), D3 (23) /1HO, 1HN, 1HE/
C UNPACK FIRST THREE CHARACTERS OF A
      CALL MPUPK (HOLL, C, 3, L)
      IF (L.NE.3) GO TO 20
C SEE IF THEY MATCH ANY OF THOSE EXPECTED.
      DO 10 I = 1, 23
      N = I
      IF (MPIS (C(1), D1(I)) .AND.
     $    MPIS (C(2), D2(I)) .AND.
     $    MPIS (C(3), D3(I))) GO TO 30
   10 CONTINUE
C HERE A HAS LENGTH LESS THAN 3 OR NO MATCH FOUND.
   20 CALL MPERRM (43HILLEGAL HOLLERITH STRING IN CALL TO MPPARM$)
C HERE A MATCH WAS FOUND AT THE N-TH VALUE.
   30 IF (SET) CALL MPPARC (N, J)
      IF (.NOT. SET) J = MPPARN (N)
      RETURN
      END
C $$                   ******  MPPARN  ******
      INTEGER FUNCTION MPPARN (N)
C RETURNS THE N-TH WORD OF COMMON /MPCOM/ IF 1 .LE. N .LE. 23,
C ZERO OTHERWISE.  FASTER BUT LESS MNEMONIC THAN MPPARA.
C FOR THE MEANINGS OF WORDS 1 TO 23 OF COMMON /MPCOM/, SEE
C THE COMMENTS IN SUBROUTINE MPPARM.  FOR THEIR DEFAULT
C SETTINGS SEE MPSET.
      COMMON /MPCOM/ MPC
      INTEGER MPC(23), N
      MPPARN = 0
      IF ((N .GT. 0) .AND. (N .LE. 23)) MPPARN = MPC(N)
      RETURN
      END
C $$                   ******  MPPI  ******
      SUBROUTINE MPPI (X)
C SETS MP X = PI TO THE AVAILABLE PRECISION.
C USES PI/4 = 4.ARCTAN(1/5) - ARCTAN(1/239), TIME = O(T**2).
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I2, I3, SV, TG
      INTEGER B, DUMMY(21), MPGD, R(1), T, X(1)
C SAVE T ETC.
      CALL MPSAVN (SV)
C SEE IF ANY GUARD DIGITS REQUIRED
      IF ((R(SV+2).NE.0).OR.(B.LE.100)) GO TO 10
C HERE NO GUARD DIGITS NECESSARY.
C ALLOCATE TEMPORARY SPACE.
      CALL MPNEW (I2)
      CALL MPART1 (5, R(I2))
      CALL MPMULI (R(I2), 4, R(I2))
      CALL MPART1 (239, X)
      CALL MPSUB (R(I2), X, X)
C USE ROUNDED MULTIPLICATION BY 4
      CALL MPSETR (1)
      CALL MPMULI (X, 4, X)
      GO TO 20
C HERE NEED TO USE SOME GUARD DIGITS
   10 T = T + MPGD (100)
      TG = T
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPART1 (5, R(I2))
      CALL MPMULI (R(I2), 4, R(I2))
C TAKE CARE IF DIRECTED ROUNDING REQUIRED.
      CALL MPREVR (1)
      CALL MPART1 (239, R(I3))
      CALL MPSETR (IABS(R(SV+2)))
      CALL MPSUB (R(I2), R(I3), R(I3))
      CALL MPMULI (R(I3), 4, R(I3))
C ROUND RESULT
      CALL MPMOVE (R(I3), TG, X, IABS(R(SV)))
C RESTORE EVERYTHING
   20 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPPIGL  ******
      SUBROUTINE MPPIGL (PI)
C SETS MP PI = 3.14159... TO THE AVAILABLE PRECISION.
C USES THE GAUSS-LEGENDRE ALGORITHM.
C THIS METHOD REQUIRES TIME O(LN(T)M(T)), SO IT IS SLOWER
C THAN MPPI IF M(T) = O(T**2), BUT WOULD BE FASTER FOR
C LARGE T IF A FASTER MULTIPLICATION ALGORITHM WERE USED
C (SEE COMMENTS IN MPMUL).
C FOR A DESCRIPTION OF THE METHOD, SEE - MULTIPLE-PRECISION
C ZERO-FINDING AND THE COMPLEXITY OF ELEMENTARY FUNCTION
C EVALUATION (BY R. P. BRENT), IN ANALYTIC COMPUTATIONAL
C COMPLEXITY (EDITED BY J. F. TRAUB), ACADEMIC PRESS, 1976, 151-176.
C ROUNDING OPTIONS NOT IMPLEMENTED, NO GUARD DIGITS USED.
      COMMON R
      INTEGER IX, I2, I3, I4, PI(1), R(1), SV
C SAVE T ETC.
      CALL MPSAVN (SV)
C USE TRUNCATED ARITHMETIC.
      CALL MPSETR (0)
C ALLOCATE WORKING SPACE.
      CALL MPNEW (I2)
      CALL MPNEW (I3)
      CALL MPNEW (I4)
      CALL MPCIM (1, PI(1))
      CALL MPCQM (1, 2, R(I4))
      CALL MPSQRT (R(I4), R(I4))
      CALL MPCQM (1, 4, R(I3))
      IX = 1
   10 CALL MPSTR (PI(1), R(I2))
      CALL MPADD (PI(1), R(I4), PI(1))
      CALL MPDIVI (PI(1), 2, PI(1))
      CALL MPMUL (R(I2), R(I4), R(I4))
      CALL MPSUB (PI(1), R(I2), R(I2))
      CALL MPMUL (R(I2), R(I2), R(I2))
      CALL MPMULI (R(I2), IX, R(I2))
      CALL MPSUB (R(I3), R(I2), R(I3))
      CALL MPSQRT (R(I4), R(I4))
      IX = 2*IX
C CHECK FOR CONVERGENCE
      IF ((R(I2).NE.0).AND.(R(I2+1).GE.(-R(SV)))) GO TO 10
      CALL MPMUL (PI(1), R(I4), PI(1))
      CALL MPDIV (PI(1), R(I3), PI(1))
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPPOLY  ******
      SUBROUTINE MPPOLY (X, Y, IC, N)
C SETS Y = IC(1) + IC(2)*X + ... + IC(N)*X**(N-1),
C WHERE X AND Y ARE MULTIPLE-PRECISION NUMBERS AND
C IC IS AN INTEGER ARRAY OF DIMENSION AT LEAST N .GT. 0
C ROUNDING NOT BEST POSSIBLE, BUT DIRECTED ROUNDING OPTIONS
C (RNDRL = 2 OR 3) GIVE CORRECT LOWER AND UPPER BOUNDS RESPECTIVLEY.
      COMMON R
      INTEGER I, IC(1), I2, N, R(1), SV, X(1), Y(1)
C SAVE T ETC.
      CALL MPSAVN (SV)
      IF (N .LE. 0) CALL MPERRM (
     $  27HN .LE. 0 IN CALL TO MPPOLY$)
C ALLOCATE TEMPORARY SPACE.
      CALL MPNEW (I2)
      CALL MPCIM (IC(N), R(I2))
      I = N - 1
      IF (I.LE.0) GO TO 20
C LOOP TO COMPUTE POLYNOMIAL, TAKING CARE FOR DIRECTED ROUNDINGS.
   10 IF (MOD (I, 2) .EQ. 0) CALL MPREVR (-X(1))
      CALL MPMUL (R(I2), X, R(I2))
      CALL MPSETR (IABS(R(SV+2)))
      CALL MPADDI (R(I2), IC(I), R(I2))
      I = I - 1
      IF (I.GT.0) GO TO 10
   20 CALL MPSTR (R(I2), Y)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPPWR  ******
      SUBROUTINE MPPWR (X, N, Y)
C RETURNS Y = X**N, FOR MP X AND Y, INTEGER N, WITH 0**0 = 1.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      INTEGER I2, N, R(1), SV, TG, X(1), Y(1)
C SAVE T ETC. THEN INCREASE T AS NECESSARY.
      CALL MPSAVN (SV)
      CALL MPGD3 (N, TG)
C ALLOCATE TEMPORARY SPACE AND MOVE X.
      CALL MPNEW (I2)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      IF (N .GE. 0) GO TO 10
C N .LT. 0
      IF (X(1) .EQ. 0) CALL MPERRM (
     $  38HX = 0 AND N NEGATIVE IN CALL TO MPPWR$)
C HERE N .LT. 0,  X .NE. 0.  CHECK FOR DIRECTED ROUNDINGS.
      IF (MOD (IABS (N), 2) .EQ. 0) CALL MPREVR (-X(1))
      CALL MPREC (R(I2), R(I2))
      CALL MPSETR (IABS(R(SV+2)))
C NOW USE MPPWRA TO FIND R(I2)**ABS(N).
   10 CALL MPPWRA (R(I2), N, R(I2))
C ROUND RESULT
      CALL MPRND (R(I2), TG, Y, IABS(R(SV)), 0)
C RESTORE T ETC. AND RETURN.
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPPWRA  ******
      SUBROUTINE MPPWRA (X, N, Y)
C RETURNS Y = X**ABS(N) FOR MP X AND Y, INTEGER N.  (0**0 = 1)
C USES NO GUARD DIGITS, CHOPPED RATHER THAN ROUNDED ARITHMETIC.
C CALLED BY MPEXP, MPPWR, MPQPWR, MPROOT, ETC.,
C NOT RECOMMENDED FOR INDEPENDENT USE (USE MPPWR INSTEAD).
C ROUNDING NOT BEST POSSIBLE, BUT DIRECTED ROUNDING
C (RNDRL = 2 OR 3) IS CORRECT IN THAT LOWER AND UPPER BOUNDS
C (RESPECTIVELY) ARE OBTAINED.
      COMMON R
      INTEGER I2, N, N2, R(1), S, SV, X(1), Y(1)
C CHECK FOR SOME SPECIAL CASES.
      N2 = IABS(N)
      IF (N2 - 1) 10, 20, 30
C HERE ABS(N) = 0
   10 CALL MPCIM (1, Y)
      RETURN
C HERE ABS(N) = 1
   20 CALL MPSTR (X, Y)
      RETURN
C SAVE T ETC. AND ALLOCATE TEMPORARY SPACE ETC.
   30 CALL MPSAVN (SV)
      CALL MPNEW (I2)
C COMPUTE SIGN OF RESULT
      S = X(1)
      IF (MOD(N2,2).EQ.0) S = IABS(S)
C MOVE ABS(X) TO TEMPORARY STORAGE
      CALL MPABS (X, R(I2))
C INITIALIZE PRODUCT IN Y
      CALL MPCIM (1, Y)
C USE CHOPPED ARITHMETIC RATHER THAN ROUNDED TO SAVE TIME.
      IF (R(SV+2) .EQ. 1) CALL MPSETR (0)
C FOLLOWING FOR DIRECTED ROUNDING
      CALL MPREVR (-S)
C LOOP, LOOKING AT BITS OF ABS(N) FROM RIGHT.
   40 IF (MOD (N2, 2) .NE. 0) CALL MPMUL (Y, R(I2), Y)
      N2 = N2/2
      IF (N2.LE.0) GO TO 50
      CALL MPMUL (R(I2), R(I2), R(I2))
      GO TO 40
C RESTORE EVERYTHING AND FIX UP SIGN OF RESULT.
   50 CALL MPRESN (SV)
      Y(1) = S*Y(1)
      RETURN
      END
C $$                   ******  MPPWR2  ******
      SUBROUTINE MPPWR2 (X, Y, Z)
C RETURNS Z = X**Y FOR MP NUMBERS X, Y AND Z, WHERE X IS
C POSITIVE (X .EQ. 0 ALLOWED IF Y .GT. 0).  SLOWER THAN
C MPPWR AND MPQPWR, SO USE THEM IF POSSIBLE.
C X AND/OR Y MAY BE PACKED OR UNPACKED, Z IS UNPACKED.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I2, I3, SV, TG
      INTEGER B, DUMMY(21), R(1), T, X(1), Y(1), Z(1)
      INTEGER MPCMPI, MPGD, MPGET, MPTLB
C SAVE T ETC., THEN CHECK SIGN OF X.
      CALL MPSAVN (SV)
      IF (X(1)) 10, 20, 30
   10 CALL MPERRM (29HX NEGATIVE IN CALL TO MPPWR2$)
C HERE X IS ZERO, RETURN ZERO IF Y POSITIVE, OTHERWISE ERROR
   20 IF (Y(1) .LE. 0) CALL MPERRM (
     $  43HX ZERO AND Y NONPOSITIVE IN CALL TO MPPWR2$)
C RETURN ZERO HERE
      Z(1) = 0
      GO TO 50
C HERE X IS POSITIVE.  CHECK FOR X = 1 OR Y = 0.
   30 IF ((Y(1) .NE. 0) .AND. (MPCMPI (X, 1) .NE. 0)) GO TO 40
C X**0 = 1, 1**Y = 1.
      CALL MPCIM (1, Z)
      GO TO 50
C USUAL CASE HERE, X POSITIVE, Y NONZERO.  ALLOCATE TEMPORARY
C SPACE AND USE MPLN AND MPEXP TO COMPUTE POWER.
C INCREASE T AS NECESSARY.
   40 T = T + 1 + MPGD (100*MPTLB(1))
     $      + MPGD (MPGET (X, 2)) + MAX0 (0, MPGET (Y, 2))
      TG = T
      CALL MPNEW (I2)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
C TAKE CARE FOR DIRECTED ROUNDING
      CALL MPREVR (-Y(1))
      CALL MPLN (R(I2), R(I2))
      CALL MPNEW (I3)
      CALL MPMOVE (Y, IABS(R(SV)), R(I3), TG)
      CALL MPMUL (R(I2), R(I3), R(I2))
C RESTORE RNDRL BEFORE CALLING MPEXP
      CALL MPREVR (-Y(1))
C IF X**Y IS TOO LARGE, MPEXP WILL PRINT ERROR MESSAGE
      CALL MPEXP (R(I2), R(I2))
      CALL MPRND (R(I2), TG, Z, IABS(R(SV)), 0)
   50 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPQPWR  ******
      SUBROUTINE MPQPWR (I, J, K, L, X)
C SETS MULTIPLE-PRECISION X = (I/J)**(K/L) FOR INTEGERS
C I, J, K AND L,  TIME = O(T**2).
C ROUNDING IS DETERMINED BY RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN THE LAST PLACE,
C RNDRL = 2 OR 3 - DIRECTED ROUNDINGS, SEE SUBROUTINE MPNZR.
      COMMON R
      INTEGER IS, I2, JS, KS, LS, SV, TG
      INTEGER I, J, K, L, R(1), X(1)
C SAVE T ETC. AND INCREASE WORKING PRECISION
      CALL MPSAVN (SV)
      CALL MPGD3 (K, TG)
C ALLOCATE TEMPORARY STORAGE.
      CALL MPNEW (I2)
      R(I2) = 0
      IS = I
      JS = J
      KS = IABS(K)
      LS = L
C FOR EFFICIENCY MAKE KS POSITIVE AND LS NEGATIVE
C (SEE COMMENTS IN MPROOT AND MPPWR).
      IF (K) 30, 10, 40
C (I/J)**(0/L) = 1 IF J AND L ARE NONZERO.
   10 CALL MPCIM (1, R(I2))
      IF ((JS.NE.0).AND.(LS.NE.0)) GO TO 90
   20 CALL MPERRM (33HJ = 0 OR L = 0 IN CALL TO MPQPWR$)
C HERE K IS NEGATIVE
   30 LS = -LS
C NOW LOOK AT SIGN OF LS
   40 IF (LS) 60, 20, 50
C LS POSITIVE SO INTERCHANGE IS AND JS TO MAKE NEGATIVE
   50 IS = J
      JS = I
      LS = -LS
C NOW KS POSITIVE, LS NEGATIVE
   60 IF (IS .EQ. 0) CALL MPERRM (
     $  56HI=0 AND K/L.LT.0, OR J=0 AND K/L.GT.0 IN CALL TO MPQPWR$)
C (I/0)**(NEGATIVE) = 0 IF I NONZERO
      IF (JS.EQ.0) GO TO 90
C TO SAVE TIME IN MPROOT AND MPPWR, FIND GCD OF KS AND LS
      CALL MPGCD (KS, LS)
C CHECK FOR DIRECTED ROUNDING
      IF (MOD (KS, 2) .EQ. 0) CALL MPREVR (IS*(-(JS/IABS(JS))))
C CHECK FOR LS = -1, TREAT AS SPECIAL CASE
      IF (LS.NE.(-1)) GO TO 70
      CALL MPCQM (JS, IS, R(I2))
      GO TO 80
C USUAL CASE HERE, LS .NE. -1
   70 CALL MPCQM (IS, JS, R(I2))
      CALL MPROOT (R(I2), LS, R(I2))
   80 CALL MPSETR (IABS(R(SV+2)))
      CALL MPPWRA (R(I2), KS, R(I2))
C ROUND RESULT, RESTORE T ETC, AND RETURN
   90 CALL MPRND (R(I2), TG, X, IABS(R(SV)), 0)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPREC  ******
      SUBROUTINE MPREC (X, Y)
C RETURNS Y = 1/X, FOR MP X AND Y.
C USES MPDIVL IF T SMALL OR RNDRL .NE. 0, MPROOT OTHERWISE.
C TIME = O(M(T)).
C ROUNDING DETERMINED BY RNDRL IN COMMON /MPCOM/ - SEE COMMENTS
C IN SUBROUTINE MPDIV.
      COMMON R
      INTEGER R(1), X(1), Y(1), CROSS, I2, SV
C FOLLOWING CROSSOVER POINT FOR USE OF MPROOT DETERMINED EMPIRICALLY.
      DATA CROSS /50/
      CALL MPSAVN (SV)
C CHECK FOR X ZERO
      IF (X(1) .EQ. 0) CALL MPERRM (
     $  44HATTEMPTED DIVISION BY ZERO IN CALL TO MPREC$)
C DECIDE WHETHER TO USE MPDIVL OR MPROOT.
      IF ((R(SV) .LT. CROSS) .OR. (R(SV+2) .NE. 0)) GO TO 10
      CALL MPROOT (X, -1, Y)
      GO TO 20
C HERE USE MPDIVL TO COMPUTE 1/X
   10 CALL MPNEW (I2)
      CALL MPCIM (1, R(I2))
      CALL MPDIVL (R(I2), X, Y)
   20 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPRESN  ******
      SUBROUTINE MPRESN (N)
C RESTORES T, M AND RNDRL WHICH WERE SAVED BY
C SUBROUTINE MPSAVN.  N MUST BE THE VALUE RETURNED BY MPSAVN.
C SPTR IS RESTORED TO ITS VALUE ON THE CALL TO MPSAVN (I.E. N).
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, DUMMY
      INTEGER B, T, M, LUN, MXR, SPTR, N, DUMMY(17)
      CALL MPRES2 (N)
      SPTR = N
      RETURN
      END
C $$                   ******  MPRES2  ******
      SUBROUTINE MPRES2 (N)
C RESTORES T, M AND RNDRL WHICH WERE SAVED BY
C SUBROUTINE MPSAVN.  N MUST BE THE VALUE RETURNED BY MPSAVN.
C SPTR IS UNCHANGED.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, DUMMY
      INTEGER B, DUMMY(12), LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR, MXSPTR,
     $  N, R(1), RNDRL, SPTR, T
      IF ((N .GE. MNSPTR) .AND. (SPTR .GE. (N+3))) GO TO 20
      WRITE (LUN, 10)
   10 FORMAT (44H *** ILLEGAL N OR STPR ON CALL TO MPRES2 ***)
      CALL MPERR
   20 T = R(N)
      M = R(N+1)
      RNDRL = R(N+2)
      RETURN
      END
C $$                   ******  MPREVR  ******
      SUBROUTINE MPREVR (I)
C IF I .GT. 0 AND RNDRL (IN COMMON /MPCOM/) IS 2 OR 3,
C RNDRL IS REPLACED BY 5 - RNDRL (I.E. 2 AND 3 INTERCHANGED).
C THIS REVERSES THE DIRECTION OF DIRECTED ROUNDING - SEE MPNZR.
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, DUMMY
      INTEGER B, DUMMY(12), I, LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR,
     $  MXSPTR, RNDRL, SPTR, T
      IF ((I.GT.0) .AND. (RNDRL.GT.1)) RNDRL = 5 - RNDRL
      RETURN
      END
C $$                   ******  MPRND  ******
      SUBROUTINE MPRND (X, TX, Y, TY, K)
C MOVES X + S*K*(B**(-TY))*ABS(X) APPROPRIATELY ROUNDED TO Y,
C WHERE X IS AN MP NUMBER WITH TX DIGITS, Y IS AN MP NUMBER
C WITH TY DIGITS, K AN INTEGER, AND
C S = 0 IF RNDRL .LE. 1,
C    -1 IF RNDRL .EQ. 2,
C    +1 IF RNDRL .EQ. 3.
C NOTE - RNDRL = 0 HAS SAME EFFECT AS RNDRL = 1, I.E. X ROUNDED TO
C NEAREST REPRESENTABLE NUMBER WITH TY DIGITS.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, DUMMY
      INTEGER B, DUMMY(12), K, LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR,
     $  MXSPTR, R(1), RNDRL, SPTR, T, TX, TY, X(1), Y(1), I2, SV
C SAVE T ETC., SET RNDRL TO 1 IF ZERO.
      CALL MPSAVN (SV)
      RNDRL = MAX0 (1, RNDRL)
C SEE IF ADDITION NECESSARY
      IF ((RNDRL.GT.1).AND.(K.NE.0).AND.(X(1).NE.0)) GO TO 10
      CALL MPMOVE (X, TX, Y, TY)
      GO TO 20
C HERE ADDITION NECESSARY.  ALLOCATE TEMPORARY SPACE ETC.
   10 T = TX
      CALL MPNEW (I2)
      CALL MPSTR (X, R(I2))
      R(I2+1) = R(I2+1) - TY
      CALL MPMULI (R(I2), ((2*RNDRL-5)*K*X(1)), R(I2))
      CALL MPADD (R(I2), X, R(I2))
      CALL MPMOVE (R(I2), TX, Y, TY)
C RESTORE EVERYTHING AND RETURN
   20 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPROOT  ******
      SUBROUTINE MPROOT (X, N, Y)
C RETURNS Y = X**(1/N) FOR INTEGER N, MP X AND Y, USING NEWTONS
C METHOD WITHOUT DIVISIONS.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C TIME IS O(M(T)) UNLESS ABS(N) IS LARGE (WHEN MPPWR2 IS USED).
C ROUNDING DETERMINED BY PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE
C                  (SO RESULT EXACT IF EXACTLY REPRESENTABLE).
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
C ABS(N) .LE. M (MAXIMUM EXPONENT) IS REQUIRED.
      COMMON R
      COMMON /MPCOM/ B, T, M, DUMMY
      INTEGER E, EP, EX, I2, I3, I4, I5, I6, J, K, KS, NP, SV, TG, TG2
      INTEGER B, DUMMY(20), KTM, M, MPTLB, N, R(1), T, X(1), Y(1)
C SAVE T ETC., USE TRUNCATED ARITHMETIC INTERNALLY.
      CALL MPSAVN (SV)
      CALL MPSETR (0)
      NP = IABS (N)
      IF (N .NE. 1) GO TO 10
C SIMPLY MOVE X IF N = 1
      CALL MPUNPK (X, Y)
      GO TO 110
C CHECK FOR VARIOUS ILLEGAL ARGUMENT COMBINATIONS
   10 IF (N .EQ. 0) CALL MPERRM (24HN = 0 IN CALL TO MPROOT$)
      IF (X(1)) 30, 20, 40
   20 Y(1) = 0
      IF (N.LT.0) CALL MPERRM (37HX = 0 AND N .LT. 0 IN CALL TO MPROOT$)
      GO TO 110
   30 IF (MOD (NP, 2) .EQ. 0) CALL MPERRM (
     $  38HX .LT. 0 AND N EVEN IN CALL TO MPROOT$)
C INCREASE T AND ALLOCATE SPACE
   40 CALL MPGD3 (NP, TG)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
C WORK WITH ABS(X), FIX UP SIGN LATER.
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      R(I2) = IABS (R(I2))
C CHECK FOR LARGE ABS(N).
      IF (NP .GE. (M/4)) GO TO 130
      CALL MPNEW (I4)
      IF (NP .LE. 2) GO TO 50
      CALL MPNEW (I5)
      CALL MPNEW (I6)
   50 E = -R(I2+1)
C COMPUTE EP = FLOOR (E/NP) + 1
      EP = E/NP
      IF ((NP*EP) .LE. E) EP = EP + 1
C SCALE TO AVOID UNDER/OVERFLOW
C SCALED ABS(X) IS BETWEEN 1 AND B**NP
      R(I2+1) = R(I2+1) + EP*NP
C LOWER AND UPPER BOUNDS ON ABS(SCALED RESULT) ARE 1/B AND 1.
      CALL MPCQM (1, IABS(B), R(I3))
      CALL MPSTR (R(I3), R(I4))
      IF (NP .GT. 2) CALL MPCIM (1, R(I5))
C SET KTM TO MAXIMUM NUMBER OF ITERATIONS ALLOWED.
      KTM = T*MPTLB(1)
C REDUCE T AT FIRST.
      T = 2
      CALL MPGD3 (NP, TG2)
      EX = 0
C TO SPEED UP RECIPROCALS AND SQUARE ROOTS, TREAT NP = 1 OR 2 AS
C SPECIAL CASES AND GET BETTER STARTING APPROXIMATIONS FOR THEM.
      IF (NP .EQ. 1)
     $  CALL MPCQM (IABS(B), (B*R(I2+2) + R(I2+3) + 1), R(I3))
      IF (NP .NE. 2) GO TO 70
C HERE NP = 2.  COMPUTE J = UPPER BOUND ON 4*ABS(SCALED X).
      CALL MPCMI (R(I2), J)
      J = 4*(J + 1)
C COMPUTE K = UPPER BOUND ON SQRT(J)
C USING INTEGER NEWTON ITERATION.
      K = J
   60 KS = K
      K = (K + J/K)/2
      IF (K .LT. KS) GO TO 60
      IF ((K*K) .LT. J) K = K + 1
C NOW GET LOWER BOUND ON SCALED ABS (RESULT).
      CALL MPCQM (2, K, R(I3))
C SKIP BISECTION PHASE IF NP .LE. 2
   70 IF (NP .LE. 2) GO TO 80
C BISECTION LOOP HERE.  CHECK FOR INFINITE LOOP.
      KTM = KTM - 1
      IF (KTM .LT. 0) GO TO 120
      CALL MPSUB (R(I5), R(I3), R(I6))
      CALL MPDIVI (R(I6), 2, R(I6))
      CALL MPADD (R(I3), R(I6), R(I6))
      CALL MPPWRA (R(I6), NP, R(I4))
      CALL MPMUL (R(I2), R(I4), R(I4))
      CALL MPADDI (R(I4), -1, R(I4))
      IF (R(I4) .LE. 0) CALL MPSTR (R(I6), R(I3))
      IF (R(I4) .GE. 0) CALL MPSTR (R(I6), R(I5))
C REPEAT BISECTION IF ABS (RESIDUAL) .GE. 1/2
      IF (R(I4) .EQ. 0) GO TO 90
      IF ((R(I4+1) .GT. 0) .OR.
     $  ((R(I4+1) .EQ. 0) .AND. ((2*R(I4+2)) .GE. B))) GO TO 70
C NOW NEWTONS METHOD SHOULD CONVERGE
      CALL MPSTR (R(I6), R(I3))
      GO TO 90
C NEWTON LOOP STARTS HERE.  CHOOSE GOOD T.
   80 T = MIN0 (TG, TG2 + 4*IABS(EX))
      CALL MPPWRA (R(I3), NP, R(I4))
      CALL MPMUL (R(I2), R(I4), R(I4))
      CALL MPADDI (R(I4), -1, R(I4))
   90 EX = -T
      IF (R(I4) .NE. 0) EX = R(I4+1)
C CHECK FOR INFINITE LOOP
      KTM = KTM - 1
      IF ((KTM .LT. 0) .OR. (EX .GT. 0)) GO TO 120
      CALL MPMUL (R(I3), R(I4), R(I4))
      CALL MPDIVI (R(I4), NP, R(I4))
      CALL MPSUB (R(I3), R(I4), R(I3))
C CHECK FOR CONVERGENCE
      IF ((2*EX + TG) .GT. 0) GO TO 80
C END OF LOOP, CORRECT EXPONENTS
      R(I2+1) = R(I2+1) - EP*NP
      R(I3+1) = R(I3+1) + EP
C CORRECT RESULT FOR N POSITIVE
      IF (N .LT. 0) GO TO 100
      CALL MPPWRA (R(I3), N-1, R(I3))
      CALL MPMUL (R(I2), R(I3), R(I3))
  100 R(I3) = ISIGN (R(I3), X(1))
C RESTORE RNDRL AND DO CORRECT ROUNDING
      CALL MPSETR (IABS(R(SV+2)))
      CALL MPRND (R(I3), TG, Y, IABS(R(SV)), 1)
  110 CALL MPRESN (SV)
      RETURN
  120 CALL MPERRM (35HITERATION NOT CONVERGING IN MPROOT$)
C HERE ABS(N) IS VERY LARGE
  130 CALL MPCQM (1, N, R(I3))
      CALL MPPWR2 (R(I2), R(I3), R(I3))
      GO TO 100
      END
C $$                   ******  MPSAVN  ******
      SUBROUTINE MPSAVN (N)
C SAVES T, M AND RNDRL ON STACK.
C RETURNS N = OLD VALUE OF SPTR,
C SAVES T     IN R(N),
C       M     IN R(N+1),
C       RNDRL IN R(N+2).
C NOTE - THE ARGUMENT N MUST NOT HAVE SAME ADDRESS AS SPTR.
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, DUMMY
      INTEGER B, DUMMY(12), LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR, MXSPTR,
     $  N, R(1), RNDRL, SPTR, T
C ALLOCATE THREE WORDS ON STACK.
      CALL MPNEW2 (N, 3)
C SAVE T, M AND RNDRL.
      R(N) = T
      R(N+1) = M
      R(N+2) = RNDRL
      RETURN
      END
C $$                   ******  MPSCAL  ******
      SUBROUTINE MPSCAL (X, BASE, J)
C SETS  X = X*(BASE**J), FOR MP X, INTEGER J, AND (SMALL)
C POSITIVE INTEGER BASE (E.G. BASE = 10).
C ROUNDING NOT BEST POSSIBLE, BUT DIRECTED ROUNDING OPTIONS
C (RNDRL = 2 OR 3) GIVE CORRECT LOWER AND UPPER BOUNDS.
      COMMON R
      INTEGER B, I, IB, I2, JA, JP, SV
      INTEGER BASE, J, MPPARN, R(1), X(1)
      IF (BASE.LE.0) CALL MPERRM (31HILLEGAL BASE IN CALL TO MPSCAL$)
C RETURN IF J ZERO OR X ZERO
      IF ((J.EQ.0).OR.(X(1).EQ.0)) RETURN
C SAVE T ETC.
      CALL MPSAVN (SV)
C OTHERWISE MULTIPLY BY BASE**J
      JA = IABS(J)
C THE NUMBERS -500 AND 100 WERE DETERMINED EMPIRICALLY FOR BASE = 10.
C THE OPTIMUM CHOICE DEPENDS ON BASE, B AND T.
      IF ((J.GT.(-500)).AND.(J.LT.100)) GO TO 10
C HERE EXPONENT LARGE, SO USE MPPWRA TO COMPUTE BASE**ABS(J)
      CALL MPNEW (I2)
      CALL MPCIM (BASE, R(I2))
C TAKE CARE FOR DIRECTED ROUNDINGS.
      CALL MPREVR ((-J)*X(1))
      CALL MPPWRA (R(I2), JA, R(I2))
      CALL MPSETR (IABS(R(SV+2)))
      IF (J.LT.0) CALL MPDIV (X, R(I2), X)
      IF (J.GE.0) CALL MPMUL (X, R(I2), X)
      GO TO 30
C HERE ABS(J) IS SMALL SO PROBABLY FASTER TO USE MPDIVI OR MPMULI
   10 JP = 1
      IB = MPPARN (16)/BASE
      B = MPPARN (1)
      DO 20 I = 1, JA
      JP = BASE*JP
      IF ((JP.LE.IB).AND.(JP.NE.B).AND.(I.LT.JA)) GO TO 20
      IF (J.LT.0) CALL MPDIVI (X, JP, X)
      IF (J.GE.0) CALL MPMULI (X, JP, X)
      JP = 1
   20 CONTINUE
   30 CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPSET  ******
      SUBROUTINE MPSET (LUN, DECPL, MT2, MXR)
C REDUNDANT BUT INCLUDED FOR COMPATIBILITY WITH EARLIER
C VERSIONS OF MP.
      INTEGER LUN, DECPL, MT2, MXR
      CALL MPSET2 (LUN, DECPL, MT2, 1, MXR)
      RETURN
      END
C $$                   ******  MPSETR  ******
      SUBROUTINE MPSETR (N)
C SETS THE PARAMETER RNDRL IN COMMON /MPCOM/ TO N = 0, 1, 2 OR 3.
C FOR EFFECT OF THIS SEE SUBROUTINE MPNZR ETC.
      INTEGER N
      IF ((N .LT. 0) .OR. (N .GT. 3)) CALL MPERRM (
     $  35HILLEGAL ARGUMENT IN CALL TO MPSETR$)
      CALL MPPARC (11, N)
      RETURN
      END
C $$                   ******  MPSET2  ******
      SUBROUTINE MPSET2 (LUN, DECPL, MT2, MNSPTR, MXR)
C
C LUN IS THE LOGICAL UNIT TO BE USED FOR ERROR MESSAGES.
C SETS BASE (B) AND NUMBER OF DIGITS (T) TO GIVE THE
C EQUIVALENT OF AT LEAST DECPL DECIMAL DIGITS.
C DECPL SHOULD BE A POSITIVE INTEGER.
C MT2 IS THE DIMENSION OF ARRAYS USED FOR MP NUMBERS,
C SO AN ERROR OCCURS IF THE COMPUTED T EXCEEDS MT2 - 2.
C MXR IS THE SIZE OF BLANK COMMON DECLARED IN THE CALLING PROGRAM,
C AND MNSPTR IS THE FIRST LOCATION IN BLANK COMMON AVAILABLE FOR
C USE BY MP.  (MP WILL USE WORDS MNSPTR, MNSPTR+1, ... , MXR OF
C BLANK COMMON (COUNTING FROM 1) FOR WORKING STORAGE.)
C
C LET MXINT BE THE LARGEST INTEGER OF THE FORM 2**K - 1 REPRESENTABLE
C AS A SIGNED INTEGER ON THE MACHINE (SEE MPLARG).
C THE COMPUTED B AND T SATISFY THE CONDITIONS
C B**(T-1) .GE. 10**(DECPL-1)  AND 8*B*B-1 .LE. MXINT .
C APPROXIMATELY MINIMAL T AND MAXIMAL B SATISFYING
C THESE CONDITIONS ARE CHOSEN.
C
C MPSET2 ALSO SETS
C
C       M      = MXINT/4 (MAXIMUM ALLOWABLE EXPONENT),
C       SPTR   = MNSPTR  (STACK POINTER),
C       MXSPTR = MNSPTR  (MAXIMUM VALUE OF SPTR IS SAVED HERE),
C       RNDRL  = 0       (SEE SUBROUTINE MPNZR),
C       KTUNFL = 0       (UNDERFLOW COUNTER),
C       MXUNFL = 0       (SEE SUBROUTINE MPUNFL),
C       MNEXPN = M+1     (MINIMUM EXPONENT WHICH OCCURS SAVED HERE),
C       MXEXPN = -M      (MAXIMUM EXPONENT WHICH OCCURS SAVED HERE),
C       MXINT  = LARGE INTEGER (SEE SUBROUTINE MPLARG),
C       EXWID  = 6       (EXPONENT FIELD WIDTH, SEE MPFOUT),
C       INRECL = 80      (INPUT RECORD LENGTH, SEE MPFIN),
C       INBASE = 10      (DEFAULT INPUT BASE FOR MPIN),
C       OUTBAS = 10      (DEFAULT OUTPUT BASE FOR MPOUT),
C       EXPCH  = 1HE     (DEFAULT OUTPUT EXPONENT CHARACTER),
C       CHWORD = NUMBER OF CHARACTERS PER WORD (RETURNED BY MPUPW),
C       ONESCP = 1 IF ONES COMPLEMENT ARITHMETIC, 0 OTHERWISE.
C
C IF THESE ARE NOT ALL AS DESIRED, CHANGE AFTER THE CALL TO MPSET2,
C FOR EXAMPLE, ONE COULD SET MXUNFL = 10 IF
C EXECUTION WERE TO BE TERMINATED AFTER 10 MP UNDERFLOWS.
C
      COMMON R
      COMMON /MPCOM/ B, T, M, LUNC, MXRC, SPTR, MXSPTR, MNSPTC,
     $  MXEXPN, MNEXPN, RNDRL, KTUNFL, MXUNFL,
     $  DECPLC, MT2C, MXINT, EXWID, INRECL, INBASE,
     $  OUTBAS, EXPCH, CHWORD, ONESCP
C INCREASE DIMENSION OF C AND MODIFY DATA STATEMENT FOR MAXCHW
C BELOW IF THERE ARE MORE THAN 10 CHARACTERS PER WORD.
C 10 CHARACTERS PER WORD.
      INTEGER C(10), MAXCHW,
     $  I, I2, K, TAB(10),
     $  B, CHW, CHWORD, DECPL, DECPLC, EXPCH, EXWID, INBASE, INRECL,
     $  KTUNFL, LUN, LUNC, M, MNEXPN, MNSPTC, MNSPTR, MT2, MT2C,
     $  MXEXPN, MXINT, MXR, MXRC, MXSPTR, MXUNFL, ONESCP, OUTBAS,
     $  R(1), RNDRL, SPTR, T, MPDIGS, MPGET
      LOGICAL MPIS
C SEE COMMENT ABOVE ABOUT MAXCHW.
      DATA MAXCHW /10/
      DATA TAB(1), TAB(2), TAB(3), TAB(4) /1H0, 1H9, 1HA, 1HZ/
      DATA TAB(5), TAB(6), TAB(7), TAB(8) /1H+, 1H-, 1H., 1H$/
      DATA TAB(9), TAB(10) /1H , 1HE/
C FIRST SET OUTPUT UNIT, MAXIMUM SIZE OF COMMON, ETC.
      LUNC = LUN
      MXRC = MXR
      MNSPTC = MNSPTR
      SPTR = MNSPTR
      MXSPTR = SPTR
      RNDRL = 0
      KTUNFL = 0
      MXUNFL = 0
      DECPLC = DECPL
      MT2C = MT2
C SET DEFAULT IO PARAMETERS
      EXWID = 6
      INRECL = 80
      INBASE = 10
      OUTBAS = 10
      EXPCH = MPGET (TAB, 10)
C CHECK THAT LUN IN RANGE 1,...,99 AND WRITE ERROR MESSAGE
C ON UNIT 6 IF NOT.
      IF ((LUN.GT.0).AND.(LUN.LT.100)) GO TO 20
      WRITE (6, 10) LUN
   10 FORMAT (10H *** LUN =, I10, 30H ILLEGAL IN CALL TO MPSET2 ***)
      LUNC = 6
      CALL MPERR
C CHECK FOR BURROUGHS 6700
   20 IF (.NOT. MPIS (TAB(9), TAB(6))) GO TO 40
   25 WRITE (LUNC, 30)
   30 FORMAT (35H *** REPLACE MPIS AND/OR MPLARG ***)
      CALL MPERR
C SET MXINT TO LARGE REPRESENTABLE INTEGER (SEE ABOVE).
   40 CALL MPLARG (MXINT)
C IF WORDLENGTH .GE. 12 BITS, EXPECT MXINT .GE. 2047
      IF (MXINT .LT. 2047) GO TO 25
C MAXIMUM EXPONENT IS MXINT/4
      M = MXINT/4
C BASE B IS LARGEST POWER OF 2 SUCH THAT 8*B*B-1 .LE. MXINT
      B = 1
   50 B = 2*B
      IF ((4*B*B) .LT. (M+1)) GO TO 50
C SET MNEXPN AND MXEXPN TO GREATER THAN M, LESS THAN -M RESP.
      MNEXPN = M+1
      MXEXPN = -M
      IF (DECPL.GT.0) GO TO 70
      WRITE (LUNC, 60)
   60 FORMAT (39H *** DECPL .LE. 0 IN CALL TO MPSET2 ***)
      CALL MPERR
C ENSURE THAT B**(T-1) .GE. 10**(DECPL-1).
   70 T = MPDIGS (DECPL)
C SEE IF T TOO LARGE FOR DIMENSION STATEMENTS
      I2 = T + 2
      IF (I2.LE.MT2) GO TO 90
      WRITE (LUNC, 80) I2
   80 FORMAT (40H *** MT2 TOO SMALL IN CALL TO MPSET2 *** /
     $  45H *** INCREASE MT2 AND DIMENSIONS OF MP ARRAYS,
     $  12H TO AT LEAST, I6, 4H ***)
      CALL MPERR
      CHWORD = MAXCHW
C NOW CHOOSE ONESCP SO THAT MPUPW WORKS FOR ALL
C CHARACTERS OF INTEREST (SEE MPIN, MPOUT ETC).
   90 ONESCP = 0
      DO 120 K = 1, 2
      DO 100 I = 1, 9
      CALL MPUPW (TAB(I), C, CHW)
      CHWORD = CHW
      IF ((CHWORD .LE. 1) .OR. (CHWORD .GT. MAXCHW)) GO TO 120
      IF (.NOT. MPIS (TAB(I), C(1))) GO TO 110
      IF (.NOT. MPIS (TAB(9), C(CHWORD))) GO TO 110
  100 CONTINUE
      GO TO 120
  110 ONESCP = ONESCP + 1
  120 CONTINUE
      IF (ONESCP .LE. 1) GO TO 140
      WRITE (LUNC, 130)
  130 FORMAT (22H *** REPLACE MPUPW ***)
      CALL MPERR
C CHECK LEGALITY OF B, T ETC.
  140 CALL MPCHK
      RETURN
      END
C $$                   ******  MPSIGA  ******
      INTEGER FUNCTION MPSIGA (X)
C RETURNS SIGN OF PACKED OR UNPACKED MP NUMBER X, SIGN (0) = 0.
      INTEGER X(1)
      MPSIGA = 0
      IF (X(1) .NE. 0) MPSIGA = ISIGN (1, X(1))
      RETURN
      END
C $$                   ******  MPSIGB  ******
      SUBROUTINE MPSIGB (I, X)
C SETS SIGN OF PACKED OR UNPACKED MP NUMBER X TO SIGN OF I.
C NOTE THAT SIGN (0) = 0.
      INTEGER I, J, X(1)
C EXPONENT AND DIGITS OF X ARE UNCHANGED.
      J = I
      IF (J .EQ. 0) X(1) = 0
      IF (J .NE. 0) X(1) = ISIGN (X(1), J)
      RETURN
      END
C $$                   ******  MPSIGN  ******
      SUBROUTINE MPSIGN (X, Y, Z)
C SETS Z = ABS(X)*SIGN(Y) FOR MP X, Y AND Z.
C X AND/OR Y MAY BE PACKED OR UNPACKED, Z IS UNPACKED.
C NOTE THAT Z = 0 IF Y = 0 (I.E. SIGN (0) = 0).
      INTEGER IY, X(1), Y(1), Z(1)
      IY = Y(1)
      CALL MPUNPK (X, Z)
      Z(1) = ISIGN (Z(1), IY)
      IF (IY .EQ. 0) Z(1) = 0
      RETURN
      END
C $$                   ******  MPSIN  ******
      SUBROUTINE MPSIN (X, Y)
C RETURNS Y = SIN(X) FOR (PACKED OR UNPACKED) MP X, UNPACKED MP Y.
C USES MPCIS, SO TIME = O(SQRT(T)M(T)).
C ROUNDING OPTIONS ARE IMPLEMENTED AS FOR MPCIS.
      COMMON R
      INTEGER I2, R(1), SV, X(1), Y(1)
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPCIS (X, R(I2), Y, .TRUE.)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPSINH  ******
      SUBROUTINE MPSINH (X, Y)
C RETURNS Y = SINH(X) FOR MP NUMBERS X AND Y, X NOT TOO LARGE.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C USES MPEXP OR MPEXP1.
C ROUNDING OPTIONS NOT YET IMPLEMENTED, NO GUARD DIGITS USED.
      COMMON R
      INTEGER I2, I3, MPGET, MPMEXA, R(1), SV, X(1), XS, Y(1)
C SAVE T ETC.
      CALL MPSAVN (SV)
C SAVE SIGN OF X AND CHECK FOR ZERO, SINH(0) = 0
      XS = X(1)
      IF (XS.NE.0) GO TO 10
      Y(1) = 0
      GO TO 40
C ALLOCATE TEMPORARY SPACE.
   10 CALL MPNEW (I2)
C USE TRUNCATED ARITHMETIC.
      CALL MPSETR (0)
C WORK WITH ABS(X)
      CALL MPABS (X, R(I2))
      IF (R(I2+1).LE.0) GO TO 20
C HERE ABS(X) .GE. 1, IF TOO LARGE MPEXP GIVES ERROR MESSAGE
C INCREASE M TO AVOID OVERFLOW IF SINH(X) REPRESENTABLE
      CALL MPMEXB (MPMEXA (X) + 2, X)
      CALL MPEXP (R(I2), R(I2))
      CALL MPREC (R(I2), Y)
      CALL MPSUB (R(I2), Y, Y)
C RESTORE M.  IF RESULT OVERFLOWS OR UNDERFLOWS, MPDIVI AT
C STATEMENT 30 WILL ACT ACCORDINGLY.
      CALL MPMEXB (MPGET (R, SV+1), X)
      GO TO 30
C HERE ABS(X) .LT. 1 SO USE MPEXP1 TO AVOID CANCELLATION
   20 CALL MPNEW (I3)
      CALL MPEXP1 (R(I2), R(I3))
      CALL MPADDI (R(I3), 2, R(I2))
      CALL MPMUL (R(I2), R(I3), Y)
      CALL MPADDI (R(I3), 1, R(I2))
      CALL MPDIV (Y, R(I2), Y)
C DIVIDE BY TWO AND RESTORE SIGN
   30 CALL MPDIVI (Y, ISIGN (2, XS), Y)
      CALL MPRESN (SV)
   40 RETURN
      END
C $$                   ******  MPSQRT  ******
      SUBROUTINE MPSQRT (X, Y)
C RETURNS Y = SQRT(X), USING SUBROUTINE MPROOT IF X .GT. 0.
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C ROUNDING IS DETERMINED BY RNDRL IN COMMON /MPCOM/ AS FOLLOWS -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 ULP, SO EXACT IF RESULT CAN
C             BE EXACTLY REPRESENTED.
C RNDRL = 2 OR 3 - DIRECTED ROUNDINGS - SEE SUBROUTINE MPNZR.
      INTEGER X(1), Y(1)
C CHECK LEGALITY OF B, T, ETC.
      CALL MPCHK
C CHECK SIGN OF X.
      IF (X(1)) 10, 20, 30
   10 CALL MPERRM (36HNEGATIVE ARGUMENT IN CALL TO MPSQRT$)
C HERE RETURN ZERO.
   20 Y(1) = 0
      RETURN
C HERE USE MPROOT.
   30 CALL MPROOT (X, 2, Y)
      RETURN
      END
C $$                   ******  MPSTOV  ******
      SUBROUTINE MPSTOV (N)
C
C CALLED IF STACK SPACE IN BLANK COMMON TOO SMALL.
C IF POSSIBLE, SPACE SHOULD BE EXPANDED BY AT LEAST N WORDS
C AND MXR INCREASED BY THE AMOUNT EXPANDED.
C
C THE NEW SPACE MUST BE CONTIGUOUS WITH R(MXR), I.E. IT MUST
C INCLUDE LOCATIONS R(MXR+1), ... , R(MXR+N).
C
C AT PRESENT MPSTOV DOES NOTHING BECAUSE THE METHOD OF EXPANDING
C THE STACK IS MACHINE AND OPERATING-SYSTEM DEPENDENT.
C
      COMMON R
      COMMON /MPCOM/ B, T, M, LUN, MXR, DUMMY
      INTEGER B, DUMMY(18), LUN, M, MXR, N, R(1), T
      WRITE (LUN, 10)
   10 FORMAT (42H *** MPSTOV CALLED BUT NOT IMPLEMENTED ***)
      RETURN
      END
C $$                   ******  MPSTR  ******
      SUBROUTINE MPSTR (X, Y)
C SETS Y = X FOR MP X AND Y.
C X MAY BE IN PACKED OR UNPACKED FORMAT,
C Y WILL BE IN SAME FORMAT AS X.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER B, T, DUMMY(21), I, J, X(1), Y(1), T2
C SEE IF X AND Y HAVE THE SAME ADDRESS (THEY OFTEN DO)
C NOTE - THIS TEST IS FOR EFFICIENCY ONLY, AND IT DOES NOT MATTER
C IF THE FACT THAT X AND Y HAVE THE SAME ADDRESS IS NOT DETECTED.
      J = X(1)
      Y(1) = J + 1
      IF (J.EQ.X(1)) GO TO 10
C HERE X(1) AND Y(1) MUST HAVE THE SAME ADDRESS
      X(1) = J
      RETURN
C HERE X(1) AND Y(1) MAY HAVE DIFFERENT ADDRESSES
   10 Y(1) = J
C NO NEED TO MOVE X(2), ... IF X(1) = 0
      IF (J.EQ.0) RETURN
      T2 = T + 2
C REDUCE T2 IF X IS IN PACKED FORMAT.
      IF (IABS(J) .GT. 1) T2 = (T+3)/2
C NOW MOVE REMAINING WORDS OF X.
      DO 20 I = 2, T2
   20 Y(I) = X(I)
      RETURN
      END
C $$                   ******  MPSUB  ******
      SUBROUTINE MPSUB (X, Y, Z)
C SUBTRACTS Y FROM X, FORMING RESULT IN Z, FOR MP X, Y AND Z.
C ROUNDING IS CONTROLLED BY THE PARAMETER RNDRL IN COMMON /MPCOM/
C AS FOLLOWS -
C
C RNDRL = 0 - ROUND TOWARDS ZERO IF X*Y .LE. 0,
C             AWAY FROM ZERO IF X*Y .GT. 0,
C             IN BOTH CASES ONE GUARD DIGIT IS USED, SO RESULT
C             IS EXACT IF SIGNIFICANT CANCELLATION OCCURS.
C
C RNDRL = 1, 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
C
      INTEGER X(1), Y(1), Z(1), S
C SAVE SIGN OF X
      S = X(1)
C REVERSE SIGN OF Y, SEE IF SIGN OF X CHANGED
      Y(1) = -Y(1)
      IF (S.EQ.X(1)) GO TO 10
C HERE X AND Y HAVE THE SAME ADDRESS SO RESULT IS ZERO
      Y(1) = S
      Z(1) = 0
      RETURN
C HERE X AND Y HAVE DIFFERENT ADDRESSES (OR BOTH ZERO) SO USE MPADD.
   10 CALL MPADD (X, Y, Z)
C RESTORE SIGN OF Y, BEING CAREFUL IN CASE Y AND Z HAVE SAME ADDRESS
      S = Z(1)
      Y(1) = -Y(1)
      Z(1) = S
      RETURN
      END
C $$                   ******  MPSUBA  ******
      SUBROUTINE MPSUBA (X, Y, I)
C CALLED BY MPLARG AND MPUPW.
      INTEGER I, X(1), Y(1)
      I = MAX0 (1, X(1) - Y(1))
      RETURN
      END
C $$                   ******  MPTAN  ******
      SUBROUTINE MPTAN (X, Y)
C SETS Y = TAN(X) FOR MP X AND Y,
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C USES MPCIS, SO TIME = O(SQRT(T)M(T)).
C ROUNDING OPTIONS NOT IMPLEMENTED BUT SOME GUARD DIGITS USED.
      COMMON R
      INTEGER I2, I3, R(1), SV, TG, X(1), Y(1)
C TAN(0) = 0
      IF (X(1) .NE. 0) GO TO 10
      Y(1) = 0
      RETURN
C SAVE T ETC., INCREASE T, AND ALLOCATE WORKING SPACE.
   10 CALL MPSAVN (SV)
      CALL MPGD3 (1, TG)
      CALL MPNEW (I2)
      CALL MPNEW (I3)
C USE TRUNCATED ARITHMETIC.
      CALL MPSETR (0)
C MOVE X AND COMPUTE COS(X) AND SIN(X)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      CALL MPCIS (R(I2), R(I2), R(I3), .TRUE.)
C FOLLOWING MESSAGE INDICATES THAT X IS TOO CLOSE TO AN ODD
C MULTIPLE OF PI/2
      IF (R(I2) .EQ. 0) CALL MPERRM (
     $  34HTAN(X) TOO LARGE IN CALL TO MPTAN$)
      CALL MPDIV (R(I3), R(I2), R(I2))
C ROUND RESULT, RESTORE T ETC. AND RETURN
      CALL MPRND (R(I2), TG, Y, IABS(R(SV)), 0)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPTANH  ******
      SUBROUTINE MPTANH (X, Y)
C RETURNS Y = TANH(X) FOR MP NUMBERS X AND Y,
C X MAY BE PACKED OR UNPACKED, Y IS UNPACKED.
C USES MPEXP OR MPEXP1.
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
      COMMON R
      INTEGER I2, I3, SV, TG, XS
      INTEGER MPGET, R(1), X(1), Y(1)
      INTEGER MPCMPQ, MPTLB
      IF (X(1).NE.0) GO TO 10
C TANH(0) = 0
      Y(1) = 0
      RETURN
C SAVE T ETC.
   10 CALL MPSAVN (SV)
C INCREASE T.
      CALL MPGD3 (1, TG)
C ALLOCATE WORKING SPACE.
      CALL MPNEW (I2)
      CALL MPNEW (I3)
C USE TRUNCATED ARITHMETIC.
      CALL MPSETR (0)
C SAVE SIGN AND WORK WITH ABS(X)
      CALL MPMOVE (X, IABS(R(SV)), R(I2), TG)
      XS = R(I2)
      R(I2) = 1
C SEE IF ABS(X) SO LARGE THAT RESULT IS +-1
      IF (MPCMPQ (R(I2), 2*MPTLB(IABS(R(SV))), 5) .LE. 0) GO TO 20
C HERE ABS(X) IS VERY LARGE
      CALL MPCIM (XS, R(I3))
      GO TO 50
C HERE ABS(X) NOT SO LARGE
   20 CALL MPMULI (R(I2), 2, R(I2))
      IF (R(I2+1).LE.0) GO TO 30
C HERE ABS(X) .GE. 1/2 SO USE MPEXP
      CALL MPEXP (R(I2), R(I2))
      CALL MPADDI (R(I2), -1, R(I3))
      CALL MPADDI (R(I2), 1, R(I2))
      CALL MPDIV (R(I3), R(I2), R(I3))
      GO TO 40
C HERE ABS(X) .LT. 1/2, SO USE MPEXP1 TO AVOID CANCELLATION
   30 CALL MPEXP1 (R(I2), R(I2))
      CALL MPADDI (R(I2), 2, R(I3))
      CALL MPDIV (R(I2), R(I3), R(I3))
C RESTORE SIGN
   40 R(I3) = XS*R(I3)
C ROUND RESULT
   50 CALL MPRES2 (SV)
      CALL MPRND (R(I3), TG, Y, IABS(R(SV)), 1)
C RESTORE EVERYTHING
      CALL MPRESN (SV)
C ENSURE THAT RESULT IS IN CLOSED INTERVAL (-1, +1).
      IF (Y(1).EQ.0) RETURN
      IF (MPGET (Y, 2) .GT. 0) CALL MPCIM (XS, Y)
      RETURN
      END
C $$                   ******  MPTLB  ******
      INTEGER FUNCTION MPTLB (J)
C RETURNS UPPER BOUND ON ABS(J)*LOG2(B).
      INTEGER J, MPCHGB, MPPARN
      MPTLB = MPCHGB (2, MPPARN(1), IABS(J))
      RETURN
      END
C $$                   ******  MPUNFL  ******
      SUBROUTINE MPUNFL (X)
C CALLED ON MULTIPLE-PRECISION UNDERFLOW, IE WHEN THE
C EXPONENT OF MP NUMBER X WOULD BE LESS THAN 1-M.
C ACTION DEPENDS ON PARAMETERS RNDRL AND MXUNFL IN COMMON /MPCOM/ -
C IF RNDRL .LE. 1 THEN
C   IF MXUNFL .EQ. 0 (DEFAULT OPTION IF MPSET CALLED), X IS SET
C                     TO ZERO AND EXECUTION CONTINUES,
C   IF MXUNFL .GT. 0, X IS SET TO ZERO AND EXECUTION CONTINUES
C                     UNLESS MXUNFL UNDERFLOWS HAVE OCCURRED,
C                     WHEN EXECUTION IS TERMINATED BY A CALL
C                     TO MPERR.
C IF RNDRL .EQ. 2, ACTION AS ABOVE EXCEPT X IS SET TO
C   -(SMALLEST POSITIVE REPRESENTABLE NUMBER).
C IF RNDRL .EQ. 3, ACTION AS ABOVE EXCEPT X IS SET TO
C   +(SMALLEST POSITIVE REPRESENTABLE NUMBER).
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, RNDRL, KTUNFL, MXUNFL, DUMMY
      INTEGER B, DUMMY(10), KTUNFL, LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR,
     $  MXSPTR, MXUNFL, RNDRL, SPTR, T, X(1)
C SINCE M MAY HAVE BEEN OVERWRITTEN, CHECK B, T, M ETC.
      CALL MPCHK
C THE UNDERFLOWING NUMBER IS SET TO ZERO
      X(1) = 0
C SET X TO -+ SMALLEST POSITIVE REPRESENTABLE NUMBER IF
C RNDRL = 2 OR 3 RESPECTIVELY.
      IF (RNDRL.GE.2) CALL MPMINR (X)
      IF (RNDRL.EQ.2) X(1) = -X(1)
C MINIMUM EXPONENT INDICATOR (MNEXPN) IS SET TO -M
      MNEXPN = -M
C INCREMENT UNDERFLOW COUNTER (KTUNFL) AND CALL MPERR IF
C MXUNFL UNDERFLOWS HAVE OCCURRED.
      KTUNFL = KTUNFL + 1
      IF (KTUNFL.NE.MXUNFL) RETURN
      WRITE (LUN, 10) KTUNFL
   10 FORMAT (4H ***, I10, 32H MP UNDERFLOWS HAVE OCCURRED ***)
      CALL MPERR
      RETURN
      END
C $$                   ******  MPUNFR  ******
      SUBROUTINE MPUNFR (LUNIT, X)
C READS MP NUMBER X FROM LOGICAL UNIT LUNIT WITHOUT FORMATTING,
C ASSUMING PREVIOUSLY WRITTEN BY MPUNFW.
      COMMON R
      INTEGER I2, LUNIT, R(1), SV, X(1)
      LOGICAL ERR
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPIO (R(I2), (R(SV)+3)/2, (-LUNIT), 1HU, ERR)
      IF (ERR) CALL MPERRM (33HERROR RETURN FROM MPIO IN MPUNFR$)
      CALL MPUNPK (R(I2), X)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPUNFW  ******
      SUBROUTINE MPUNFW (X, LUNIT)
C WRITES MP NUMBER X ON LOGICAL UNIT LUNIT WITHOUT FORMATTING.
C X SHOULD BE A (PACKED OR UNPACKED) MP VARIABLE.  TO SAVE SPACE,
C X IS WRITTEN IN PACKED FORMAT (SO A RECORD OF LENGTH
C INT ((T+3)/2) WORDS IS WRITTEN).
      COMMON R
      INTEGER I2, LUNIT, R(1), SV, X(1)
      LOGICAL ERR
      CALL MPSAVN (SV)
      CALL MPNEW (I2)
      CALL MPPACK (X, R(I2))
      CALL MPIO (R(I2), (R(SV)+3)/2, LUNIT, 1HU, ERR)
      IF (ERR) CALL MPERRM (33HERROR RETURN FROM MPIO IN MPUNFW$)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPUNPK  ******
      SUBROUTINE MPUNPK (Y, X)
C RESTORES THE MP NUMBER X WHICH IS STORED IN PACKED OR
C UNPACKED FORMAT IN THE INTEGER ARRAY Y.  FOR FURTHER
C DETAILS SEE SUBROUTINE MPPACK.
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, IB, J, TWO
      INTEGER B, DUMMY(21), T, X(1), Y(1)
C CHECK IF Y IS PACKED OR NOT.
      IF (IABS(Y(1)) .GT. 1) GO TO 10
C HERE Y IS ZERO OR UNPACKED.
      CALL MPSTR (Y, X)
      RETURN
C HERE Y IS NONZERO AND PACKED.
   10 TWO = 2
      J = T/2
C DO LAST DIGIT SEPARATELY IF T ODD.
      IF (MOD (T, 2) .NE. 0) X(T+2) = Y(J+2)/B
C WORK BACKWARDS IN CASE X AND Y ARE THE SAME ARRAY.
      IF (J .LT. 2) GO TO 30
      DO 20 IB = 2, J
      I = J - IB
      X(2*I+6) = MOD (Y(I+3), B)
   20 X(2*I+5) = Y(I+3)/B
C FIRST WORD OF Y MAY BE SIGNED.
   30 X(TWO+2) = MOD (IABS(Y(1)), B)
      X(TWO+1) = IABS(Y(1))/B
C MOVE SIGN AND EXPONENT
      X(TWO) = Y(TWO)
      X(1) = ISIGN (1, Y(1))
      RETURN
      END
C $$                   ******  MPUPDT  ******
      SUBROUTINE MPUPDT (J)
C UPDATES MINIMUM AND MAXIMUM EXPONENT INDICATORS,
C ASSUMING J IS THE EXPONENT OF A NEWLY FORMED NONZERO MP NUMBER.
C NOTE - MPUPDT DOES NOT CHECK FOR MP OVERFLOW OR UNDERFLOW.
      COMMON /MPCOM/ B, T, M, LUN, MXR, SPTR, MXSPTR, MNSPTR,
     $  MXEXPN, MNEXPN, DUMMY
      INTEGER B, DUMMY(13), J, LUN, M, MNEXPN, MNSPTR, MXEXPN, MXR,
     $  MXSPTR, SPTR, T
      MNEXPN = MIN0 (J, MNEXPN)
      MXEXPN = MAX0 (J, MXEXPN)
      RETURN
      END
C $$                   ******  MPUPK  ******
      SUBROUTINE MPUPK (SOURCE, DEST, LDEST, LFIELD)
C
C THIS SUBROUTINE UNPACKS A PACKED HOLLERITH STRING (SOURCE)
C PLACING ONE CHARACTER PER WORD IN THE ARRAY DEST (AS IF READ IN
C A1 FORMAT). IT CONTINUES UNPACKING UNTIL IT FINDS A SENTINEL ($)
C OR UNTIL IT HAS FILLED LDEST WORDS OF THE ARRAY DEST.
C THE LENGTH OF THE UNPACKED STRING (EXCLUDING THE SENTINEL IF
C ANY) IS RETURNED IN LFIELD.  THUS 0 .LE. LFIELD .LE. LDEST. GT. 0
C
      COMMON R
      INTEGER DEST(1), I, I2, J, K, K2, LDEST, LFIELD, MPPARN, N,
     $  R(1), SENTNL, SOURCE(1), SV, DOLLAR
      LOGICAL MPIS
      DATA DOLLAR /1H$/
C REPLACE $ BY COMPILER-GENERATED END-OF-STRING SENTINEL (IF ANY).
      DATA SENTNL /1H$/
      CALL MPSAVN (SV)
C MPPARN(22) SHOULD RETURN UPPER BOUND ON THE NUMBER OF CHARACTERS
C PER WORD (SEE MPSET2).
      CALL MPNEW2 (I2, MPPARN(22))
      I = 0
      J = 0
C LOOP TO UNPACK EACH WORD OF SOURCE
   10 I = I + 1
      CALL MPUPW (SOURCE (I), R(I2), N)
C ASSUME END OF STRING IF N .LE. 0
      IF (N .LE. 0) GO TO 30
C MOVE EACH CHARACTER TO DEST
      DO 20 K = 1, N
      K2 = I2 + K - 1
C CHECK FOR SENTINEL OR MAXIMUM LENGTH OF DEST
      IF (MPIS (R(K2), DOLLAR) .OR. MPIS (R(K2), SENTNL) .OR.
     $  (J .GE. LDEST)) GO TO 30
      J = J + 1
   20 DEST(J) = R(K2)
      IF (J .LT. LDEST) GO TO 10
   30 LFIELD = J
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MPZETA  ******
      SUBROUTINE MPZETA (N, X)
C
C RETURNS MP X = ZETA(N) FOR INTEGER N .GT. 1, WHERE
C ZETA(N) IS THE RIEMANN ZETA FUNCTION (THE SUM FROM
C I = 1 TO INFINITY OF I**(-N)).
C
C USES THE EULER-MACLAURIN SERIES UNLESS N = 2, 3, 4, 6 OR 8,
C SO SPACE REQUIRED = O(T**2).  (MORE ACCURATELY,
C SPACE = NL*T/2 + O(T) WORDS, WHERE NL IS THE NUMBER OF TERMS
C USED IN ASYMPTOTIC EXPANSION, NL = O(T). )
C TIME = O(T**3)  (COULD BE REDUCED TO O(T**2) IF BERNOULLI
C NUMBERS WERE PRECOMPUTED).
C
C ROUNDING IS DEFINED BY THE PARAMETER RNDRL IN COMMON /MPCOM/ -
C RNDRL = 0 OR 1 - ERROR LESS THAN 0.6 UNITS IN LAST PLACE.
C RNDRL = 2 OR 3 - SEE COMMENTS IN SUBROUTINE MPNZR.
C
      COMMON R
      COMMON /MPCOM/ B, T, DUMMY
      INTEGER I, ID(4), IP, I2, I3, I4, I5, KT, MXINT, NL, NM, NT
      INTEGER NTK, N2, P, Q, SV, TG
      INTEGER B, DUMMY(21), N, R(1), T, X(1)
      INTEGER MPCHGB, MPCMPI, MPPARN, MPTLB
C ZETA(N) KNOWN IN TERMS OF BERNOULLI NUMBERS AND
C PI**N IF N IS EVEN.  ID DEFINES ZETA(2), ... , ZETA(8).
      DATA ID(1), ID(2), ID(3), ID(4) /6, 90, 945, 9450/
C SAVE T ETC.
      CALL MPSAVN (SV)
C INCREASE T AND ALLOCATE SPACE FOR RESULT
      CALL MPGD3 (MPTLB(IABS(T)), TG)
      CALL MPNEW (I2)
      R(I2) = 0
C USE TRUNCATED ARITHMETIC.
      CALL MPSETR (0)
      IF (N .LE. 1) CALL MPERRM (
     $  35HILLEGAL ARGUMENT IN CALL TO MPZETA$)
C HERE N .GT. 1.  SEE IF N = 2, 4, 6 OR 8.
      IF ((N.GT.8).OR.(MOD(N,2).NE.0)) GO TO 10
C HERE ZETA(N) = (PI**N)/ID(N/2)
      CALL MPPI (R(I2))
      CALL MPPWRA (R(I2), N, R(I2))
      N2 = N/2
      CALL MPDIVI (R(I2), ID(N2), R(I2))
      GO TO 90
C SEE IF N IS VERY LARGE.  CAN RETURN WITH ZETA(N) = 1 TO
C REQUIRED PRECISION IF 2**N .GE. B**(T-1) .
   10 IF (N .GE. MPTLB (T-1)) GO TO 80
C CHECK FOR N = 3 (SEE COMMENTS BELOW).
      IF (N .EQ. 3) GO TO 100
C HERE WE MAY USE EULER-MACLAURIN SERIES.
      NL = -1
      MXINT = MPPARN (16)
      Q = 1
      KT = T
      NT = N - 2
C START OF LOOP TO ESTIMATE NL = NUMBER OF TERMS NEEDED IN
C ASYMPTOTIC EXPANSION, AND NM = NUMBER OF TERMS IN FINITE SUM.
   20 NL = NL + 1
C CONSTANT 5 CHOSEN EMPIRICALLY TO MINIMIZE TIME.  IF BERNOULLI
C NUMBERS WERE PRECOMPUTED, THIS CONSTANT COULD BE REDUCED.
      NM = 5*NL + 2
      DO 40 NTK = 1, 2
      NT = NT + 1
   30 IF (Q .LT. (MXINT/NT)) GO TO 40
      Q = Q/B + 1
      KT = KT + 1
      GO TO 30
   40 Q = NT*Q
C 6*NM + NM/4 IS LOWER BOUND ON 2*PI*NM .
      IF (KT .GE. (MPCHGB (IABS(B), NM, N-1) +
     $  MPCHGB (IABS(B), 6*NM + NM/4, 2*NL + 2))) GO TO 20
      P = (T+3)/2
C ALLOCATE SOME WORKING SPACE.
      CALL MPNEW (I3)
C IF NL .LE. 0 NO NEED TO COMPUTE ANY BERNOULLI NUMBERS
      IF (NL .LE. 0) GO TO 60
C ALLOCATE MORE SPACE FOR RESULT OF MPBERN.
      CALL MPNEW2 (I4, NL*P)
      CALL MPNEW (I5)
C COMPUTE REQUIRED BERNOULLI NUMBERS (IF ZETA(N) IS REQUIRED
C FOR SEVERAL N, IT WOULD SAVE TIME TO PRECOMPUTE THESE).
      CALL MPBERN ((-NL), P, R(I4))
      CALL MPCQM (N, 2*NM, R(I3))
      CALL MPDIVI (R(I3), NM, R(I3))
C SUM EULER-MACLAURIN ASYMPTOTIC SERIES FIRST
      DO 50 I = 1, NL
      IP = I4 + (I-1)*P
      CALL MPUNPK (R(IP), R(I5))
      CALL MPMUL (R(I3), R(I5), R(I5))
      CALL MPADD (R(I2), R(I5), R(I2))
      CALL MPMULS (R(I3), N+2*I-1, N+2*I, 2*I+1, 2*I+2)
   50 CALL MPMULS (R(I3), 1, 1, NM, NM)
C ADD INTEGRAL APPROXIMATION AND MULTIPLY BY NM**(1-N)
      CALL MPADDQ (R(I2), 1, N-1, R(I2))
      CALL MPSCAL (R(I2), NM, 1-N)
C ADD FINITE SUM IN FORWARD DIRECTION SO CAN REDUCE T
C MORE EASILY THAN IF BACKWARD DIRECTION WERE USED.
   60 R(I3+1) = 0
      DO 70 I = 2, NM
C REDUCE T FOR I**(-N) COMPUTATION IF POSSIBLE
      T = MAX0 (2, TG + R(I3+1))
C COMPUTE I**(-N) USING MPSCAL.
      CALL MPCIM (1, R(I3))
      CALL MPSCAL (R(I3), I, -N)
C NOW R(I3) IS I**(-N).  HALVE LAST TERM IN FINITE SUM.
      IF (I.EQ.NM) CALL MPDIVI (R(I3), 2, R(I3))
C RESTORE T FOR ADDITION
      T = TG
C LEAVE FINITE SUM LOOP IF MP UNDERFLOW OCCURRED
      IF (R(I3).EQ.0) GO TO 80
   70 CALL MPADD (R(I3), R(I2), R(I2))
C FINAL ADDITION
   80 CALL MPADDI (R(I2), 1, R(I2))
C RESTORE RNDRL AND ROUND RESULT
   90 CALL MPSETR (IABS(R(SV+2)))
      CALL MPRND (R(I2), TG, X, IABS(R(SV)), 1)
C RESTORE EVERYTHING AND CHECK RESULT
      CALL MPRESN (SV)
      IF ((MPCMPQ (X, 1, 2) .LT. 0) .OR. (MPCMPI (X, 2) .GE. 0))
     $  CALL MPERRM (43HERROR OCCURRED IN MPZETA, RESULT INCORRECT$)
C ROUNDING DOWN MAY HAVE GIVEN RESULT LESS THAN ONE
      IF (MPCMPI (X, 1) .LT. 0) CALL MPCIM (1, X)
      RETURN
C HERE USE GOSPERS SERIES FOR ZETA(3).  THIS IS FASTER AND USES
C LESS SPACE THAN THE EULER-MACLAURIN SERIES.
C SERIES FOR OTHER ODD N ARE GIVEN BY H. RIESEL IN
C BIT 13 (1973), 97-113.
  100 CALL MPNEW (I3)
      CALL MPCQM (1, 4, R(I2))
      CALL MPCQM (5, 4, R(I3))
      I = 0
C LOOP TO SUM GOSPERS SERIES
  110 I = I + 1
C REDUCE T IF POSSIBLE
      T = MAX0 (2, MIN0 (TG, TG + R(I3+1)))
      CALL MPMULQ (R(I3), (-I), 4*I+2, R(I3))
      CALL MPMULS (R(I3), I, I, I+1, I+1)
C RESTORE T FOR ADDITION
      T = TG
      CALL MPADD (R(I2), R(I3), R(I2))
C LOOP UNTIL TERMS ARE SMALL
      IF ((R(I3) .NE. 0) .AND. (R(I3+1) .GT. (-T))) GO TO 110
      GO TO 80
      END
C $$                   ******  MP40D  ******
      SUBROUTINE MP40D (N, X)
C FIXED-POINT OUTPUT ROUTINE, WRITES MP X ON UNIT LUN WITH
C N DECIMAL PLACES, ASSUMING -10 .LT. X .LT. 100.
C FOR ROUNDING OPTIONS SEE COMMENTS IN SUBROUTINE MPOUT.
      COMMON R
      LOGICAL ERR
      INTEGER I2, MPPARN, N, R(1), SV, X(1)
C DO NOTHING IF N NONPOSITIVE
      IF (N.LE.0) RETURN
      CALL MPSAVN (SV)
C ALLOCATE N+3 WORDS OF TEMPORARY SPACE.
      CALL MPNEW2 (I2, N+3)
C CONVERT TO CHARACTER FORMAT AND PRINT
      CALL MPOUT (X, R(I2), N+3, N)
      CALL MPIO (R(I2), N+3, MPPARN(4),
     $  37H(8X,13A1,4(1X,10A1)/(10X,5(1X,10A1))), ERR)
      IF (ERR) CALL MPERRM (32HERROR RETURN FROM MPIO IN MP40D$)
      CALL MPRESN (SV)
      RETURN
      END
C $$                   ******  MP40F  ******
      SUBROUTINE MP40F (N, X)
C THIS ROUTINE IS REDUNDANT, BUT IS INCLUDED FOR COMPATIBILITY
C WITH EARLIER VERSIONS OF THE MP PACKAGE.
      INTEGER N, X(1)
      CALL MPFOUT (X, N)
      RETURN
      END
C $$
