Omni Fortran Compiler, omf77 Multiple Precision Real Support
What's "multiple precsion real" and GNU MP library?
omf77 (since Omni 1.3) supports multiple precision floating point
number as a generic type, by using GNU MP (GNU Multiple Precision) library.
Platforms and Software requirements
Developping and tested on:
- Linux 2.2.14/Alpha with gcc and Compaq C compiler.
- Linux 2.2.16/i386 with gcc
- Solaris 2.6/SPARC with gcc and SUNWspro cc
You have to use GNU MP version 3 or later for proper compilation. Note
that many Linux distributions contain version 2 base GNU MP library. I
strongly recommand you to download the latest one, GMP3.1.1 from GNU MP home page .
Installation
To enable multiple precision floating point number support, run
"configure" command with '--enable-mreal' option. If the GMP is not
installed in default directory (/usr on Linux, /usr/local on others), you
also have to specify the directory with '--with-gmpLibDir=DIR' and
'--with-gmpIncDir=DIR' options. Like:
configure --enable-mreal --with-gmpIncDir=/somewhere/gmp.h_is --with-gmpLibDir=/somewhere/libgmp.a_is ...
You can also specify a default precision of the multiple precision
floating point type using '--with-precision=BITS' option. If you don't
specify this, 128 is used as the default precision. For more detail of
configuration, see Installation Notes.
How to use the multiple precision real
- Write source codes using 'MULTIPLE PRECISION' and/or 'REAL*16'
'MULTIPLE PRECISION' and 'REAL*16' are the keywords for the multiple
precision real type declaration. Note that THEY ARE IDENTICAL and
'REAL*16' DOESN'T MEANS QUAD-PRECISION BUT MULTIPLE PRECISION. Thus,
you can use muptiple precision real variable like:
- MULTIPLE PRECISION x, y
- REAL*16 z
-
- PARAMETER (x = 1.23Q-1, y = 0.5Q0)
-
- z = x / y
-
- WRITE(*, *) x, y, z
- END
With above, you may also notice that you can specify the precision of
constants with 'Q'. 'Q' is for quad-precison real. As mentioned, since 'REAL
*16' is identical to 'MULTIPLE PRECISION', constants specified with 'Q'
are treated as multiple precision real numbers.
Compile the source codes with '-m#' option
You can specify the precision of variables declared with 'MULTIPLE
PRECISION', 'REAL*16' and constants with 'Q' by using '-m#'
omf77 option. Like:
omf77 -m256 foo.F
This let the precision of multiple precision types in foo.F 256 bit,
octa-precision floating point numbers. Logically the maximum precision
is 2 ** 31 (in bits!), practically it depends on how many physical
memories your machine has as usual :)
If you don't specify the '-m#' option, a default value (128 if you
didn't specify the default precision with '--with-precision=BITS'
"configure" command option) is used.
Note that you CAN specify the precision ONLY WHEN the compilation time
of a program ONLY WITH '-m#' option, There is NO other ways.
Known problems and implementation specifications
- Currently, several math intrinsic functions:
sin, asin, sinh
cos, acos, cosh
tan, atan, atan2, tanh
log, log10
exp
are NOT implemented now. Only a power (REAL*16 ** INTEGER*{2|4|8}) is
available.
Since a storage size of 'REAL*16' is varied, people who is offten
writing legacy-styled codes that are initializing numeric variable
with strings by DATA statement might be confuesd. Here is what happens
if the 'REAL*16' variables are initialized with strings:
- If WHOLE elements of a 'REAL*16' array are initialized by
strings, the all strings are successive concatenated, stored from
the first element of the array and be NUL terminated.
- If partial of a 'REAL*16' array or a 'REAL*16' scalar variable is
initialized by a string, the string stored from the start address of
the element/variable storage area, and if the string is shorter than
the length of the storage area, remains are initialized with ASCII SPC
(0x20).
IMHO, if you are doing this, stop doing it immediately and move to
the modern world B)
Because of precision of 'REAL*16' is varied, you may want to know
how many columns needed for pretty-output of it. omf77
provides a 'precof()' intrinsic function to obtain the precision (in
bits) of a specified variable. Use like:
MULTIPLE PRECISION x
INTEGER digs
CHARACTER*30 fmtstr
DATA fmtstr/10H("x = ", F/
digs = INT(LOG10(2.0) * PRECOF(x)) + 10
WRITE(fmtstr(11:30), '(I5)') digs
WRITE(fmtstr(16:30), '(A1)') "."
WRITE(fmtstr(17:30), '(I5)') digs - 10
WRITE(fmtstr(22:30), '(A1)') ")"
C Compute value of x whatever way you want :)
WRITE(*, fmtstr) x
END
Since omf77 emit STATICALLY the size of storage needed
for keeping multiple precision floating point numbers, you CAN NOT
link object file compiled with DIFFERNT precision specified by '-m#'
option. This might cause some problems when creating libraries. If you
want to create libraries, you have to use same precision when compile
them, furthermore, you have to compile programs using the libraries
as same precision as the libraries were compiled.
Anyway because of above, omf77 can emit better
performance code than programs using C with GNU MP C language
interface. With GNU MP C language interface, you have to call
mpf_init() and mpf_clear() to allocate/destroy the storage to keep
values. The other hand omf77 DON'T call these. Instead, it
allocates the storage in a .bss or a stack, with statically computed
size needed for the precision specified with '-m#'.
Acknowledgement
Our achievement is fully based on GNU MP, the fastest and the most
portable multiple precision library ever build.
We thank the GNU MP developping team, Thank you for the GREAT JOB!