Converting a working code from double-precision to

2020-07-18 05:49发布

问题:

I have a big, old, FORTRAN 77 code that has worked for many, many years with no problems. Double-precision is not enough anymore, so to convert to quadruple-precision I have:

  1. Replaced all occurrences of REAL8 to REAL16
  2. Replaced all functions like DCOS() into functions like COS()
  3. Replaced all built-in numbers like 0.d0 to 0.q0 , and 1D+01 to 1Q+01

The program compiles with no errors or warnings with the gcc-4.6 compiler on

  1. operating system: openSUSE 11.3 x86_64 (a 64-bit operating system)
  2. hardware: Intel Xeon E5-2650 (Sandy Bridge)

My LD_LIBRARY_PATH variable is set to the 64-bit library folder: /gcc-4.6/lib64

The program reads an input file that has numbers in it. Those numbers used to be of the form 1.234D+02 (for the double-precision version of the code, which works). I have changed them so now that number is 1.234Q+02 , however I get the runtime error:

Bad real number in item 1 of list input

Indicating that the subroutine that reads in the data from the input file (called read.f) does not find the first number in the inputfile, to be compatible with what it expected.

Strangely, the quadruple-precision version of the code does not complain when the input file contains numbers like 1.234D+02 or 123.4 (which, based on the output seems to automatically be converted to the form 1.234D+02 rather than Q+02), it just does not like the Q+02 , so it seems that gcc-4.6 does not allow quadruple-precision numbers to be read in from input files in scientific notation !

Has anyone ever been able to read from an input file a quadruple-precision number in scientific notation (ie, like 1234Q+02) in FORTRAN with a gcc compiler, and if so how did you get it to work ? (or did you need a different compiler/operating system/hardware to get it to work ?)

回答1:

Almost all of this is already in comments by @IanH and @Vladimi.

I suggest mixing in a little Fortran 90 into your FORTRAN 77 code.

Write all of your numbers with "E". Change your other program to write the data this way. Don't bother with "D" and don't try to use the infrequently supported "Q". (Using "Q" in constants in source code is an extension of gfortran -- see 6.1.8 in manual.)

Since you want the same source code to support two precisions, at the top of the program, have:

use ISO_FORTRAN_ENV
WP = real128

or

use ISO_FORTRAN_ENV
WP = real64

as the variation that changes whether your code is using double or quadruple precision. This is using the ISO Fortran Environment to select the types by their number of bits. (use needs to between program and implicit none; the assignment statement after implicit none.)

Then declare your real variables via:

real (WP) :: MyVar

In source code, write real constants as 1.23456789012345E+12_WP. The _type is the Fortran 90 way of specifying the type of a constant. This way you can go back and forth between double and quadruple precision by only changing the single line defining WP

WP == Working Precision.

Just use "E" in input files. Fortran will read according to the type of the variable.

Why not write a tiny test program to try it out?