One of the simplest examples was this:
INTEGER, PARAMETER :: idp = KIND(1.0D)
REAL(KIND=idp) :: ra
WRITE(*,*)KIND(ra)
END
onto which cvf66c and ifort gave an error, reporting syntax error in
the first line (INTEG .... 1.0D)
Also, the mentioned compilers do not seem to support KIND=2 type. Is
there something I'm doing wrong, or is the mentioned book just written
for some other compiler?
with regards,
Luka
On May 8, 11:52 am, Luka Djigas <ldigas@@gmail.com> wrote:
> INTEGER, PARAMETER :: idp = KIND(1.0D)
This should be
INTEGER, PARAMETER :: idp = KIND(1.0D0)
^^^
notice that you're missing the exponent for the number.
> Also, the mentioned compilers do not seem to support KIND=2 type. Is
> there something I'm doing wrong, or is the mentioned book just written
> for some other compiler?
The value of KIND is internal representation of the compiler. It's not
necessarily portable, so different compiler may have different value
of KIND to represent the same precision. i.e the result of :
WRITE(*,*)KIND(ra)
may be different for different compiler.
So the way to select the KIND is by doing what you have in the
example, or using function such as selected_int_kind() or
selected_real_kind().
There is no particular standard meaning for KIND=2, it certainly
isn't guaranteed to be double precision. Most processors now
use kind numbers that are related to bytes; 4 for single, 8 for
double. But, that isn't required.
The purpose of the KIND system is to allow you to specify what
you need or want for the precision of floating point variables.
Specifying KIND(1.0D0) is just another way of spelling
DOUBLE PRECISION. You're usually better off to use the
SELECTED_REAL_KIND intrinsic and specify something like
INTEGER, PARAMETER :: idp = SELECTED_REAL_KIND(13)
and then you're guaranteed to get 13+ digits of precision on
all processors. Specifying DOUBLE PRECISION (or KIND(1.0D0))
is likely to get you 26 digits of precision on a machine whose
native floating point mode is 64 or 128 bits rather than the
more common 32/62 bits. That's likely to be noticeably slower.
Dick Hendrickson
>Hello,
>
>On May 8, 11:52�am, Luka Djigas <ldigas@@gmail.com> wrote:
>
>> INTEGER, PARAMETER :: idp = KIND(1.0D)
>
>This should be
>INTEGER, PARAMETER :: idp = KIND(1.0D0)
> ^^^
>notice that you're missing the exponent for the number.
Ah, I see.
Must've been a mistype in the book.
>
>> Also, the mentioned compilers do not seem to support KIND=2 type. Is
>> there something I'm doing wrong, or is the mentioned book just written
>> for some other compiler?
>
>The value of KIND is internal representation of the compiler. It's not
>necessarily portable, so different compiler may have different value
>of KIND to represent the same precision. i.e the result of :
>WRITE(*,*)KIND(ra)
>may be different for different compiler.
>
>So the way to select the KIND is by doing what you have in the
>example, or using function such as selected_int_kind() or
>selected_real_kind().
So, if I wish to achieve portable precision I should check
SELECTED_REAL_KIND (or _INT_) with my required precision and range,
and according to results of those, adjust my KIND parameter ?
with regards
Luka
Yeah, but don't actually use the KIND value itself, keep to the
PARAMETER. Then you don't have to change between compilers (the point
of introducing the syntax)
See Dick H's response on the logic behind the use of the intrinsics;
I'll not try to repeat is succinct explanation...
--
> Luka Djigas wrote:
> > I'm looking over some examples from Ramsden & Lin's "Fortran 90
> > conversion course for F77 programmers", and glancing over the chapter
> > which shows KIND parameter. I've never used it before, sticking to old
> > DOUBLE PRECISION when it was needed.
...
> > INTEGER, PARAMETER :: idp = KIND(1.0D)
...
> > Also, the mentioned compilers do not seem to support KIND=2 type.
> Unless I'm missing something, the first line looks OK. Could you
> show the actual results? Are you sure you aren't compiling
> in fixed form mode rather than free form?
That was my thought as well. Both Dick's and my eyes missed the omission
of the 0 from D0, which Reubendb caught.
> There is no particular standard meaning for KIND=2, it certainly
> isn't guaranteed to be double precision.
I haven't seen the particular book in question, but I'd be a bit
dissapointed at any book that suggested using explicit kind numbers such
as 2. No explicit kind numbers are specified by the standard, and 2
isn't even the most common choice for double precision.
If the OP is looking for a book aimed at upgrading from f77, I am quite
fond of Cooper Redwine's "UPgrading to Fortran 90". It is no longer in
print, but can often be found. (Wow, I see that Amazon shows quite
premium prices for used copies! I suppose that probably reflects
something about the demand.)
> The purpose of the KIND system is to allow you to specify what
> you need or want for the precision of floating point variables.
Also, a thing that I particularly like about the KIND system is its
consistency. (A thing that I dislike about it is the use of integers for
KIND numbers, which promulgates nonportable practices as well as just
plain mistakes; oh well). Look at what is involved in adding a new
precision, such as the quad precision that is moderately common these
days. With the "old-fashioned" way, this involves quite a lot of new
syntax. You need a new declaration statement, an exponent letter
(certainly in the source code, and often also for formatted I/O), a
bunch of new intrinsic names, and I forget what else.
Try taking a program that was written for one precision and converting
it to use another one. That can come up for many reasons. Perhaps you
are on a compiler where single and double precision are different from
the compiler the code was written for. Or perhaps you are applying the
code to problems that require larger precision than the probleme
envisioned when the code was written. In my youth, I used to spend quite
a lot of time doing precision conversions like that (most often as a
consequence of moving to a new computer with a different default
precision). I can testify that it can be a *LOT* of work in some cases.
It is possible to write code that converts easily, but you have to be
very deliberate about the intention of making it easy to convert.
With KIND parameters, you can define the kind parameter value on a
single line in a module. Then it is a one-line change to convert the
entire program. (Ok, programs that use multiple precisions can be more
complicated than that in some cases.) All the syntax is unchanged; the
same syntax works for single, double, quad, or any other oddball
precision that you might have.
--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
Do something like this:
MODULE Type_Kinds
IMPLICIT NONE
PRIVATE
PUBLIC :: Byte, Short, Long
PUBLIC :: Single, Double
INTEGER, PARAMETER :: Byte = SELECTED_INT_KIND(1) ! Byte integer
INTEGER, PARAMETER :: Short = SELECTED_INT_KIND(4) ! Short integer
INTEGER, PARAMETER :: Long = SELECTED_INT_KIND(8) ! Long integer
INTEGER, PARAMETER :: Single = SELECTED_REAL_KIND(6) ! Single precision
INTEGER, PARAMETER :: Double = SELECTED_REAL_KIND(15) ! Double precision
END MODULE Type_Kinds
and then USE the above module everywhere you need explicit types,
PROGRAM blah
USE Type_Kinds, fp=>Double
IMPLICIT NONE
REAL(fp) :: x
x = 3.14159_fp
.....
END PROGRAM
You'll then have a portable way to define all your intrisic int and float types.
If you want to switch to single prevision, change the USE statement in your app to,
USE Type_Kinds, fp=>Single
cheers,
paulv
>
>I haven't seen the particular book in question, but I'd be a bit
>dissapointed at any book that suggested using explicit kind numbers such
>as 2. No explicit kind numbers are specified by the standard, and 2
>isn't even the most common choice for double precision.
Actually, it isn't a book but a 'scripta' (latin). I didn't know how
to say it in english correctly so it comes out in the right context. A
pamphlet, a "textbook" maybe - yes, that would probably be pretty
close.
They don't suggest using explicit kind numbers. I've rather ankwardly
expressed myself there - they don't assume that kind=2 would be double
precision either.
That was a completely different question whatsoever, just putted
behind the first one in a manner that it was understood in context of
the first one - I was curious why the compiler didn't support it.
>> The purpose of the KIND system is to allow you to specify what
>> you need or want for the precision of floating point variables.
>
>Also, a thing that I particularly like about the KIND system is its
>consistency. (A thing that I dislike about it is the use of integers for
>KIND numbers, which promulgates nonportable practices as well as just
>plain mistakes; oh well).
Could you explain this a little ?
I fail to see how those integers are important at all ... they are
just a means of expressing what KIND is needed for wanted precision.
I guess those numbers could be real's as well, but I cannot see the
advantage in that approach.
I must be missing something here.
>Look at what is involved in adding a new
>precision, such as the quad precision that is moderately common these
>days. With the "old-fashioned" way, this involves quite a lot of new
>syntax. You need a new declaration statement, an exponent letter
>(certainly in the source code, and often also for formatted I/O), a
>bunch of new intrinsic names, and I forget what else.
Ughh,
yes, unfortunatelly, I've done it a few times, but never *liked* doing
it. I've always had the feeling that I missed something somewhere.
>
>Try taking a program that was written for one precision and converting
>it to use another one. That can come up for many reasons. Perhaps you
>are on a compiler where single and double precision are different from
>the compiler the code was written for. Or perhaps you are applying the
>code to problems that require larger precision than the probleme
>envisioned when the code was written. In my youth, I used to spend quite
>a lot of time doing precision conversions like that (most often as a
>consequence of moving to a new computer with a different default
>precision). I can testify that it can be a *LOT* of work in some cases.
>It is possible to write code that converts easily, but you have to be
>very deliberate about the intention of making it easy to convert.
>
>With KIND parameters, you can define the kind parameter value on a
>single line in a module. Then it is a one-line change to convert the
>entire program. (Ok, programs that use multiple precisions can be more
>complicated than that in some cases.) All the syntax is unchanged; the
>same syntax works for single, double, quad, or any other oddball
>precision that you might have.
Yes, Paul van Delst gave an example in his post, which is very nice in
illustrating that view.
with regards
Luka
>Unless I'm missing something, the first line looks OK. Could you
>show the actual results? Are you sure you aren't compiling
>in fixed form mode rather than free form?
Quite sure.
But, either way, would it make a difference ?
>
>There is no particular standard meaning for KIND=2, it certainly
>isn't guaranteed to be double precision. Most processors now
>use kind numbers that are related to bytes; 4 for single, 8 for
>double. But, that isn't required.
No, no. I've putted this in a rather ankward way. I didn't mean to
suggest that KIND=2 would be double precision.
I was just suprised that they didn't support it.
>
>The purpose of the KIND system is to allow you to specify what
>you need or want for the precision of floating point variables.
>Specifying KIND(1.0D0) is just another way of spelling
>DOUBLE PRECISION. You're usually better off to use the
>SELECTED_REAL_KIND intrinsic and specify something like
>
>INTEGER, PARAMETER :: idp = SELECTED_REAL_KIND(13)
>
>and then you're guaranteed to get 13+ digits of precision on
>all processors. Specifying DOUBLE PRECISION (or KIND(1.0D0))
>is likely to get you 26 digits of precision on a machine whose
>native floating point mode is 64 or 128 bits rather than the
>more common 32/62 bits. That's likely to be noticeably slower.
I understood the point about the SELECTED_ functions, but the one
about the processor's "number of bits" escaped me.
I thought that single precision on 32-bit cpu's ment 13+ safe digits,
and double twice that.
Could I bother you to explain a little more how the processor's
"number of bits" effects precision when using SELECTED_ functions ?
I'm under the impression that if I use SELECTED_ to determine the kind
value, I don't need to worry about cpu's "number of bits".
with regards
Luka
> On Fri, 8 May 2009 10:27:25 -0700, nos...@see.signature (Richard
> Maine) wrote:
> >(A thing that I dislike about it is the use of integers for
> >KIND numbers, which promulgates nonportable practices as well as just
> >plain mistakes; oh well).
>
> Could you explain this a little ?
>
> I fail to see how those integers are important at all ... they are
> just a means of expressing what KIND is needed for wanted precision.
> I guess those numbers could be real's as well, but I cannot see the
> advantage in that approach.
>
> I must be missing something here.
No, they wouldn't be reals. That would be just as bad (and probably
worse). The problem with them being integers (or any numeric type) is
that it provides no error protection. You can do completely
inappropriate things with them and the compiler likely won't catch it
because it isn't technically an error of the kind that won't compile,
even if it happens to have nothing to do with what you intended.
There is an excellent example of exactly this in another thread that is
active right now on this newsgroup. It is so good an example that you
might think I planted it for the purpose. (I didn't). Someone took a
kind parameter for a character character kind parameter and used it
inappropriately as a kind parameter for an integer (possibly influenced
by C conflation of character and integer). It is basically nonsense to
use a kind parameter for a character that way, but because kind
parameter values are just ordinary integers, there is nothing to say
that such a thing is actually invalid. It is pretty much nonsense by
definition, but it is nonsense that the compiler is actually required to
allow.
The idea would instead be to have a derived type for each kind
parameter. You then could not accidentally do arithmetic on them or
accidentally use some other random integer expression for a kind value.
The *ONLY* things that would be allowable as integer kind values would
be things that had the derived type defined for integer kind values. If
you made the mistake of using a kind value that was supposed to be for a
character, it would be of the wrong type and you'd get a compilation
error. In fact, apparently one of the compilers tested tried to do
something like that and throw an error for the inappropriate usage.
Unfortunately, with Fortran defined as it is today, that bit of compiler
help counts as a compiler bug.
Another advantage is that you wouldn't have to continually caution
people about how the standard doesn't specify particular numeric values
for kind parameters. The question just wouldn't come up at all.
The above are practical issues, but I think there is a more fundamental
conceptual one of integers being inappropriate to model kind parameters.
In my view, the practical problems are a consequence of the conceptual
mismatch. Integers are numeric and have all kinds of numeric properties.
Those numeric properties are not a good match for kind parameters. It
generally doesn't make any sense to be doing addition, multiplication,
exponentiation, and Lord knows what else with kind parameter values.
This isn't going to happen. I'm not making it as a serious proposal
because that would just waste the time of all concerned, debating about
something that isn't going to happen. Likewise, I'm not filling in the
fine points of detail because it seems pointless to work out the fine
points of something that won't happen. This is just explaining a rough
outline of the direction I wish it had been taken.
About 3.32 bits per decimal digit. (1./log10(2.)). 32 bit float
has about 24 digits of significand for 7.2 decimal digits.
> Could I bother you to explain a little more how the processor's
> "number of bits" effects precision when using SELECTED_ functions ?
> I'm under the impression that if I use SELECTED_ to determine the kind
> value, I don't need to worry about cpu's "number of bits".
The kind values give the appropriate KIND, if any, for the
specified number of significant decimal digits or exponent range.
If you know the exact precision required (rare) then you can
specify that with SELECTED_REAL_KIND and use the appropriate
kind. If you ask for more than the processor can supply, then
SELECTED_REAL_KIND returns -1 and compilation fails.
Some people would like the ability to specify the number of
bits required, which may not represent an integer number of digits.
Fortran as yet doesn't have that ability. (I believe not in 2008,
though I am not so sure about that.)
-- glen
>
>> There is no particular standard meaning for KIND=2, it certainly
>> isn't guaranteed to be double precision. Most processors now
>> use kind numbers that are related to bytes; 4 for single, 8 for
>> double. But, that isn't required.
>
> No, no. I've putted this in a rather ankward way. I didn't mean to
> suggest that KIND=2 would be double precision.
> I was just suprised that they didn't support it.
>
But, there's no reason to be surprised. The KIND numbers aren't
directly related to anything specific in the hardware or
processor. They're an arbitrary "tag" chosen by the compiler
writer to "name" the precisions they have chosen to support.
As I said, the KIND numbers often are the same as the number
of bytes in the entity. Many compilers support KIND=2 as
a 16 bit integer; but almost none would support a 16 bit
floating point value. Many years ago, some processors used
kind=1 for single precision and kind=2 for double. Some
still do, although they usually have a command line switch
that lets the programmer choose between 1/2 or 4/8 for the
kind numbers. The switch lets people who have put in fixed
numbers for the kinds compile their programs.
>
>> The purpose of the KIND system is to allow you to specify what
>> you need or want for the precision of floating point variables.
>> Specifying KIND(1.0D0) is just another way of spelling
>> DOUBLE PRECISION. You're usually better off to use the
>> SELECTED_REAL_KIND intrinsic and specify something like
>>
>> INTEGER, PARAMETER :: idp = SELECTED_REAL_KIND(13)
>>
>> and then you're guaranteed to get 13+ digits of precision on
>> all processors. Specifying DOUBLE PRECISION (or KIND(1.0D0))
>> is likely to get you 26 digits of precision on a machine whose
>> native floating point mode is 64 or 128 bits rather than the
>> more common 32/62 bits. That's likely to be noticeably slower.
>
> I understood the point about the SELECTED_ functions, but the one
> about the processor's "number of bits" escaped me.
> I thought that single precision on 32-bit cpu's ment 13+ safe digits,
> and double twice that.
Actually, 32 bit single precision is about 7 digits, not 13.
>
> Could I bother you to explain a little more how the processor's
> "number of bits" effects precision when using SELECTED_ functions ?
> I'm under the impression that if I use SELECTED_ to determine the kind
> value, I don't need to worry about cpu's "number of bits".
True, you don't have to worry about the number of bits. But,
ultimately you can only get precisions that the hardware supports.
The SELECTED_* functions give you a portable way to determine
what KIND value you should use on a processor. And, they do it in
a portable way that doesn't require any programming changes when
you move to a different compiler or computer.
To get a feeling for what the selected_* functions do, try
running the following program (I haven't actually tried it myself,
you'll probably have to debug it some :( )
program show_kinds
do I = 1,50
J = selected_integer_kind(I)
K = selected_real_kind(I)
L = selected_real_kind(I,200)
print "(4I5)", I,J,K,L
enddo
end program
Dick Hendrickson
>
> with regards
> Luka
It's still a little unclear to me how to manage kinds in the context of
a program that uses multiple libraries, each with their own working
precision kind parameters defined.
In the context of a single self-contained program or library, I would
simply define a working precision kind parameter and use it uniformly
throughout the program. For a program which uses a single external
library, say LAPACK95, I would probably use the precision parameters
defined by the library:
use la_precision, only: wp
However, what do you do when you need to use multiple libraries?
(Or, when you're designing a library that would likely be used
with others?) Let's say that library_a defined
integer, parameter :: a_wp = selected_real_kind(1.d0)
while library_b uses
integer, parameter :: b_wp = selected_real_kind(15, 307)
In some cases these will be the same, but you can't assume they
will be.
What kind should you use in your program? If, say, you use the
precision from library_a:
program main
use library_a, wp => a_wp
use library_b
implicit none
real(wp) :: x, y
What happens if I call a routine from library_b using x and y
if the kinds happen to be different?
call b_routine(x, y)
Is this handled automatically by casting or does it only work if the
kind parameters are identical?
I guess my main questions are what are the best practices for selecting
kind parameters when designing a library (I tend to like the renaming
facility of LAPACK95) and how should you handle (potentially) different
precisions from different libraries in a single program?
--
Jason Blevins
Ph.D. Candidate, Department of Economics, Duke University
http://jblevins.org
> It's still a little unclear to me how to manage kinds in the context of
> a program that uses multiple libraries, each with their own working
> precision kind parameters defined.
>
> In the context of a single self-contained program or library, I would
> simply define a working precision kind parameter and use it uniformly
> throughout the program. For a program which uses a single external
> library, say LAPACK95, I would probably use the precision parameters
> defined by the library:
>
> use la_precision, only: wp
>
> However, what do you do when you need to use multiple libraries?
Most commonly, you would not use precision parameters from such
libraries at all. You would use your own precision parameters. The
library should have generic procedure names, so you just invoke the
procedures with their generic names and you will get the right version
for whatever precision you are using. This doesn't involve using
precision parameters from the library at all.
If you aren't familiar with generic procedures, you'll likely be
confused by the above because generics are the crux of the whole idea.
And it is important to note that you do not need to use the kind
parameter
> (Or, when you're designing a library that would likely be used
> with others?)
Now that's more work, particularly when you have to deal with supporting
multiple environments that have different numbers of precision options
(notably if some of the environments have a quad real and others don't).
I don't think I'll try to go into that one here. It is a harder question
(but fortunately, one that fewer people have to deal with; it's a
question for the library writers more than for the library users).
> What happens if I call a routine from library_b using x and y
> if the kinds happen to be different?
>
> call b_routine(x, y)
>
> Is this handled automatically by casting or does it only work if the
> kind parameters are identical?
There is no casting in Fortran. (There are some mixed-mode operations,
but that's not the same thing). The actual and dummy arguments must
match. The library could choose to explicitly provide a version of the
subroutine that had the mixed kinds, but that would pretty quickly get
out of hand in the general case. That's much of why I talk about the
precision used on a whole application basis. You can't expect to
indivually select the precision of every separate object in your program
and get anything but a mess. (Besides, it would be too much bother to go
through deciding exactly what each object needed.) Instead, you select a
precision that pretty much the whole app will use for most things; you
can have exceptions where something uses a different precision, but they
need to be a relatively small number of exceptions to keep things under
control.
> I'm looking over some examples from Ramsden & Lin's "Fortran 90
> conversion course for F77 programmers", and glancing over the chapter
> which shows KIND parameter. I've never used it before, sticking to old
> DOUBLE PRECISION when it was needed.
>
> One of the simplest examples was this:
>
> INTEGER, PARAMETER :: idp = KIND(1.0D)
> REAL(KIND=idp) :: ra
>
> WRITE(*,*)KIND(ra)
> END
>
>
> onto which cvf66c and ifort gave an error, reporting syntax error in
> the first line (INTEG .... 1.0D)
It must be 1.0D0
> Also, the mentioned compilers do not seem to support KIND=2 type. Is
> there something I'm doing wrong, or is the mentioned book just written
> for some other compiler?
You don't need to specify any kind numbers.
Doing so can make the program non-portable.
All that's necessary is to specify something like:
INTEGER, PARAMETER :: idp = KIND(1.0D0)
Yes.
But what you originally wrote is OK too
[with minor correction, of course].
> I understood the point about the SELECTED_ functions, but the one
> about the processor's "number of bits" escaped me.
> I thought that single precision on 32-bit cpu's ment 13+ safe digits,
> and double twice that.
Typically, single precision (32 bits) gives about 6 decimal digits,
while double precision gives about 15 digits.
> INTEGER, PARAMETER :: idp = KIND(1.0D)
According to Chapman, it would be better to specify the numer of digits
that you need instead of using "1.0D0" or "1.0E0", since the concept of
single/double precision is different among compilers.
This is an example:
INTEGER, PARAMETER :: sp = SELECTED_REAL_KIND(p=6)
INTEGER, PARAMETER :: dp = SELECTED_REAL_KIND(p=15)
INTEGER, PARAMETER :: ep = SELECTED_REAL_KIND(p=18)
INTEGER, PARAMETER :: qp = SELECTED_REAL_KIND(p=33)
sp -> single precision, 32 bit
dp -> double precision, 64 bit
ep -> extended precision, 80 bit (only for x86)
qp -> quadruple precision, 128 bit
--
Lurkos
> Another advantage is that you wouldn't have to continually caution
> people about how the standard doesn't specify particular numeric values
> for kind parameters. The question just wouldn't come up at all.
> [and...] It generally doesn't make any sense to be doing addition, multiplication,
> exponentiation, and Lord knows what else with kind parameter values.
>
Doesn't help with those, however.