
This is a list of the files for version 1.1 of FMLIB and ZMLIB.

1.  zmlib.f90           Subroutine library for complex operations

2.  fmlib.f90           Subroutine library for real operations

3.  testzm.f90          Test program for most of the ZM routines

4.  zmsample.f90        Small sample program using ZM

5.  zmsample.chk        Expected output file from zmsample.f90

6.  testfm.f90          Test program for most of the FM routines

7.  fmsample.f90        Small sample program using FM

8.  fmsample.chk        Expected output file from fmsample.f90

9.  fmzm90.f90          Fortran-90 interface module

10. fmzmcomm.f90        Fortran-90 module for common blocks

11. Test90.f90          Test program for fmzm90

12. Sample90.f90        Small sample program using fmzm90

13. SAMPLE90.CHK        Expected output file from sample90.f


A makefile detailing the building of the ZM and FM libraries and the
running of all the test examples is provided.

My web site contains copies of other related papers and files.  In
1998 it was located at "http://cse.eng.lmu.edu/~dsmith/FMLIB.html".
If that location changes in the future, try searching for the keyword
"dsmithfmlibrary" to find the site.



===========================================================================
===========================================================================


                    USER'S GUIDE FOR THE FM PACKAGE


The various lists of available multiple precision operations and
routines have been collected here, along with some general advice
on using the package.

See the programs fmsample.f90, zmsample.f90, and sample90.f90 for some
examples of initializing and using the package.

This version of the package uses code with the names of routines,
variables, and files in lower case, but in this file as well as in
comment lines in the code such names are emphasized by writing them
in upper case.


INITIALIZATION:    Before ANY part of the FM package can be used, the
                   base and precision to be used must be defined, along
                   with several other saved parameters.

                   If any complex arithmetic is to be used, put
      CALL ZMSET(N)
                   in the main program before any multiple precision
                   operations are done, with N replaced by the number
                   of decimal digits of accuracy to be used.
                   This will initialize both FMLIB and ZMLIB packages.

                   If only real arithmetic is to be used, put
      CALL FMSET(N)
                   in the main program before any multiple precision
                   operations are done, with N replaced by the number
                   of decimal digits of accuracy to be used.
                   This will initialize the FMLIB package.

                   One of these calls must be present whether the FM/ZM
                   routines are to be called directly by the user, or
                   the Fortran-90 interface routines are to be used.
                   For compatibility when the interface module is used,
                   the derived type routine names FM_SET or ZM_SET may
                   be used in place of FMSET or ZMSET.

MODULE/COMMON:     Some common blocks used for saved parameters must be
                   declared in the main program.  If the Fortran-90
                   interface is used, put
      USE FMZM
                   at the beginning of the main program and also in
                   each routine that uses type FM, IM, or ZM variables.

                   If the Fortran-90 interface is not used, put the
                   common blocks given in zmsample.f90 at the top of the
                   main program if complex arithmetic is used, or put
                   the common blocks given in fmsample.f90 at the top of
                   the main program if only real arithmetic is used.

ROUTINE NAMES:     For each multiple precision operation there are
                   several routines with related names that perform
                   variations of that operation.  For example, the
                   addition operation has these forms:

                   Using the Fortran-90 interface module, to perform
                   real (floating-point) multiple precision addition,
                   declare the variables with

      TYPE ( FM ) A,B,C

                   and then add using

      C = A + B

                   Normally, using the interface module avoids the need
                   to know the name of the FM routine being called.  For
                   some operations, usually those that are not Fortran-90
                   functions (such as formatting a number), a direct call
                   may be needed.  The addition above can be done as

      CALL FM_ADD(A,B,C)

                   If fmlib.f90 is used without the interface module, then
                   the multiple precision numbers are declared as arrays

      DOUBLE PRECISION A(0:LUNPCK),B(0:LUNPCK),C(0:LUNPCK)

                   where LUNPCK is defined in the PARAMETER statement
                   included with the FM common blocks.  The numbers are
                   then added by calling the FMLIB routine where the
                   arguments are assumed to be arrays, not TYPE (FM)
                   derived types:

      CALL FMADD(A,B,C)

                   For each of the routines listed below (like FMADD),
                   there is a version that assumes the arguments have
                   the appropriate derived type.  These have the same
                   names, except "_" has been inserted after the first
                   two letters of the name (like FM_ADD).

                   If direct calls are done instead of using the
                   interface module, there is another form for these
                   routine names that is used when the arrays have been
                   declared in a packed format that takes roughly half
                   as much space:

      DOUBLE PRECISION A(0:LPACK),B(0:LPACK),C(0:LPACK)

                   The routines that work with packed arrays have names
                   where the second letter has been changed from M to P:

      CALL FPADD(A,B,C)

                   The packed versions are slower.

                   For multiple precision integer or complex operations
                   there are similar Fortran-90 derived types and the
                   various routines:

      USE FMZM
      ...
      TYPE ( IM ) A,B,C
      TYPE ( ZM ) X,Y,Z
      ...
      C = A + B
      ...
      Z = X + Y

                   with explicit calls of the form

      CALL IM_ADD(A,B,C)
      CALL ZM_ADD(X,Y,Z)

                   Without using the interface module:

      DOUBLE PRECISION A(0:LUNPCK),B(0:LUNPCK),C(0:LUNPCK)
      DOUBLE PRECISION X(0:LUNPKZ),Y(0:LUNPKZ),Z(0:LUNPKZ)
      ...
      CALL IMADD(A,B,C)
      ...
      CALL ZMADD(X,Y,Z)

                   Packed format without the interface module:

      DOUBLE PRECISION A(0:LPACK),B(0:LPACK),C(0:LPACK)
      DOUBLE PRECISION X(0:LPACKZ),Y(0:LPACKZ),Z(0:LPACKZ)
      ...
      CALL IPADD(A,B,C)
      ...
      CALL ZPADD(X,Y,Z)



------------------------------------------------------------------------
-------------------   Fortran-90 Interface Notes   ---------------------



There are three multiple precision data types:
   FM  (multiple precision real)
   IM  (multiple precision integer)
   ZM  (multiple precision complex)

Some the the interface routines assume that the precision chosen
in the calling program (using FM_SET or ZM_SET) represents more
significant digits than does the machine's double precision.

All the functions defined in this module are standard Fortran-90
functions, except for several direct conversion functions:

TO_FM is a function for converting other types of numbers to type
FM.  Note that TO_FM(3.12) converts the REAL constant to FM, but
it is accurate only to single precision.  TO_FM(3.12D0) agrees
with 3.12 to double precision accuracy, and TO_FM('3.12') or
TO_FM(312)/TO_FM(100) agrees to full FM accuracy.

TO_IM converts to type IM, and TO_ZM converts to type ZM.

Functions are also supplied for converting the three multiple
precision types to the other numeric data types:
   TO_INT   converts to machine precision integer
   TO_SP    converts to single precision
   TO_DP    converts to double precision
   TO_SPZ   converts to single precision complex
   TO_DPZ   converts to double precision complex

WARNING:   When multiple precision type declarations are inserted
           in an existing program, take care in converting functions
           like DBLE(X), where X has been declared as a multiple
           precision type.  If X was single precision in the
           original program, then replacing the DBLE(X) by TO_DP(X)
           in the new version could lose accuracy.
           For this reason, the Fortran type-conversion functions
           defined in this module assume that results should be
           multiple precision whenever inputs are.  Examples:
           DBLE(TO_FM('1.23E+123456')) is type FM
           REAL(TO_FM('1.23E+123456')) is type FM
           REAL(TO_ZM('3.12+4.56i'))   is type FM   = TO_FM('3.12')
           INT(TO_FM('1.23'))          is type IM   = TO_IM(1)
           INT(TO_IM('1E+23'))         is type IM
           CMPLX(TO_FM('1.23'),TO_FM('4.56')) is type ZM

Programs using this module may sometimes need to call FM, IM, or
ZM routines directly.  This is normally the case when routines are
needed that are not Fortran-90 intrinsics, such as the formatting
subroutine FMFORM.  In a program using this module, suppose MAFM
has been declared with TYPE ( FM ) MAFM.  To use the routine FMFORM,
which expects the second argument to be an array and not a derived
type, the call would have to be CALL FMFORM('F65.60',MAFM%MFM,ST1)
so that the array contained in MAFM is passed.

As an alternative so the user can refer directly to the FM-, IM-,
and ZM-type variables and avoid the cumbersome "%MFM" suffixes,
this module contains a collection of interface routines to supply
any needed argument conversions.  For each FM, IM, and ZM routine
that is designed to be called by the user, there is also a version
that assumes any multiple-precision arguments are derived types
instead of arrays.  Each interface routine has the same name as
the original with an underscore after the first two letters of the
routine name.  To convert the number to a character string with
F65.60 format, use CALL FM_FORM('F65.60',MAFM,ST1) if MAFM is of
TYPE ( FM ), or use CALL FMFORM('F65.60',MA,ST1) if MA is declared
as an array.  All the routines shown below may be used this way.

For each of the operations  =, +, -, *, /, **, .EQ., .NE., .GT.,
.GE., .LT., and .LE., the interface module defines all mixed mode
variations involving one of the three multiple precision derived
types and another argument having one of the types:
{ integer, real, double, complex, complex double, FM, IM, ZM }.
So mixed mode expressions such as
      MAFM = 12
      MAFM = MAFM + 1
      IF (ABS(MAFM).LT.1.0D-23) THEN
are handled correctly.

Not all the named functions are defined for all three multiple
precision derived types, so the list below shows which can be used.
The labels "real", "integer", and "complex" refer to types FM, IM,
and ZM respectively, "string" means the function accepts character
strings (e.g., TO_FM('3.45')), and "other" means the function can
accept any of the machine precision data types integer, real,
double, complex, or complex double.  For functions that accept two
or more arguments, like ATAN2 or MAX, all the arguments must be of
the same type.


AVAILABLE OPERATIONS:

   =
   +
   -
   *
   /
   **
   .EQ.
   .NE.
   .GT.
   .GE.
   .LT.
   .LE.
   ABS          real    integer    complex
   ACOS         real               complex
   AIMAG                           complex
   AINT         real               complex
   ANINT        real               complex
   ASIN         real               complex
   ATAN         real               complex
   ATAN2        real
   BTEST                integer
   CEILING      real               complex
   CMPLX        real    integer
   CONJ                            complex
   COS          real               complex
   COSH         real               complex
   DBLE         real    integer    complex
   DIGITS       real    integer    complex
   DIM          real    integer
   DINT         real               complex
   DOTPRODUCT   real    integer    complex
   EPSILON      real
   EXP          real               complex
   EXPONENT     real
   FLOOR        real    integer    complex
   FRACTION     real               complex
   HUGE         real    integer    complex
   INT          real    integer    complex
   LOG          real               complex
   LOG10        real               complex
   MATMUL       real    integer    complex
   MAX          real    integer
   MAXEXPONENT  real
   MIN          real    integer
   MINEXPONENT  real
   MOD          real    integer
   MODULO       real    integer
   NEAREST      real
   NINT         real    integer    complex
   PRECISION    real               complex
   RADIX        real    integer    complex
   RANGE        real    integer    complex
   REAL         real    integer    complex
   RRSPACING    real
   SCALE        real               complex
   SETEXPONENT  real
   SIGN         real    integer
   SIN          real               complex
   SINH         real               complex
   SPACING      real
   SQRT         real               complex
   TAN          real               complex
   TANH         real               complex
   TINY         real    integer    complex
   TO_FM        real    integer    complex    string    other
   TO_IM        real    integer    complex    string    other
   TO_ZM        real    integer    complex    string    other
   TO_INT       real    integer    complex
   TO_SP        real    integer    complex
   TO_DP        real    integer    complex
   TO_SPZ       real    integer    complex
   TO_DPZ       real    integer    complex



------------------------------------------------------------------------
-----------   Routines for Real Floating-Point Operations   ------------



  These are the FM routines that are designed to be called by
  the user.  All are subroutines except logical function FMCOMP.
  MA, MB, MC refer to FM format numbers.

  In each case it is permissible to use the same array more than
  once in the calling sequence.  The statement MA = MA*MA can
  be written CALL FMMPY(MA,MA,MA).

  For each of these routines there is also a version available for
  which the argument list is the same but all FM numbers are in packed
  format.  The routines using packed numbers have the same names except
  'FM' is replaced by 'FP' at the start of each name.


  FMABS(MA,MB)         MB = ABS(MA)

  FMACOS(MA,MB)        MB = ACOS(MA)

  FMADD(MA,MB,MC)      MC = MA + MB

  FMADDI(MA,IVAL)      MA = MA + IVAL   Increment an FM number by a one
                                        word integer.  Note this call
                                        does not have an "MB" result
                                        like FMDIVI and FMMPYI.

  FMASIN(MA,MB)        MB = ASIN(MA)

  FMATAN(MA,MB)        MB = ATAN(MA)

  FMATN2(MA,MB,MC)     MC = ATAN2(MA,MB)

  FMBIG(MA)            MA = Biggest FM number less than overflow.

  FMCHSH(MA,MB,MC)     MB = COSH(MA),  MC = SINH(MA).  Faster than
                            making two separate calls.

  FMCOMP(MA,LREL,MB)        Logical comparison of MA and MB.
                            LREL is a CHARACTER*2 value identifying
                            which comparison is made.
                            Example:  IF (FMCOMP(MA,'GE',MB)) ...

  FMCONS                    Set several saved constants that depend
                            on MBASE, the base being used.  FMCONS
                            should be called immediately after
                            changing MBASE.

  FMCOS(MA,MB)         MB = COS(MA)

  FMCOSH(MA,MB)        MB = COSH(MA)

  FMCSSN(MA,MB,MC)     MB = COS(MA),  MC = SIN(MA).  Faster than
                            making two separate calls.

  FMDIG(NSTACK,KST)         Find a set of precisions to use during
                            Newton iteration for finding a simple
                            root starting with about double
                            precision accuracy.

  FMDIM(MA,MB,MC)      MC = DIM(MA,MB)

  FMDIV(MA,MB,MC)      MC = MA/MB

  FMDIVI(MA,IVAL,MB)   MB = MA/IVAL   IVAL is a one word integer.

  FMDP2M(X,MA)         MA = X    Convert from double precision to FM.

  FMDPM(X,MA)          MA = X    Convert from double precision to FM.
                                 Much faster than FMDP2M, but MA agrees
                                 with X only to D.P. accuracy.  See
                                 the comments in the two routines.

  FMEQ(MA,MB)          MB = MA   Both have precision NDIG.
                                 This is the version to use for
                                 standard  B = A  statements.

  FMEQU(MA,MB,NA,NB)   MB = MA   Version for changing precision.
                                 MA has NA digits (i.e., MA was
                                 computed using NDIG = NA), and MB
                                 will be defined having NB digits.
                                 MB is zero-padded if NB.GT.NA
                                 MB is rounded if NB.LT.NA

  FMEXP(MA,MB)         MB = EXP(MA)

  FMFORM(FORM,MA,STRING)    MA is converted to a character string
                               using format FORM and returned in
                               STRING.  FORM can represent I, F,
                               E, or 1PE formats.  Example:
                               CALL FMFORM('F60.40',MA,STRING)

  FMFPRT(FORM,MA)           Print MA on unit KW using FORM format.

  FMI2M(IVAL,MA)       MA = IVAL   Convert from one word integer
                                   to FM.

  FMINP(LINE,MA,LA,LB) MA = LINE   Input conversion.
                                   Convert LINE(LA) through LINE(LB)
                                   from characters to FM.

  FMINT(MA,MB)         MB = INT(MA)    Integer part of MA.

  FMIPWR(MA,IVAL,MB)   MB = MA**IVAL   Raise an FM number to a one
                                       word integer power.

  FMLG10(MA,MB)        MB = LOG10(MA)

  FMLN(MA,MB)          MB = LOG(MA)

  FMLNI(IVAL,MA)       MA = LOG(IVAL)   Natural log of a one word
                                        integer.

  FMM2DP(MA,X)         X  = MA     Convert from FM to double precision.

  FMM2I(MA,IVAL)       IVAL = MA   Convert from FM to integer.

  FMM2SP(MA,X)         X  = MA     Convert from FM to single precision.

  FMMAX(MA,MB,MC)      MC = MAX(MA,MB)

  FMMIN(MA,MB,MC)      MC = MIN(MA,MB)

  FMMOD(MA,MB,MC)      MC = MA mod MB

  FMMPY(MA,MB,MC)      MC = MA*MB

  FMMPYI(MA,IVAL,MB)   MB = MA*IVAL    Multiply by a one word integer.

  FMNINT(MA,MB)        MB = NINT(MA)   Nearest FM integer.

  FMOUT(MA,LINE,LB)    LINE = MA   Convert from FM to character.
                                   LINE is a character array of
                                   length LB.

  FMPI(MA)             MA = pi

  FMPRNT(MA)                Print MA on unit KW using current format.

  FMPWR(MA,MB,MC)      MC = MA**MB

  FMREAD(KREAD,MA)     MA   is returned after reading one (possibly
                            multi-line) FM number on unit KREAD.  This
                            routine reads numbers written by FMWRIT.

  FMRPWR(MA,K,J,MB)    MB = MA**(K/J)  Rational power.  Faster than
                            FMPWR for functions like the cube root.

  FMSET(NPREC)              Set default values and machine-dependent
                            variables to give at least NPREC base 10
                            digits plus three base 10 guard digits.
                            Must be called to initialize FM package.

  FMSIGN(MA,MB,MC)     MC = SIGN(MA,MB)   Sign transfer.

  FMSIN(MA,MB)         MB = SIN(MA)

  FMSINH(MA,MB)        MB = SINH(MA)

  FMSP2M(X,MA)         MA = X   Convert from single precision to FM.

  FMSQR(MA,MB)         MB = MA*MA   Faster than FMMPY.

  FMSQRT(MA,MB)        MB = SQRT(MA)

  FMST2M(STRING,MA)    MA = STRING
                            Convert from character string to FM.
                            Often more convenient than FMINP, which
                            converts an array of CHARACTER*1 values.
                            Example:   CALL FMST2M('123.4',MA).

  FMSUB(MA,MB,MC)      MC = MA - MB

  FMTAN(MA,MB)         MB = TAN(MA)

  FMTANH(MA,MB)        MB = TANH(MA)

  FMULP(MA,MB)         MB = One Unit in the Last Place of MA.

  FMWRIT(KWRITE,MA)         Write MA on unit KWRITE.
                            Multi-line numbers will have '&' as the
                            last nonblank character on all but the last
                            line.  These numbers can then be read
                            easily using FMREAD.



------------------------------------------------------------------------
-----------------   Routines for Integer Operations   ------------------



  These are the integer routines that are designed to be called by
  the user.  All are subroutines except logical function IMCOMP.
  MA, MB, MC refer to IM format numbers.  In each case the version
  of the routine to handle packed IM numbers has the same name,
  with 'IM' replaced by 'IP'.

  IMABS(MA,MB)         MB = ABS(MA)

  IMADD(MA,MB,MC)      MC = MA + MB

  IMBIG(MA)            MA = Biggest IM number less than overflow.

  IMCOMP(MA,LREL,MB)        Logical comparison of MA and MB.
                            LREL is a CHARACTER*2 value identifying
                            which comparison is made.
                            Example:  IF (IMCOMP(MA,'GE',MB)) ...

  IMDIM(MA,MB,MC)      MC = DIM(MA,MB)

  IMDIV(MA,MB,MC)      MC = int(MA/MB)
                            Use IMDIVR if the remainder is also needed.

  IMDIVI(MA,IVAL,MB)   MB = int(MA/IVAL)
                            IVAL is a one word integer.  Use IMDVIR
                            to get the remainder also.

  IMDIVR(MA,MB,MC,MD)  MC = int(MA/MB),   MD = MA mod MB
                            When both the quotient and remainder are
                            needed, this routine is twice as fast as
                            calling both IMDIV and IMMOD.

  IMDVIR(MA,IVAL,MB,IREM)   MB = int(MA/IVAL),   IREM = MA mod IVAL
                            IVAL and IREM are one word integers.

  IMEQ(MA,MB)          MB = MA

  IMFM2I(MAFM,MB)      MB = MAFM  Convert from real (FM) format
                                  to integer (IM) format.

  IMFORM(FORM,MA,STRING)    MA is converted to a character string
                               using format FORM and returned in
                               STRING.  FORM can represent I, F,
                               E, or 1PE formats.  Example:
                               CALL IMFORM('I70',MA,STRING)

  IMFPRT(FORM,MA)           Print MA on unit KW using FORM format.

  IMGCD(MA,MB,MC)      MC = greatest common divisor of MA and MB.

  IMI2FM(MA,MBFM)    MBFM = MA  Convert from integer (IM) format
                                to real (FM) format.

  IMI2M(IVAL,MA)       MA = IVAL   Convert from one word integer
                                   to IM.

  IMINP(LINE,MA,LA,LB) MA = LINE   Input conversion.
                                   Convert LINE(LA) through LINE(LB)
                                   from characters to IM.

  IMM2DP(MA,X)         X  = MA     Convert from IM to double precision.

  IMM2I(MA,IVAL)       IVAL = MA   Convert from IM to one word integer.

  IMMAX(MA,MB,MC)      MC = MAX(MA,MB)

  IMMIN(MA,MB,MC)      MC = MIN(MA,MB)

  IMMOD(MA,MB,MC)      MC = MA mod MB

  IMMPY(MA,MB,MC)      MC = MA*MB

  IMMPYI(MA,IVAL,MB)   MB = MA*IVAL    Multiply by a one word integer.

  IMMPYM(MA,MB,MC,MD)  MD = MA*MB mod MC
                            Slightly faster than calling IMMPY and
                            IMMOD separately, and it works for cases
                            where IMMPY would return OVERFLOW.

  IMOUT(MA,LINE,LB)    LINE = MA   Convert from IM to character.
                                   LINE is a character array of
                                   length LB.

  IMPMOD(MA,MB,MC,MD)       MD = MA**MB mod MC

  IMPRNT(MA)                Print MA on unit KW.

  IMPWR(MA,MB,MC)      MC = MA**MB

  IMREAD(KREAD,MA)     MA   is returned after reading one (possibly
                            multi-line) IM number on unit KREAD.  This
                            routine reads numbers written by IMWRIT.

  IMSIGN(MA,MB,MC)     MC = SIGN(MA,MB)   Sign transfer.

  IMSQR(MA,MB)         MB = MA*MA   Faster than IMMPY.

  IMST2M(STRING,MA)    MA = STRING
                            Convert from character string to IM.
                            Often more convenient than IMINP, which
                            converts an array of CHARACTER*1 values.
                            Example:   CALL IMST2M('12345678901',MA).

  IMSUB(MA,MB,MC)      MC = MA - MB

  IMWRIT(KWRITE,MA)         Write MA on unit KWRITE.
                            Multi-line numbers will have '&' as the
                            last nonblank character on all but the last
                            line.  These numbers can then be read
                            easily using IMREAD.

  Many of the IM routines call FM routines, but none of the FM
  routines call IM routines, so the IM routines can be omitted
  if none are called explicitly from a program.



------------------------------------------------------------------------
----------   Routines for Complex Floating-Point Operations   ----------



  These are the routines in ZMLIB that are designed to be called by
  the user.  All are subroutines, and in each case the version of the
  routine to handle packed ZM numbers has the same name, with 'ZM'
  replaced by 'ZP'.

  MA, MB, MC refer to ZM format complex numbers.
  MAFM, MBFM, MCFM refer to FM format real numbers.
  INTEG is a Fortran INTEGER variable.
  ZVAL is a Fortran COMPLEX variable.

  In each case it is permissible to use the same array more than
  once in the calling sequence.  The statement
  MA = MA*MA   may be written  CALL ZMMPY(MA,MA,MA).

  ZMABS(MA,MBFM)       MBFM = ABS(MA)    Result is real.

  ZMACOS(MA,MB)        MB = ACOS(MA)

  ZMADD(MA,MB,MC)      MC = MA + MB

  ZMADDI(MA,INTEG)     MA = MA + INTEG  Increment an ZM number by a one
                                        word integer.  Note this call
                                        does not have an "MB" result
                                        like ZMDIVI and ZMMPYI.

  ZMARG(MA,MBFM)       MBFM = Argument(MA)    Result is real.

  ZMASIN(MA,MB)        MB = ASIN(MA)

  ZMATAN(MA,MB)        MB = ATAN(MA)

  ZMCHSH(MA,MB,MC)     MB = COSH(MA),  MC = SINH(MA).
                            Faster than 2 calls.

  ZMCMPX(MAFM,MBFM,MC) MC = CMPLX(MAFM,MBFM)

  ZMCONJ(MA,MB)        MB = CONJG(MA)

  ZMCOS(MA,MB)         MB = COS(MA)

  ZMCOSH(MA,MB)        MB = COSH(MA)

  ZMCSSN(MA,MB,MC)     MB = COS(MA),  MC = SIN(MA).
                            Faster than 2 calls.

  ZMDIV(MA,MB,MC)      MC = MA / MB

  ZMDIVI(MA,INTEG,MB)  MB = MA / INTEG

  ZMEQ(MA,MB)          MB = MA

  ZMEQU(MA,MB,NDA,NDB) MB = MA    Version for changing precision.
                                  (NDA and NDB are as in FMEQU)

  ZMEXP(MA,MB)         MB = EXP(MA)

  ZMFORM(FORM1,FORM2,MA,STRING)   STRING = MA
                       MA is converted to a character string using
                       format FORM1 for the real part and FORM2 for
                       the imaginary part.  The  result is returned
                       in STRING.  FORM1 and FORM2 can represent I,
                       F, E, or 1PE formats.  Example:
                          CALL ZMFORM('F20.10','F15.10',MA,STRING)

  ZMFPRT(FORM1,FORM2,MA)    Print MA on unit KW using
                            formats FORM1 and FORM2.

  ZMI2M(INTEG,MA)           MA = CMPLX(INTEG,0)

  ZM2I2M(INTEG1,INTEG2,MA)  MA = CMPLX(INTEG1,INTEG2)

  ZMIMAG(MA,MBFM)           MBFM = IMAG(MA)    Imaginary part.

  ZMINP(LINE,MA,LA,LB)      MA = LINE   Input conversion.
                                 Convert LINE(LA) through LINE(LB)
                                 from characters to ZM.  LINE is a
                                 character array of length at least LB.

  ZMINT(MA,MB)         MB = INT(MA)        Integer part of both Real
                                           and Imaginary parts of MA.

  ZMIPWR(MA,INTEG,MB)  MB = MA ** INTEG    Integer power function.

  ZMLG10(MA,MB)        MB = LOG10(MA)

  ZMLN(MA,MB)          MB = LOG(MA)

  ZMM2I(MA,INTEG)      INTEG = INT(REAL(MA))

  ZMM2Z(MA,ZVAL)       ZVAL = MA

  ZMMPY(MA,MB,MC)      MC = MA * MB

  ZMMPYI(MA,INTEG,MB)  MB = MA * INTEG

  ZMNINT(MA,MB)        MB = NINT(MA)   Nearest integer of both Real
                                       and Imaginary.

  ZMOUT(MA,LINE,LB,LAST1,LAST2)        LINE = MA
                       Convert from FM to character.
                       LINE  is the returned character array.
                       LB    is the dimensioned size of LINE.
                       LAST1 is returned as the position in LINE of
                             the last character of REAL(MA).
                       LAST2 is returned as the position in LINE
                             of the last character of AIMAG(MA).

  ZMPRNT(MA)           Print MA on unit KW using current format.

  ZMPWR(MA,MB,MC)      MC = MA ** MB

  ZMREAD(KREAD,MA)     MA   is returned after reading one (possibly
                            multi-line) ZM number on unit KREAD.  This
                            routine reads numbers written by ZMWRIT.

  ZMREAL(MA,MBFM)      MBFM = REAL(MA)    Real part.

  ZMRPWR(MA,IVAL,JVAL,MB)     MB = MA ** (IVAL/JVAL)

  ZMSET(NPREC)         Initialize ZM package.  Set precision to the
                       equivalent of at least NPREC base 10 digits.

  ZMSIN(MA,MB)         MB = SIN(MA)

  ZMSINH(MA,MB)        MB = SINH(MA)

  ZMSQR(MA,MB)         MB = MA*MA    Faster than ZMMPY.

  ZMSQRT(MA,MB)        MB = SQRT(MA)

  ZMST2M(STRING,MA)    MA = STRING
                            Convert from character string to ZM.
                            Often more convenient than ZMINP, which
                            converts an array of CHARACTER*1 values.
                            Example: CALL ZMST2M('123.4+5.67i',MA).

  ZMSUB(MA,MB,MC)      MC = MA - MB

  ZMTAN(MA,MB)         MB = TAN(MA)

  ZMTANH(MA,MB)        MB = TANH(MA)

  ZMWRIT(KWRITE,MA)    Write MA on unit KWRITE.  Multi-line numbers
                       are formatted for automatic reading with ZMREAD.

  ZMZ2M(ZVAL,MA)       MA = ZVAL



------------------------------------------------------------------------
--------------------------   fmlib.f90 Notes   ---------------------------



  The FM routines in this package perform floating-point
  multiple-precision arithmetic, and the IM routines perform
  integer multiple-precision arithmetic.



  1. INITIALIZING THE PACKAGE

  Before calling any routine in the package, several variables in
  the common blocks /FMUSER/, /FM/, /FMBUFF/, and /FMSAVE/ must be
  initialized.  These four common blocks contain information that
  is saved between calls, so they should be declared in the main
  program.

  Subroutine FMSET initializes these variables to default values and
  defines all machine-dependent values in the package.  After calling
  FMSET once at the start of a program, the user may sometimes want
  to reset some of the variables in these common blocks.  These
  variables are described below.



  2. REPRESENTATION OF FM NUMBERS

  MBASE is the base in which the arithmetic is done.  MBASE must be
        bigger than one, and less than or equal to the square root of
        the largest representable integer.  For best efficiency MBASE
        should be large, but no more than about 1/4 of the square root
        of the largest representable integer.  Input and output
        conversions are much faster when MBASE is a power of ten.

  NDIG  is the number of base MBASE digits that are carried in the
        multiple precision numbers.  NDIG must be at least two.  The
        upper limit for NDIG is defined in the PARAMETER statement at
        the top of each routine and is restricted only by the amount
        of memory available.

  Sometimes it is useful to dynamically vary NDIG during the program.
  Use FMEQU to round numbers to lower precision or zero-pad them to
  higher precision when changing NDIG.

  It is rare to need to change MBASE during a program.  Use FMCONS to
  reset some saved constants that depend on MBASE.  FMCONS should be
  called immediately after changing MBASE.

  There are two representations for a floating multiple precision
  number.  The unpacked representation used by the routines while
  doing the computations is base MBASE and is stored in NDIG+2 words.
  A packed representation is available to store the numbers in the
  user's program in compressed form.  In this format, the NDIG
  (base MBASE) digits of the mantissa are packed two per word to
  conserve storage.  Thus the external, packed form of a number
  requires (NDIG+1)/2+2 words.

  This version uses double precision arrays to hold the numbers.
  Version 1.0 of FM used integer arrays, which are faster on some
  machines.  The package can easily be changed to use integer
  arrays -- see section 11 on EFFICIENCY below.

  The unpacked format of a floating multiple precision number is as
  follows.  A number MA is kept in an array with MA(1) containing
  the exponent and MA(2) through MA(NDIG+1) containing one digit of
  the mantissa, expressed in base MBASE.  The array is dimensioned
  to start at MA(0), with the approximate number of bits of precision
  stored in MA(0).  This precision value is intended to be used by FM
  functions that need to monitor cancellation error in addition and
  subtraction. The cancellation monitor code is usually disabled for
  user calls, and FM functions only check for cancellation when they
  must.  Tracking cancellation causes most routines to run slower,
  with addition and subtraction being affected the most.

  The exponent is a power of MBASE and the implied radix point is
  immediately before the first digit of the mantissa.  Every nonzero
  number is normalized so that the second array element (the first
  digit of the mantissa) is nonzero.

  In both representations the sign of the number is carried on the
  second array element only.  Elements 3,4,... are always nonnegative.
  The exponent is a signed integer and may be as large in magnitude as
  MXEXP (defined in FMSET).

  For MBASE = 10,000 and NDIG = 4, the number -pi would have these
  representations:
                   Word 1         2         3         4         5

         Unpacked:      1        -3      1415      9265      3590
         Packed:        1    -31415  92653590

  Word 0 would be 42 in both formats, indicating that the mantissa
  has about 42 bits of precision.

  Because of normalization in a large base, the equivalent number
  of base 10 significant digits for an FM number may be as small as
  LOG10(MBASE)*(NDIG-1) + 1.

  The integer routines use the FMLIB format to represent numbers,
  without the number of digits (NDIG) being fixed.  Integers in IM
  format are essentially variable precision, using the minimum number
  of words to represent each value.

  For programs using both FM and IM numbers, FM routines should not
  be called with IM numbers, and IM routines should not be called
  with FM numbers, since the implied value of NDIG used for an IM
  number may not match the explicit NDIG expected by an FM routine.
  Use the conversion routines IMFM2I and IMI2FM to change between
  the FM and IM formats.



  3. INPUT/OUTPUT ROUTINES

  All versions of the input routines perform free-format conversion
  from characters to FM numbers.

  a. Conversion to or from a character array

     FMINP converts from a character*1 array to an FM number.

     FMOUT converts an FM number to base 10 and formats it for output
           as an array of type character*1.  The output is left
           justified in the array, and the format is defined by two
           variables in common, so that a separate format definition
           does not have to be provided for each output call.

     The user sets JFORM1 and JFORM2 to determine the output format.

     JFORM1 = 0     E   format       ( .314159M+6 )
            = 1     1PE format       ( 3.14159M+5 )
            = 2     F   format       ( 314159.000 )

     JFORM2 is the number of significant digits to display (if
            JFORM1 = 0 or 1).  If JFORM2.EQ.0 then a default number
            of digits is chosen.  The default is roughly the full
            precision of the number.
     JFORM2 is the number of digits after the decimal point (if
            JFORM1 = 2).  See the FMOUT documentation for more details.

  b. Conversion to or from a character string

     FMST2M converts from a character string to an FM number.

     FMFORM converts an FM number to a character string according to
            a format provided in each call.  The format description
            is more like that of a Fortran FORMAT statement, and
            integer or fixed-point output is right justified.

  c. Direct read or write

     FMPRNT uses FMOUT to print one FM number.

     FMFPRT uses FMFORM to print one FM number.

     FMWRIT writes FM numbers for later input using FMREAD.

     FMREAD reads FM numbers written by FMWRIT.

  The values given to JFORM1 and JFORM2 can be used to define a
  default output format when FMOUT or FMPRNT are called.  The
  explicit format used in a call to FMFORM or FMFPRT overrides
  the settings of JFORM1 and JFORM2.

  KW is the unit number to be used for standard output from
     the package, including error and warning messages, and
     trace output.

  For multiple precision integers, the corresponding routines
  IMINP, IMOUT, IMST2M, IMFORM, IMPRNT, IMFPRT, IMWRIT, and
  IMREAD provide similar input and output conversions.  For
  output of IM numbers, JFORM1 and JFORM2 are ignored and
  integer format (JFORM1=2, JFORM2=0) is used.

  For further description of these routines, see sections
  9 and 10 below.



  4. ARITHMETIC TRACING

  NTRACE and LVLTRC control trace printout from the package.

  NTRACE =  0   No printout except warnings and errors.
         =  1   The result of each call to one of the routines
                   is printed in base 10, using FMOUT.
         = -1   The result of each call to one of the routines
                   is printed in internal base MBASE format.
         =  2   The input arguments and result of each call to one
                   of the routines is printed in base 10, using FMOUT.
         = -2   The input arguments and result of each call to one
                   of the routines is printed in base MBASE format.

  LVLTRC defines the call level to which the trace is done.  LVLTRC = 1
         means only FM routines called directly by the user are traced,
         LVLTRC = 2 also prints traces for FM routines called by other
         FM routines called directly by the user, etc.

  In the above description, internal MBASE format means the number is
  printed as it appears in the array --- an exponent followed by NDIG
  base MBASE digits.



  5. ERROR CONDITIONS

  KFLAG is a condition parameter returned by the package after each
        call to one of the routines.  Negative values indicate
        conditions for which a warning message will be printed
        unless KWARN = 0.  Positive values indicate conditions
        that may be of interest but are not errors.
        No warning message is printed if KFLAG is nonnegative.

    KFLAG =  0     Normal operation.

          =  1     One of the operands in FMADD or FMSUB was
                       insignificant with respect to the other, so
                       that the result was equal to the argument of
                       larger magnitude.
          =  2     In converting an FM number to a one word integer
                       in FMM2I, the FM number was not exactly an
                       integer.  The next integer toward zero was
                       returned.

          = -1     NDIG was less than 2 or more than NDIGMX.
          = -2     MBASE was less than 2 or more than MXBASE.
          = -3     An exponent was out of range.
          = -4     Invalid input argument(s) to an FM routine.
                        UNKNOWN was returned.
          = -5     + or - OVERFLOW was generated as a result from an
                        FM routine.
          = -6     + or - UNDERFLOW was generated as a result from an
                        FM routine.
          = -7     The input string (array) to FMINP was not legal.
          = -8     The character array was not large enough in an
                   input or output routine.
          = -9     Precision could not be raised enough to provide all
                        requested guard digits.  Increasing NDIGMX in
                        all the PARAMETER statements may fix this.
                        UNKNOWN was returned.
          = -10    An FM input argument was too small in magnitude to
                        convert to the machine's single or double
                        precision in FMM2SP or FMM2DP.  Check that the
                        definitions of SPMAX and DPMAX in FMSET are
                        correct for the current machine.
                        Zero was returned.

  When a negative KFLAG condition is encountered, the value of KWARN
  determines the action to be taken.

  KWARN = 0     Execution continues and no message is printed.
        = 1     A warning message is printed and execution continues.
        = 2     A warning message is printed and execution stops.

  The default setting is KWARN = 1.

  When an overflow or underflow is generated for an operation in which
  an input argument was already an overflow or underflow, no additional
  message is printed.  When an unknown result is generated and an input
  argument was already unknown, no additional message is printed.  In
  these cases the negative KFLAG value is still returned.

  IM routines handle exceptions like OVERFLOW or UNKNOWN in the same
  way as FM routines.  When using IMMPY, the product of two large
  positive integers will return +OVERFLOW.  The routine IMMPYM can
  be used to obtain a modular result without overflow.  The largest
  representable IM integer is MBASE**NDIGMX - 1.  For example, if
  MBASE is 10**7 and NDIGMX is set to 256, integers less than 10**1792
  can be used.



  6. OTHER PARAMETERS

  KRAD = 0     All angles in the trigonometric functions and
                  inverse functions are measured in degrees.
       = 1     All angles are measured in radians. (Default)


  KROUND = 0   All final results are chopped (rounded toward
                  zero).  Intermediate results are rounded.
         = 1   All results are rounded to the nearest FM
                  number, or to the value with an even last
                  digit if the result is halfway between two
                  FM numbers. (Default)

  KSWIDE defines the maximum screen width to be used for
         all unit KW output.  Default is 80.

  KESWCH controls the action taken in FMINP and other input routines
         for strings like 'E7' that have no digits before the exponent
         field.  Default is for 'E7' to translate like '1.0E+7'.

  CMCHAR defines the exponent letter to be used for FM variable
         output.  Default is 'M', as in 1.2345M+678.

  KDEBUG = 0   Error checking is not done for valid input arguments
               and parameters like NDIG and MBASE upon entry to
               each routine. (Default)
         = 1   Some error checking is done.  (Slower speed)

  See FMSET for additional description of these and other variables
  defining various FM conditions.



  7. ARRAY DIMENSIONS

  The dimensions of the arrays in the FM package are defined using
  a PARAMETER statement at the top of each routine.  The size of
  these arrays depends on the values of parameters NDIGMX and NBITS.
  NDIGMX is the maximum value the user may set for NDIG.
  NBITS  is the number of bits used to represent integers for a
         given machine.  See the EFFICIENCY discussion below.

  The standard version of FMLIB sets NDIGMX = 256, so on a 32-bit
  machine using MBASE = 10**7 the maximum precision is about
  7*255+1 = 1786 significant digits.  To change dimensions so that
  10,000 significant digit calculation can be done, NDIGMX needs to
  be at least  10**4/7 + 5 = 1434.  This allows for a few user guard
  digits to be defined when the package is initialized using
  CALL FMSET(10000).  Changing 'NDIGMX = 256' to 'NDIGMX = 1434'
  everywhere in the package and the user's calling program will
  define all the new array sizes.

  If NDIG much greater than 256 is to be used and elementary functions
  will be needed, they will be faster if array MJSUMS is larger. The
  parameter defining the size of MJSUMS is set in the standard version
  by LJSUMS = 8*(LUNPCK+2).  The 8 means that up to eight concurrent
  sums can be used by the elementary functions.  The approximate number
  needed for best speed is given by the formula
      0.051*Log(MBASE)*NDIG**(1/3) + 1.85
  For example, with MBASE=10**7 and NDIG=1434 this gives 11.  Changing
  'LJSUMS = 8*(LUNPCK+2)' to 'LJSUMS =11*(LUNPCK+2)' everywhere in the
  package and the user's calling program will give slightly better
  speed.

  FM numbers in packed format have dimension 0:LPACK, and those
  in unpacked format have dimension 0:LUNPCK.



  8. PORTABILITY

  In FMSET there is some machine-dependent code that attempts to
  approximate the largest representable integer value.  The current
  code works on all machines tested, but if an FM run fails, check
  the MAXINT and INTMAX loops in FMSET.  Values for SPMAX and DPMAX
  are also defined in FMSET that should be set to values near overflow
  for single precision and double precision.  Setting KDEBUG = 1 may
  also identify some errors if a run fails.

  Some compilers object to a function like FMCOMP with side effects
  such as changing KFLAG or other common variables.  Blocks of code
  in FMCOMP and IMCOMP that modify common are identified so they may
  be removed or commented out to produce a function without side
  effects.  This disables trace printing in FMCOMP and IMCOMP, and
  error codes are not returned in KFLAG.  See FMCOMP and IMCOMP for
  further details.

  All variables are explicitly declared in each routine.  There is
  a commented IMPLICIT NONE statement in each routine that can be
  enabled to get more compiler diagnostic information in some testing
  or debugging situations.


  9. NEW FOR VERSION 1.1

  Version 1.0 used integer arrays and integer arithmetic internally
  to perform the multiple precision operations.  Version 1.1 uses
  double precision arithmetic and arrays internally.  This is usually
  faster at higher precisions, and on many machines it is also faster
  at lower precisions.  Version 1.1 is written so that the arithmetic
  used can easily be changed from double precision to integer, or any
  other available arithmetic type.  This permits the user to make the
  best use of a given machine's arithmetic hardware.
  See the EFFICIENCY discussion below.

  Several routines have undergone minor modification, but only a few
  changes should affect programs that used FM 1.0.  Many of the
  routines are faster in version 1.1, because code has been added to
  take advantage of special cases for individual functions instead of
  using general formulas that are more compact.  For example, there
  are separate routines using series for SINH and COSH instead of
  just calling EXP.

  FMEQU was the only routine that required the user to give the value
        of the current precision.  This was to allow automatic
        rounding or zero-padding when changing precision.  Since few
        user calls change precision, a new routine has been added for
        this case.
        FMEQ now handles this case and has a simple argument list that
             does not include the value of NDIG.
        FMEQU is used for changing precision.
        See the list of FM routines above for details.

  All variable names beginning with M in the package are now declared
  as double precision, so FM common blocks in the user's program need
  D.P. declarations, and FM variables (arrays) used in the calling
  program need to be D.P.

  /FMUSER/ is a common block holding parameters that define the
           arithmetic to be used and other user options.  Several
           new variables have been added, including screen width to
           be used for output.  See above for further description.

  /FMSAVE/ is a common block for saving constants to avoid
           re-computing them.  Several new variables have been added.

  /FMBUFF/ is a common block containing a character array used to
           format FM numbers for output.  Two new items have been
           added.

  New routines:

  All the IM routines are new for version 1.1.

  FMADDI increments an FM number by a small integer.
         It runs in O(1) time, on the average.

  FMCHSH returns both SINH(MA) and COSH(MA).
         When both are needed, this is almost twice as fast
         as making separate calls to FMCOSH and FMSINH.

  FMCSSN returns both SIN(MA) and COS(MA).
         When both are needed, this is almost twice as fast
         as making separate calls to FMCOS and FMSIN.

  FMFORM uses a format string to convert an FM number to a
         character string.

  FMFPRT prints an FM number using a format string.

  FMREAD reads an FM number written using FMWRIT.

  FMRPWR computes an FM number raised to a rational power.  For cube
         roots and similar rational powers it is usually much faster
         than FMPWR.

  FMSQR  squares an FM number.  It is faster than using FMMPY.

  FMST2M converts character strings to FM format.  Since FMINP converts
         character arrays, this routine can be more convenient for
         easily defining an FM number.
         For example, CALL FMST2M('123.4',MA).

  FMWRIT writes an FM number using a format for multi-line numbers
         with '&' at the end of all but the last line of a multi-line
         number.  This allows automatic reading of FM numbers without
         needing to know the base, precision or format under which they
         were written.

  One extra word has been added to the dimensions of all FM numbers.
  Word zero in each array contains a value used to monitor cancellation
  error arising from addition or subtraction.  This value approximates
  the number of bits of precision for an FM value.  It allows higher
  level FM functions to detect cases where too much cancellation has
  occurred.  KACCSW is a switch variable in COMMON /FM/ used internally
  to enable cancellation error monitoring.


  10. EFFICIENCY

  To take advantage of hardware architecture on different machines, the
  package has been designed so that the arithmetic used to perform the
  multiple precision operations can easily be changed.  All variables
  that must be changed to get a different arithmetic have names
  beginning with 'M' and are declared using REAL (KIND(0.0D0)) :: m....

  For example, to change the package to use integer arithmetic
  internally, make these two changes everywhere in the package:
  change  'REAL (KIND(0.0D0)) :: m'  to  'INTEGER m',
  change  'DINT('  to  'INT('.
  On some systems, changing  'DINT('  to  '('  may give better speed.

  When changing to a different type of arithmetic, all FM common blocks
  and arrays in the user's program must be changed to agree.  In a few
  places in FM, where a DINT function is not supposed to be changed, it
  is spelled 'DINT (' so the global change will not find it.

  This version restricts the base used to be also representable in
  integer variables, so using precision above double usually does not
  save much time unless integers can also be declared at a higher
  precision.  Using IEEE Extended would allow a base of around 10**9
  to be chosen, but the delayed digit-normalization method used for
  multiplication and division means that a slightly smaller base like
  10**8 would usually run faster.  This would usually not be much
  faster than using 10**7 with double precision.

  The value of NBITS defined as a parameter in most FM routines
  refers to the number of bits used to represent integers in an
  M-variable word.  Typical values for NBITS are:  24 for IEEE single
  precision, 32 for integer, 53 for IEEE double precision.  NBITS
  controls only array size, so setting it too high is ok, but then
  the program will use more memory than necessary.

  For cases where special compiler directives or minor re-writing
  of the code may improve speed, several of the most important
  loops in FM are identified by comments containing the string
  '(Inner Loop)'.



------------------------------------------------------------------------
--------------------------   zmlib.f90 Notes   ---------------------------




  The ZM routines perform complex floating-point multiple-precision
  arithmetic.

  These routines use a Fortran 90 version of the FMLIB package (version
  1.1) for real floating-point multiple-precision arithmetic.  FMLIB is
  Algorithm 693, ACM Transactions on Mathematical Software, Vol. 17,
  No. 2, June 1991, pages 273-283.

  This package and FMLIB 1.1 use double precision arithmetic and arrays
  internally.  This is usually faster at higher precision, and on many
  machines it is also faster at lower precision.  Both packages are
  written so that the arithmetic used can easily be changed from double
  precision to integer, or another available arithmetic type.  See the
  EFFICIENCY discussion in the fmlib.f90 Notes for details.



  1. INITIALIZING THE PACKAGE

  Before calling any routine in the package, several variables in the
  common blocks /FMUSER/, /FM/, /FMSAVE/, /FMBUFF/, and /ZMUSER/ must
  be initialized.  These common blocks contain information that is
  saved between calls, so they should be declared in the main program.

  Subroutine ZMSET initializes these variables to default values and
  defines all machine-dependent values in the package.  After calling
  ZMSET once at the start of a program, the user may sometimes want to
  reset some of the variables in common blocks /FMUSER/ or /ZMUSER/.


  2.  REPRESENTATION OF ZM NUMBERS

  The format for complex FM numbers (called ZM numbers below) is very
  similar to that for real FM numbers in FMLIB.  Each ZM array holds
  two FM numbers to represent the real and imaginary parts of a complex
  number.  Each ZM array is twice as long as a corresponding FM array,
  with the imaginary part starting at the midpoint of the array.  As
  with FM, there are packed and unpacked formats for the numbers.


  3. INPUT/OUTPUT ROUTINES

  All versions of the input routines perform free-format conversion
  from characters to ZM numbers.

  a. Conversion to or from a character array

     ZMINP converts from a character*1 array to an ZM number.

     ZMOUT converts an ZM number to base 10 and formats it for output
           as an array of type character*1.  The output is left
           justified in the array, and the format is defined by
           variables in common, so that a separate format definition
           does not have to be provided for each output call.

     For the output format of ZM numbers, JFORM1 and JFORM2 determine
     the format for the individual parts of a complex number as
     described in the FMLIB documentation.

     JFORMZ (in /ZMUSER/) determines the combined output format of the
     real and imaginary parts.

     JFORMZ = 1  normal setting :       1.23 - 4.56 i
            = 2  use capital I  :       1.23 - 4.56 I
            = 3  parenthesis format   ( 1.23 , -4.56 )

     JPRNTZ (in /ZMUSER/) controls whether to print real
     and imaginary parts on one line whenever possible.

     JPRNTZ = 1  print both parts as a single string :
                     1.23456789M+321 - 9.87654321M-123 i
            = 2  print on separate lines without the 'i' :
                     1.23456789M+321
                    -9.87654321M-123

  b. Conversion to or from a character string

     ZMST2M converts from a character string to an ZM number.

     ZMFORM converts an ZM number to a character string according to
            a format provided in each call.  The format descriptions
            are more like that of a Fortran FORMAT statement, and
            integer or fixed-point output is right justified.

  c. Direct read or write

     ZMPRNT uses ZMOUT to print one ZM number.

     ZMFPRT uses ZMFORM to print one ZM number.

     ZMWRIT writes ZM numbers for later input using ZMREAD.

     ZMREAD reads ZM numbers written by ZMWRIT.

  For further description of these routines, see the list of ZM
  routines above.


  4. ARRAY DIMENSIONS

  The parameters LPACKZ and LUNPKZ define the size of the packed and
  unpacked ZM arrays.  The real part starts at the beginning of the
  array, and the imaginary part starts at word KPTIMP for packed format
  or at word KPTIMU for unpacked format.


===========================================================================
===========================================================================
