Discussion:
newbie question: underscore in fortran?
(too old to reply)
M. Serkan Apaydin
2003-09-10 18:44:51 UTC
Permalink
Hi,

I have a very basic question. I am trying to understand code written
in fortran, and since I am not a fortran programmer, I don't understand
what _q in a statement like:

FNrp=(FNrp1+FNrp2)/2._q

means. I checked a couple of tutorials and did some search with no success.

FNrp is defined as:

real(q) :: FNrp,FNrp1,FNrp2


Thanks,

serkan
Richard Maine
2003-09-10 19:17:32 UTC
Permalink
Post by M. Serkan Apaydin
FNrp=(FNrp1+FNrp2)/2._q
...
Post by M. Serkan Apaydin
real(q) :: FNrp,FNrp1,FNrp2
The q here is a kind parameter. There are multiple kinds of
reals, each of which has a different representation. Generally,
these are different precisions, although it is at least
theoretically allowed to have two different representations
with the same precision.

Q is just a named constant (parameter). Its value needs to be defined
somewhere else. Most likely it is defined in some module that this
code is using. Ideally it would be defined portably using the
selected_real_kind intrinsic. Alternatively, it might be hard-wired
to a compiler-specific value.

From the choice of name for the parameter, I might guess that this is
intended to be the kind parameter for quad precision real. In that
case, the 2._q is a quad precision real constant and the real(q)
statement declares the three names in it to be quad precision reals.
--
Richard Maine | Good judgment comes from experience;
email: my first.last at org.domain | experience comes from bad judgment.
org: nasa, domain: gov | -- Mark Twain
Steven G. Kargl
2003-09-10 19:09:47 UTC
Permalink
Post by M. Serkan Apaydin
Hi,
I have a very basic question. I am trying to understand code written
in fortran, and since I am not a fortran programmer, I don't understand
FNrp=(FNrp1+FNrp2)/2._q
means. I checked a couple of tutorials and did some search with no success.
real(q) :: FNrp,FNrp1,FNrp2
Someplace in your program, you should have a statement
of the form "q = kind(1.e0)" or "q = selected_real_kind(6,20)".
This sets the float point model for the numbers, e.g., single
precision or double precision or perhaps quad precision. The
suffix in 2._q tells the compiler you want the floating point
number 2. to _q precision.
--
Steve
http://troutmask.apl.washington.edu/~kargl/
Dave Seaman
2003-09-10 19:51:53 UTC
Permalink
Post by M. Serkan Apaydin
Hi,
I have a very basic question. I am trying to understand code written
in fortran, and since I am not a fortran programmer, I don't understand
FNrp=(FNrp1+FNrp2)/2._q
means. I checked a couple of tutorials and did some search with no success.
real(q) :: FNrp,FNrp1,FNrp2
It means that "2._q" is a real constant of kind "q". That is, it's like
saying

real(kind=q), parameter :: twoq = 2.0_q

where real(q) means real(kind=q). Most likely, the name "q" was chosen to
suggest "quad precision", but it would be defined somewhere in the
program as a parameter, such as

integer, parameter :: q = selected_real_kind(20,100)

or something similar.
--
Dave Seaman
Judge Yohn's mistakes revealed in Mumia Abu-Jamal ruling.
<http://www.commoncouragepress.com/index.cfm?action=book&bookid=228>
Jim Riley
2003-09-12 07:19:33 UTC
Permalink
On Wed, 10 Sep 2003 11:44:51 -0700, "M. Serkan Apaydin"
Post by M. Serkan Apaydin
I have a very basic question. I am trying to understand code written
in fortran, and since I am not a fortran programmer, I don't understand
FNrp=(FNrp1+FNrp2)/2._q
2._q

Is a constant of *type* real (as denoted by the presence of the
decimal point) and *kind* q (as denoted by the _ followed by q.
q is a named integer constant whose value is defined elsewhere in the
program. There is nothing special to Fortran about the letter q, or
the fact that it is a single letter. It could just as legally been

2.0_this_precision_produces_quick_but_adequate_answers

The other underscores in
this_precision_produces_quick_but_adequate_answers are part of the
identifier. They can be used to produce more readable identifiers
than thisprecisionproducesquickbutadequateanswers, which is not only
hard to read but not the same identifier. It is likely that a single
letter was chosen for compactness, and because q may not be used for
other purposes. 'q' might have been chosen because to the programmer
it meant 'quite good' or 'quad precision' or 'quality' or 'quick'.
Post by M. Serkan Apaydin
means. I checked a couple of tutorials and did some search with no success.
real(q) :: FNrp,FNrp1,FNrp2
FNrp is a variable of *type* real and kind q.


Before Fortran 90, Fortran had two real types, called REAL and DOUBLE
PRECISION. On any particular processor, DOUBLE PRECISION would
(usually) have greater precision, but would require more memory, and
often execute slower. But among different processors, REAL or DOUBLE
PRECISION could have different precision.

If you had written a program on a computer where REAL had sufficient
precision for solving your particular problem, you could have
unanticipated failure when you tried to port your program to a
computer where REAL had less precision.

You might then have to go through your program and change all the
declarations of REAL variables to DOUBLE PRECISION. If you are
careless in your editing, you may find the variable AREALIST has
become ADOUBLE PRECISIONIST. And your program might still not produce
the same or similar results.

You would then discover that you would also have to change your DOUBLE
PRECISION constants. 3.141593265358979 is a REAL constant, and might
well be stored with much less precision than you had typed in. To
indicate that it is a DOUBLE PRECISION constant, you need to add an
exponent using a 'D'. 3.14159 and 3.14159E0 are the both real
constants with the same value (i.e. 3.14159*(10**0) is 3.14159 * 1.0),
so the exponent is typically not included when writing real constants.
But it is the only way to indicate a DOUBLE PRECISION constant
(3.14159D0) where 'D' rather than 'E' is used both to set off the
exponent value and to denote a DOUBLE PRECISION constant.

And then when you converted your program back to the original
computer, you might find that it now produces different results.

Fortran 90 introduced the concept of subtypes, called *kinds*. A
processor must have two kinds of type real corresponding to REAL and
DOUBLE PRECISION, but it may implement other subtypes. Rather than
introducing a lot of new names like QUADRUPLE PRECISION, kinds are
specified by an integer value. **But** these integer values may vary
among different compilers. The intrinsic function kind(), returns the
kind value of its argument. That is, kind(1.0) is the kind value for
REAL values, and kind(1.0D0) is the kind value for DOUBLE PRECISION
values. On one processor, kind(1.0) might return a value of 27, while
on another it will return 4. But ordinarily, you shouldn't need to
know these values.

If I wanted to convert to more of a Fortran 90 style, but maintain the
flavor of explicitly denoting kinds, I could convert:

REAL X,Y,Z
DOUBLE PRECISION A,B,C

to

integer, parameter :: SP = Kind(1.0). DP = Kind(1.0D0)

This declares SP and DP to be named constants whose values are
respectively, the kind value for REAL (or more precisely the default
real subtype) and kind value for DOUBLE PRECISION.

real(kind=SP) :: x,y,z
real(kind=DP) :: a,b,c

I could do something weird like:

real(27) :: x,y,z

But that depends on me knowing that 27 is the kind value for single
precision on that particular processor. You may seem some uses of 4
and 8 in this manner. On some implementations, the kind value may
have been chosen to correspond to the number of bytes of storage, but
that is not is something to go hardwiring into a program.

I would also need to convert any real constants in my program:

X = (Y+Z)/2.0
A = (B+C)/2.0D0

to

x= (y+z)/2.0_SP
a= (b+c)/2.0_DP


More generally, I might want to choose by subtypes based on the
problem that my program is solving. For example, I might have decided
that my problem needed 10 decimal digits of precision. I could change
by declaration of kind values to

integer, parameter :: good_enough = 10
integer, parameter :: Q = Selected_Real_Kind(good_enough)

real(Q) :: x,y,z

x = (y+z)/2.0_Q

Selected_Real_Kind() is an intrinsic function that returns a kind
value of a real subtype that satisfies the specified precision needs
(in this case, it will have at least 10 decimal digits of precision).
--
Jim Riley
Loading...