INTEGER*8 usage

189 views
Skip to first unread message

r d

unread,
Nov 3, 2009, 7:04:07 PM11/3/09
to GNU Fortran
Consider the following declaration and usage:

INTEGER J
INTEGER*8 int8

int8 = 1

DO J = 1,int8
ENDDO

IF(int8.EQ.1)THEN
ENDIF

If I compile this with gfortran (64bit linux machine) with all of the
compiler flags turned on for catching implicit type assignments, then
I get warning messages for each of these uses of int8 in that there is
a mixed use of INTEGER*4 and *8 being performed.
The first is most surprising, since the compiler considers that "1" is
INTEGER*4.

My fixes are:

int8 = INT(1,KIND=8)

DO J = 1,INT(int8)
ENDDO

IF(INT(int8).EQ.1)THEN
ENDIF

Surely there must be a simpler way, especially for the first case.
What is it?
(yea I could turn the compiler flags off, but then I wouldn't catch
other problems.)
Thanks.

Tobias Burnus

unread,
Nov 4, 2009, 5:28:40 PM11/4/09
to gnu-f...@googlegroups.com
r d wrote:
> int8 = 1
> DO J = 1,int8
> IF(int8.EQ.1)THEN

>
> If I compile this with gfortran (64bit linux machine) with all of the
> compiler flags turned on for catching implicit type assignments, then
> I get warning messages for each of these uses of int8 in that there is
> a mixed use of INTEGER*4 and *8 being performed.
> The first is most surprising, since the compiler considers that "1" is
> INTEGER*4.
>

First, I think one can (at least for most integer-to-integer
conversions), ignore this warning. It is not really a bad programming
style to do so - at least if one is cautious not to do it when it
matters. For instant "real(8) :: sq2 =sqrt(2.0)" is a bad idea because
one wasts precision.

> int8 = INT(1,KIND=8)
>
Secondly, doing "INT(1, kind=8)" does not really make "1" a 8-byte
variable but converts a 4-byte variable to an 8-byte variable. The
proper way is to use:
1_8
where "8" is the kind number. Analogously, one can use 1_4 (for
integer(4)) or 1.0_8 for real numbers. For real numbers, using
something like
integer, parameter :: dp = kind(0.0d0) ! effectively: dp = 8
and then
1.0_dp
is the recommend way of doing. Thus my square-root -2 example would be
best written as
sq2 = sqrt(2.0_dp)

For integers one could do the same, e.g.
integer, parameter :: i8 = 8
int8 = 1_i8

The advantage of using a constant like "dp" or "i8" is that one can
change it if needed.

Note that kind numbers "8" and "4" for 8-byte and 4-byte variables are
very common, but that the standard allows any positive integer and it
depends on the compiler which one is valid and has which length. For
instance the NAG compiler uses 1 and 2 instead of 4 and 8 (except with
"-kind=byte").

Tobias

fulvio ciriaco

unread,
Nov 5, 2009, 2:14:22 AM11/5/09
to gnu-f...@googlegroups.com, bur...@net-b.de
Is this the dark side of fortran(90|95) or is it a peculiarity
of gfortran? Numeric constants do not burden programmers in other
languages. Some languages check if they are within constraints
of the assigned variables, particularly in inizialization, but
treat them otherwise like a literal.
A warning from
int8=int4
makes little sense, a warning from
int8=1
makes no sense at all.
Asking the programmer to ignore these warnings also makes
no sense, since one raises the verbosity level because is looking
for the cause of troubles and wishes to search the cause of his problem
in the smallest amount of text.
I agree that int8=1 is not a bad programming practice, to the point
that it should not issue any warning.
For "real(8) :: sq2 =sqrt(2.0)", it is instead certainly necessary
to issue the warning that the compiler is not so smart as to
understand that 2.0 is a real(8).
Please understand that I am no standard guru and that I am speculating
on the basis of knowledge of other languages.
Hence my first question: does this somehow meet a fortran(90|95)
specification?
In this case, this is a rant against recent advancements, because
fortran was a practical and readable language and is loosening
these smart attributes at a fast pace with each standard.
Fulvio

Tobias Burnus

unread,
Nov 5, 2009, 9:02:40 AM11/5/09
to fulvio ciriaco, gnu-f...@googlegroups.com
Hi Fulvio,

On 11/05/2009 08:14 AM, fulvio ciriaco wrote:
> Is this the dark side of fortran(90|95) or is it a peculiarity
> of gfortran? Numeric constants do not burden programmers in other
> languages.

That is the burden of Fortran 66 or even older (Fortran I?) - except
that you do not have there the underscore-number syntax. But Fortran 66
definitely made a distinction between 1.0 = 1.0e0 and 1.0d0 where the
former is single precision ("real" = "real*4") and the latter is "double
precision" (= "real*8").

But that's also not different from other programming languages. In C
"123" is "int" - and not "long". And 1.0 is "double", while 1.0f is
"float" and 1.0l is "long double".

For strings, even Python makes a distinction between b"ABC" and u"ABC"
(hope I got the syntax right).

Often one does not care and result is the same independ whether 1, 1_8,
1.0, or 1.0_8 is used. But sometimes it matters. Note that in gfortran
the warning is not enabled by default.

> Some languages check if they are within constraints
> of the assigned variables, particularly in inizialization, but
> treat them otherwise like a literal.
>

I doubt that there are many languages where it is a constraint.
(Constraint means something invalid which the compiler *must* reject -
at least that's what "constraint" means in the ISO Fortran standard.)

Well, if you try
int8 = 214748364833
you get an *error* in gfortran as 214748364833 overflows. The problem
with warning is that it really depends whether one wants to see a
warning or not. This is highly nontrivial - I once wanted to reduce the
number of conversion warnings in gfortran, but I gave up as it was not
clear to me when one could really turn the warning off.

> A warning from
> int8=int4
> makes little sense

Why? You can overflow here - you may not care or you know that it cannot
happen, but the compiler cannot know it (in the general case).

> a warning from
> int8=1
> makes no sense at all.
>

For integer not, but how about
real8 = 0.1
? ("0.1" is not exactly representable in a binary floating point number.)

> Asking the programmer to ignore these warnings also makes
> no sense, since one raises the verbosity level because is looking
> for the cause of troubles and wishes to search the cause of his problem
> in the smallest amount of text.
>

Sorry, there is no other solution: You cannot have all: (a) no
unnecessary warning, (b) writing sloppy code with the (implicit) type
conversion, (c) warnings where it matters. Choose one, choose two but
you cannot get all three.

I think that the most reasonable usage of the conversion warning is the
following: Develop the code with the warning disabled (-Wno-conversion)
- and only once in a while turn on -Wconversion and go through the list
of warning and check whether any of them requires action. I usually
check real/complex(4) -> real/complex(8) and
real/complex(8)->real/complex(4).

There will be hundreds of unnecessary warnings, but there will be one or
two where you made a mistake.

Tobias

fulvio ciriaco

unread,
Nov 5, 2009, 11:39:20 AM11/5/09
to bur...@net-b.de, gnu-f...@googlegroups.com
Hallo Tobias,
since you mention C, let us try:
----test.c----------------------
int main() {
double a=1.0l;
float b=1.0l;
long int ia=123;
int ib=123l;
if (ia==123) {ib=123l;}
if (ib==123l) {ia=123;}
if (a==1.0l)
{b=0.1l;}
return 0;
}
----------------------------------------------
0>gcc -Wall -Wconversion test.c
test.c: In function 'main':
test.c:9: warning: conversion to 'float' alters 'long double' constant value

Only line 9 i.e. {b=0.1l;} issues a warning, and this is more or less
the philosophy behind my words.
For integers, the literal describes the number unequivocally, no need
to burden the programmer with suffixes, only overflow could bring
problems, but the compiler can check overflow in most cases.

For inprecise numbers, two cases hold:
-initialization poses no problem, it is like reading into the
number from a string;
-assignment and comparison is the problem, I do not know why line 8
issues no warning. In my opinion, implicit type conversion should
not appear in clean code.

Python, lisp, scheme and similar syntaxes are not relevant. Variables
are simply lexical bindings in these languages, there is nothing
like a double float variable, only double float values. You can change
representation only by explicit cast.

In SML, which is a strongly typed language
val a:Int32.int=0;
means the same as
val a=(0:Int32.int);
that is, 0 is a lexical representation for any value appropriate
for the left side.

Thank you for your patience
Fulvio

From: Tobias Burnus <bur...@net-b.de>
Subject: Re: INTEGER*8 usage

samig

unread,
Mar 25, 2013, 12:50:27 PM3/25/13
to gnu-f...@googlegroups.com
Quite I few years delayed, but here why your compiler *should* warn you for implicit casting:


Cheers,

/Sakis
Reply all
Reply to author
Forward
0 new messages