   MODULE FMVALS



!  These are the global and saved variables used by the FM and ZM packages.

!  See the User's Manual in the ReadMe file for further description of some

!  of these variables.



!  They are initialized assuming the program will run on a 32-bit computer

!  with variables in FM.f having names beginning with 'M' being declared

!  as having 64-bit representations (DOUBLE PRECISION).



!  For a machine with a different architecture, or for setting the precision

!  level to a different value, CALL FMSET(NPREC) before doing any multiple

!  precision operations.  FMSET tries to initialize the variables to the

!  best values for the given machine.  To have the values chosen by FMSET

!  written on unit KW, CALL FMVARS.



!  Base and precision will be set to give slightly more than 50 decimal

!  digits of precision, giving the user 50 significant digits of precision

!  along with several base ten guard digits.



!  MBASE is set to 10**7.

!  JFORM1 and JFORM2 are set to 1PE format displaying 50 significant digits.



!  The trace option is set off.

!  The mode for angles in trig functions is set to radians.

!  The rounding mode is set to symmetric rounding (to nearest), with the

!  option for perfect rounding off.

!  Warning error message level is set to 1.

!  Cancellation error monitor is set off.

!  Screen width for output is set to 80 columns.

!  The exponent character for FM output is set to 'M'.

!  Debug error checking is set off.



!  KW, the unit number for all FM output, is set to 6.



!  The size of all arrays is controlled by defining two parameters:

!  NDIGMX is the maximum value the user can set NDIG,

!  NBITS  is an upper bound for the number of bits used to represent

!         integers in an M-variable word.



      INTEGER, PARAMETER :: NDIGMX = 256

      INTEGER, PARAMETER :: NBITS  = 64



      INTEGER, PARAMETER :: LPACK  = (NDIGMX+1)/2 + 1

      INTEGER, PARAMETER :: LUNPCK = (11*NDIGMX)/5 + 20

      INTEGER, PARAMETER :: LMWA   = 2*LUNPCK

      INTEGER, PARAMETER :: LJSUMS = 8*(LUNPCK+2)

      INTEGER, PARAMETER :: LMBUFF = ((LUNPCK+3)*(NBITS-1)*301)/2000 + 6



!             KW is the unit number for standard output from the

!                FM package.  This includes trace output and error

!                messages.

!

      INTEGER, SAVE :: KW = 6



!             MAXINT should be set to a very large integer, possibly

!                    the largest representable integer for the current

!                    machine.  For most 32-bit machines, MAXINT is set

!                    to  2**53 - 1 = 9.007D+15  when double precision

!                    arithmetic is used for M-variables.  Using integer

!                    M-variables usually gives MAXINT = 2**31 - 1 =

!                    2147483647.

!                    Setting MAXINT to a smaller number is ok, but this

!                    unnecessarily restricts the permissible range of

!                    MBASE and MXEXP.



      DOUBLE PRECISION, SAVE :: MAXINT = 9007199254740991.0D0

! Integer initialization

!      INTEGER, SAVE :: MAXINT = 2147483647



!             INTMAX is a large value close to the overflow threshold

!                    for integer variables.  It is usually 2**31 - 1

!                    for machines with 32-bit integer arithmetic.



      INTEGER, SAVE :: INTMAX = 2147483647



!             DPMAX should be set to a value near the machine's double

!                   precision overflow threshold, so that DPMAX and

!                   1.0D0/DPMAX are both representable in double

!                   precision.



      DOUBLE PRECISION, SAVE :: DPMAX = 1.797D+308/5.0D0



!             SPMAX should be set to a value near the machine's single

!                   precision overflow threshold, so that 1.01*SPMAX

!                   and 1.0/SPMAX are both representable in single

!                   precision.



      REAL, SAVE :: SPMAX = 3.40E+38/5.0



!             NDG2MX is the maximum value for NDIG that can be used

!                    internally.  FM routines may raise NDIG above

!                    NDIGMX temporarily, to compute correctly

!                    rounded results.

!                    In the definition of LUNPCK, the '11/5' condition

!                    allows for carrying at least NDIG guard digits

!                    when the option for perfect rounding is selected.

!                    The '+ 20' condition allows for the need to carry

!                    many guard digits when using a small base like 2.



      INTEGER, PARAMETER :: NDG2MX = LUNPCK - 1



!             MXBASE is the maximum value for MBASE.



      DOUBLE PRECISION, SAVE :: MXBASE = 94906265.0D0

! Integer initialization

!      INTEGER, SAVE :: MXBASE = 46340



!             MBASE is the currently used base for arithmetic.



      DOUBLE PRECISION, SAVE :: MBASE = 1.0D7

! Integer initialization

!      INTEGER, SAVE :: MBASE = 10000



!             NDIG is the number of digits currently being carried.



      INTEGER, SAVE :: NDIG = 9

! Integer initialization

!      INTEGER, SAVE :: NDIG = 14



!             KFLAG is the flag for error conditions.



      INTEGER, SAVE :: KFLAG = 0



!             NTRACE is the trace switch.  Default is no printing.



      INTEGER, SAVE :: NTRACE = 0



!             LVLTRC is the trace level.  Default is to trace only

!                    routines called directly by the user.



      INTEGER, SAVE :: LVLTRC = 1



!             NCALL is the call stack pointer.



      INTEGER, SAVE :: NCALL = 0



!             NAMEST is the call stack.



      INTEGER, PRIVATE :: I

      CHARACTER(6), SAVE :: NAMEST(0:50) = (/ ('MAIN  ' , I = 0, 50) /)



!             Some constants that are often needed are stored with the

!             maximum precision to which they have been computed in the

!             currently used base.  This speeds up the trig, log, power,

!             and exponential functions.



!             NDIGPI is the number of digits available in the currently

!                    stored value of pi (MPISAV).



      INTEGER, SAVE :: NDIGPI = 0



!             MBSPI is the value of MBASE for the currently stored

!                   value of pi.



      DOUBLE PRECISION, SAVE :: MBSPI = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBSPI = 0



!             NDIGE is the number of digits available in the currently

!                   stored value of e (MESAV).



      INTEGER, SAVE :: NDIGE = 0



!             MBSE is the value of MBASE for the currently stored

!                  value of e.



      DOUBLE PRECISION, SAVE :: MBSE = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBSE = 0



!             NDIGLB is the number of digits available in the currently

!                    stored value of LN(MBASE) (MLBSAV).



      INTEGER, SAVE :: NDIGLB = 0



!             MBSLB is the value of MBASE for the currently stored

!                   value of LN(MBASE).



      DOUBLE PRECISION, SAVE :: MBSLB = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBSLB = 0



!             NDIGLI is the number of digits available in the currently

!                    stored values of the four logarithms used by FMLNI

!                    MLN1 - MLN4.



      INTEGER, SAVE :: NDIGLI = 0



!             MBSLI is the value of MBASE for the currently stored

!                   values of MLN1 - MLN4.



      DOUBLE PRECISION, SAVE :: MBSLI = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBSLI = 0



!             MXEXP  is the current maximum exponent.

!             MXEXP2 is the internal maximum exponent. This is used to

!                    define the overflow and underflow thresholds.

!

!             These values are chosen so that FM routines can raise the

!             overflow/underflow limit temporarily while computing

!             intermediate results, and so that EXP(INTMAX) is greater

!             than MXBASE**(MXEXP2+1).

!

!             The overflow threshold is MBASE**(MXEXP+1), and the

!             underflow threshold is MBASE**(-MXEXP-1).

!             This means the valid exponents in the first word of an FM

!             number can range from -MXEXP to MXEXP+1 (inclusive).



      DOUBLE PRECISION, SAVE :: MXEXP  =  58455923.0D0

! Integer initialization

!      INTEGER, SAVE :: MXEXP = 99940964



      DOUBLE PRECISION, SAVE :: MXEXP2 = 117496405.0D0

! Integer initialization

!      INTEGER, SAVE :: MXEXP2 = 200881337



!             KACCSW is a switch used to enable cancellation error

!                    monitoring.  Routines where cancellation is

!                    not a problem run faster by skipping the

!                    cancellation monitor calculations.

!                    KACCSW = 0 means no error monitoring,

!                           = 1 means error monitoring is done.



      INTEGER, SAVE :: KACCSW = 0



!             MEXPUN is the exponent used as a special symbol for

!                    underflowed results.



      DOUBLE PRECISION, SAVE :: MEXPUN = -117497685.0D0

! Integer initialization

!      INTEGER, SAVE :: MEXPUN = -200882617



!             MEXPOV is the exponent used as a special symbol for

!                    overflowed results.



      DOUBLE PRECISION, SAVE :: MEXPOV = 117497685.0D0

! Integer initialization

!      INTEGER, SAVE :: MEXPOV = 200882617



!             MUNKNO is the exponent used as a special symbol for

!                    unknown FM results (1/0, SQRT(-3.0), ...).



      DOUBLE PRECISION, SAVE :: MUNKNO = 117498965.0D0

! Integer initialization

!      INTEGER, SAVE :: MUNKNO = 200883897



!             RUNKNO is returned from FM to real or double conversion

!                    routines when no valid result can be expressed in

!                    real or double precision.  On systems that provide

!                    a value for undefined results (e.g., Not A Number)

!                    setting RUNKNO to that value is reasonable.  On

!                    other systems set it to a value that is likely to

!                    make any subsequent results obviously wrong that

!                    use it.  In either case a KFLAG = -4 condition is

!                    also returned.



      REAL, SAVE :: RUNKNO = -1.01*(3.40E+38/3.0)



!             IUNKNO is returned from FM to integer conversion routines

!                    when no valid result can be expressed as a one word

!                    integer.  KFLAG = -4 is also set.



      INTEGER, SAVE :: IUNKNO = -117496405



!             JFORM1 indicates the format used by FMOUT.



      INTEGER, SAVE :: JFORM1 = 1



!             JFORM2 indicates the number of digits used in FMOUT.



      INTEGER, SAVE :: JFORM2 = 50



!             KRAD = 1 indicates that trig functions use radians,

!                  = 0 means use degrees.



      INTEGER, SAVE :: KRAD = 1



!             KWARN = 0 indicates that no warning message is printed

!                       and execution continues when UNKNOWN or another

!                       exception is produced.

!                   = 1 means print a warning message and continue.

!                   = 2 means print a warning message and stop.



      INTEGER, SAVE :: KWARN = 1



!             KROUND =  1  causes all results to be rounded to the

!                          nearest FM number, or to the value with

!                          an even last digit if the result is halfway

!                          between two FM numbers.

!                    =  0  causes all results to be rounded toward zero

!                          (chopped).

!                    = -1  causes all results to be rounded toward minus

!                          infinity.

!                    =  2  causes all results to be rounded toward plus

!                          infinity.

!                    Regardless of KROUND, when an FM function is called

!                    all intermediate operations are rounded to nearest.

!                    Only the final result returned to the user is rounded

!                    according to KROUND.



      INTEGER, SAVE :: KROUND = 1



!             KRPERF = 1  causes more guard digits to be used, to get

!                         perfect rounding in the mode set by KROUND.

!                         This slows execution speed.

!                    = 0  causes a smaller number of guard digits used,

!                         to give nearly perfect rounding.  This number

!                         is chosen so that the last intermediate result

!                         should have error less than 0.001 unit in the

!                         last place of the final rounded result.



      INTEGER, SAVE :: KRPERF = 0



!             KSWIDE defines the maximum screen width to be used for

!                    all unit KW output.



      INTEGER, SAVE :: KSWIDE = 80



!             KESWCH = 1   causes input to FMINP with no digits before

!                          the exponent letter to be treated as if there

!                          were a leading '1'.  This is sometimes better

!                          for interactive input:  'E7' converts to

!                          10.0**7.

!                    = 0   causes a leading zero to be assumed.  This

!                          gives compatibility with Fortran:  'E7'

!                          converts to 0.0.



      INTEGER, SAVE :: KESWCH = 1



!             CMCHAR defines the exponent letter to be used for

!                    FM variable output from FMOUT, as in 1.2345M+678.

!                    Change it to 'E' for output to be read by a

!                    non-FM program.



      CHARACTER, SAVE :: CMCHAR = 'M'



!             KSUB is an internal flag set during subtraction so that

!                  the addition routine will negate its second argument.



      INTEGER, SAVE :: KSUB = 0



!             JRSIGN is an internal flag set during arithmetic operations

!                    so that the rounding routine will know the sign of the

!                    final result.



      INTEGER, SAVE :: JRSIGN = 0



!             KDEBUG = 0   Error checking is not done for valid input

!                          arguments and parameters like NDIG and MBASE

!                          upon entry to each routine.

!                    = 1   Error checking is done.



      INTEGER, SAVE :: KDEBUG = 0



!             LHASH is a flag variable used to indicate when to initialize

!                   two hash tables that are used for character look-up

!                   during input conversion.  LHASH = 1 means that the tables

!                   have been built.

!             LHASH1 and LHASH2 are the array dimensions of the tables.

!             KHASHT and KHASHV are the two tables.



      INTEGER, SAVE :: LHASH = 0

      INTEGER, PARAMETER :: LHASH1 =   0

      INTEGER, PARAMETER :: LHASH2 = 256

      INTEGER, SAVE :: KHASHT(LHASH1:LHASH2),KHASHV(LHASH1:LHASH2)



!             DPEPS is the approximate machine precision.

      DOUBLE PRECISION, SAVE :: DPEPS = 2.220446049250313D-16



!             Saved constants that depend on MBASE.



      DOUBLE PRECISION, SAVE :: MBLOGS = 1.0D7

! Integer initialization

!      INTEGER, SAVE :: MBLOGS = 0

!             (Setting MBLOGS to zero here will cause the other variables that

!              depend on MBASE to automatically be defined when the first FM

!              operation is done.)



      REAL, SAVE :: ALOGMB = 1.611810E+1

      REAL, SAVE :: ALOGM2 = 2.325350E+1

      REAL, SAVE :: ALOGMX = 3.673680E+1

      REAL, SAVE :: ALOGMT = 7.0E0



      INTEGER, SAVE :: NGRD21 = 1

      INTEGER, SAVE :: NGRD52 = 2

      INTEGER, SAVE :: NGRD22 = 2

      DOUBLE PRECISION, SAVE :: MEXPAB = 2.3499281D+7

! Integer initialization

!      INTEGER, SAVE :: MEXPAB = 23499281



      DOUBLE PRECISION, SAVE :: DLOGMB = 1.611809565095832D+1

      DOUBLE PRECISION, SAVE :: DLOGTN = 2.302585092994046D+0

      DOUBLE PRECISION, SAVE :: DLOGTW = 6.931471805599453D-1

      DOUBLE PRECISION, SAVE :: DPPI   = 3.141592653589793D+0

      DOUBLE PRECISION, SAVE :: DLOGTP = 1.837877066409345D+0

      DOUBLE PRECISION, SAVE :: DLOGPI = 1.144729885849400D+0

      DOUBLE PRECISION, SAVE :: DLOGEB = 2.236222824932432D+0



      DOUBLE PRECISION, SAVE :: MBASEL = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBASEL = 0

      DOUBLE PRECISION, SAVE :: MBASEN = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBASEN = 0



      INTEGER, SAVE :: NDIGL = 0

      INTEGER, SAVE :: NDIGN = 0

      INTEGER, SAVE :: N21

      INTEGER, SAVE :: NGRDN



!             These variables are used by FM_RANDOM_NUMBER.

!             MBRAND is the base used for the random number arithmetic.

!                    It needs to remain the same even if the user changes MBASE.



      DOUBLE PRECISION, SAVE :: MBRAND = 1.0D7

! Integer initialization

!      INTEGER, SAVE :: MBRAND = 10000



      DOUBLE PRECISION, SAVE :: MRNX(0:LUNPCK)

      INTEGER, SAVE :: START_RANDOM_SEQUENCE = -1



!             Work areas for temporary FM calculations.



      DOUBLE PRECISION, SAVE :: MWA(LMWA),MWD(LMWA),MWE(LMWA)

      DOUBLE PRECISION, SAVE :: M01(0:LUNPCK),M02(0:LUNPCK),M03(0:LUNPCK),  &

                                M04(0:LUNPCK),M05(0:LUNPCK),M06(0:LUNPCK)

      DOUBLE PRECISION, SAVE :: MPA(0:LUNPCK),MPB(0:LUNPCK),MPC(0:LUNPCK)

      DOUBLE PRECISION, SAVE :: MPMA(0:LUNPCK),MPMB(0:LUNPCK)

      DOUBLE PRECISION, SAVE :: MJSUMS(0:LJSUMS)

      CHARACTER, SAVE :: CMBUFF(LMBUFF)



!             Saved FM constants.



      DOUBLE PRECISION, SAVE :: MPISAV(0:LUNPCK),MESAV(0:LUNPCK),  &

                  MLBSAV(0:LUNPCK),MLN1(0:LUNPCK),MLN2(0:LUNPCK),  &

                  MLN3(0:LUNPCK),MLN4(0:LUNPCK)



!             Set JFORMZ to ' 1.23 + 4.56 i ' format.



      INTEGER, SAVE :: JFORMZ = 1



!             Set JPRNTZ to print real and imaginary parts on one

!             line whenever possible.



      INTEGER, SAVE :: JPRNTZ = 1



!             These arrays are work areas for temporary ZM calculations.



      INTEGER, PARAMETER :: LPACKZ = 2*LPACK+1

      INTEGER, PARAMETER :: LUNPKZ = 2*LUNPCK+1

      INTEGER, PARAMETER :: KPTIMP = LPACK+1

      INTEGER, PARAMETER :: KPTIMU = LUNPCK+1

      DOUBLE PRECISION, SAVE :: MZ01(0:LUNPKZ),MZ02(0:LUNPKZ),MZ03(0:LUNPKZ),  &

                                MZ04(0:LUNPKZ),MPX(0:LUNPKZ),MPY(0:LUNPKZ)

      INTEGER, PARAMETER :: LMBUFZ = 2*LMBUFF+10

      CHARACTER, SAVE :: CMBUFZ(LMBUFZ)



!             MBERN  is the array used to save Bernoulli numbers so they

!                    do not have to be re-computed on subsequent calls.

!             MBSBRN is the value of MBASE for the currently saved

!                    Bernoulli numbers.



      DOUBLE PRECISION, SAVE :: MBSBRN = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBSBRN = 0



!             NWDBRN is the total number of words used for the saved

!                    Bernoulli numbers.



      INTEGER, SAVE :: NWDBRN = 0



!             NUMBRN is the number of the largest Bernoulli number

!                    saved using base MBSBRN.



      INTEGER, SAVE :: NUMBRN = 0



!  LMBERN is the size of the array NPTBRN for saving Bernoulli numbers.



      INTEGER, PARAMETER :: LMBERN = 250000

      DOUBLE PRECISION, SAVE :: MBERN(0:LMBERN)



!             B(2N) starts in MBERN(NPTBRN(N)) for 2N >= 28.

!             NPTBRN(N) is -1 if B(2N) has not been computed

!             previously.



      INTEGER, SAVE :: NPTBRN(LMBERN/10) = (/ (-1 , I = 1, LMBERN/10) /)



!             M_GAMMA_MA  is the last input value to FMGAM, and

!             M_GAMMA_MB  is the corresponding output value.

!             MBSGAM is the value of MBASE used in the currently stored

!                    value of M_GAMMA_MA and M_GAMMA_MB.

!             NDGGAM is the maximum NDIG used in the currently stored

!                    value of M_GAMMA_MA and M_GAMMA_MB.



      DOUBLE PRECISION, SAVE :: MBSGAM = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBSGAM = 0



      INTEGER, SAVE :: NDGGAM = 0



!             M_LN_2PI holds the saved value of LN(2*pi).

!             MBS2PI is the value of MBASE used in the currently stored

!                    value of LN(2*pi).

!             NDG2PI is the maximum NDIG used in the currently stored

!                    value of LN(2*pi).



      DOUBLE PRECISION, SAVE :: MBS2PI = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBS2PI = 0



      INTEGER, SAVE :: NDG2PI = 0



!             M_EULER is the saved value of Euler's constant.

!             MBSEUL is the value of MBASE used in the currently stored

!                    value of M_EULER.

!             NDGEUL is the maximum NDIG used in the currently stored

!                    value of M_EULER.



      DOUBLE PRECISION, SAVE :: MBSEUL = 0.0D0

! Integer initialization

!      INTEGER, SAVE :: MBSEUL = 0



      INTEGER, SAVE :: NDGEUL = 0



!             MRETRY is used to detect convergence in some cases where

!                    cancellation error forces a retry.



      DOUBLE PRECISION, SAVE :: MRETRY(0:LUNPCK)



   END MODULE

