[home] [publications] [download] [projects]

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!