I just encountered the following in ifort (IFORT) 15.0.0 2014072
program integerkinds
use iso_fortran_env
implicit none
integer(kind=selected_int_kind(15)):: j15
print *,'Selected Integer Kind 15:'
print *, huge(j15)
print *, int(huge(j15))
print *, int(huge(j15),kind=selected_int_kind(15))
end program integerkinds
for which the output is
Selected Integer Kind 15:
9223372036854775807
-1
9223372036854775807
shouldn't the compiler automatically choose the correct return type based on int()'s argument? This unexpected behavior has just cost me about 2500 hours of computing time on our cluster :(
The documentation states (http://nf.nci.org.au/facilities/software/intel_fortran_reference.pdf at page 9-80):
Argument Type Result Type
INTEGER(1), INTEGER(2), INTEGER(4) INTEGER(4)
INTEGER(1), INTEGER(2), INTEGER(4), INTEGER(8) INTEGER(8)
According to this table Integer(8) as argument should give Integer(8) as result type, but the output gives -1. Looks like a bug to me, but I wanted to get a second pair of eyes on this before I go and bug the intel developers. Is there something in the standard that I am overlooking that mandates a -1 as return value here?
No. That table is wrong or misleading (the multiple rows, which otherwise make no sense, may possibly reflect variation in behaviour given some compatibility option, but if so I'm not aware of what option it is). In standard Fortran, the kind of the result of the INT generic intrinsic only depends on the presence and value of the KIND argument. If the KIND argument is not present then the result has default integer kind, otherwise the KIND argument specifies the KIND of the result.
The value of the argument to the second invocation of INT in your example program cannot be represented in a default integer for that compiler, in the absence of compile options that change the default integer kind. Your code is non-conforming.
While the text has not changed materially (apart from perhaps becoming more confusing) I note that the documentation that you link to is ancient.
Related
If you have a standalone function in a file (not in a module) and you call it with a single-precision while it expects a double precision number:
main.f90 :
program main
call test(1.0)
end program main
test.f90:
subroutine test(a)
double precision :: a
print *, "a", a
end subroutine
How does the compiler "casts" from single to double precision in this case ?
Using floating-point format, I would expect the bits to stay the same during the cast but additionnal zeroes to be appended. That is:
1 = 0 01111111 00000000000000000000000 in single-precision
and I would expect the final value to be 2^(-7):
0 01111111000 0000000000000000000000000000000000000000000000000000 in double precision
Surprisingly, with gfortran 6.4.0, the final value is 5.2635442471208903E-315.
The compiler does no casting. What you have written is not Fortran.
In the main program the subroutine test has an implicit interface. Essentially, the compiler knows nothing about this except that it is a subroutine. You also tell it that it has a single (default) real argument.
It is your responsibility, not the compiler's, to provide the correct type and kind of argument when referencing the subroutine. You failed there, so you do not have a compliant Fortran program. The Fortran compiler owes you nothing.
What you will observe will depend on implementation details of the Fortran processor. The subroutine expects a double precision argument and has no reason to believe it has anything else. Whether there is copy-in/copy-out or some address passing1, the interpretation of memory will not match. In the dummy argument, all but the bytes corresponding to the default real of the actual argument are "junk".
If you provide an explicit interface for the subroutine in the main program there will still be no casting, but the compiler will notice the mismatch. Equally, some compilers (perhaps with certain compile flags) will do some checking even when an implicit interface is there.
1 For details of the likely pass-by-reference, see the comment by user5713492.
I guess the compiler "casts" according to endianess. If you stak zeros on the left, you get:
0 00000000000 0000000000000000000000111111100000000000000000000000
Which is 5.2635442471208903E-315. You can check by forcing endianess at compile-time.
I have some legacy Fortran code which I was asked to analyze and translate to a modern language. I don't know which compiler was used in the past to compile the code, so for now, I'm trying to compile it with gfortran. The code contains a statement like this was causes gfortran to complain:
program test
implicit none
integer*4 :: var
var=.true.
if(var) then
write(*,*) "Hi"
endif
end program test
Compiling this with gfortran gives the following error:
test.f:6:9:
if(var) then
1
Error: IF clause at (1) requires a scalar LOGICAL expression
(In addition, it gives a warning about the conversion done in var=.true.).
I'm not sure which which compiler the code was compiled, but apparently the code should compile as it is. Is there a way to tell gfortran to accept this conversion?
According to the docs, no implicit conversion is done within if-statements though: https://gcc.gnu.org/onlinedocs/gfortran/Implicitly-convert-LOGICAL-and-INTEGER-values.html
This is not possible in GFortran. The manual states:
However, there is no implicit conversion of INTEGER values in
if-statements, nor of LOGICAL or INTEGER values in I/O operations.
You are only able to perform implicit conversions in assignments like your
integer :: var
var = .true.
but even there you must be very careful. It is not standard conforming and the value var will differ between compilers. Intel used to use -1 (all bits set to 1), unless -standard-semantics was chosen, for .true., but gfortran uses +1 as in the C language. New versions of Intel Fortran changes the default. The other direction is even trickier, there might be values which are neither .true. nor .false..
This question already has an answer here:
Fortran: Integer too big for its kind
(1 answer)
Closed 7 years ago.
I want to see integer kind number of gfortran
so I write this line
write(*,"(1X,I20,'correspond to kind ',I2)"),11111111111,kind(11111111111)
There will be compilation error says
precision of type test.f90:67:57: Error: Integer too big for its kind
at (1). Th is check can be disabled with the option -fno-range-check
So I tried recompile with -fno-range-check. But it gives result
-1773790777correspond to kind 4
What is wrong? On the other hand, intel fortran gives no error and correct answer
An integer literal without any kind designation is always of the default kind no matter what value you enter1. There is therefore no much sense to even inquire
kind(111111111111)
the kind of any such literal is always the default kind, provided the value is valid. So the same as kind(1).
All integer kinds have a limited range of values. The largest one you can get using
write(*,*) HUGE(1)
Here instead of 1 you can use any other constant or variable of the integer kind you examine. Most often, the default value of HUGE will be 2147483647 which corresponds to 32-bit integers.
To use larger integer literal constants, use larger non-default kinds.
It doesn't matter if you use the methods from Fortran 90:
integer, parameter :: lk = selected_int_kind(15)
write(*,*) 11111111111_lk
or from Fortran 2008
use iso_fortran_env
integer, parameter :: lk = int64
write(*,*) 11111111111_lk
Both will work. Of course kind(11111111111_lk) will return the value of lk.
1 That is in standard Fortran. Some compilers may promote a large value to a larger kind for you, but only as a non-standard extension. You may be unpleasantly surprised when moving to a compiler, which keeps the standard behaviour.
There may be a better explanation, but this is how I understand it. The short answer is the compiler defaults to a 4 byte integer.
Fortran is statically typed and you have not declared a variable type. The compiler is forced to use the default integer kind, 4 bytes in this case. The kind function simply returns the 'kind' of integer used. The compiler is letting you know that you are trying to assign a value too large for a 4 byte integer. When you apply -fno-range-check the compiler ignores this fact and the value overflows, thus the negative value returned. You can specify that the default integer kind be 8 bytes, -fdefault-integer-8. See the gfortran docs
Example foo.f90:
program foo
write(*,"(1X,I20,' correspond to kind ',I2)"),111111111111,kind(111111111111)
write(*,"(1X,I20,' correspond to kind ',I2)"),11,kind(11)
end program foo
Compiled with:
$ gfortran -fdefault-integer-8 -o foo.exe foo.f90
$ foo
Results in:
111111111111 correspond to kind 8
11 correspond to kind 8
So you can see the compiler is indifferent to the actual value you are testing.
However, I don't think this gets at the root of what you are trying to do, which I assume is to discover the minimum size of integer necessary for a specific numeric value. I don't know of a way to do this off hand with fortran. See this here and here for solutions you might be able to port from C. The second approach looks promising. In a dynamically typed language like Python the type assignment is handled for you.
>>> type(111111111111)
<type 'long'>
>>> type(11111)
<type 'int'>
I've been using using an underscore to define an integer as a specific kind in fortran.
Here is a snippet of code to demonstrate what 1_8 means, for example:
program main
implicit none
integer(2) :: tiny
integer(4) :: short
integer(8) :: long
tiny = 1
short = 1
long = 1
print*, huge(tiny)
print*, huge(1_2)
print*, huge(short)
print*, huge(1_4)
print*, huge(long)
print*, huge(1_8)
end program main
Which returns (with PGI or gfortran):
32767
32767
2147483647
2147483647
9223372036854775807
9223372036854775807
I'm using the huge intrinsic function to return largest number of the given kind. So 1_8 is clearly the same kind as integer(8). This works for real numbers also, although I haven't shown it here.
However, I've been unable to find any documentation of this functionality and I don't remember where I learned it. My question is:
Is using _KIND standard fortran? Does anybody have a source for this?
Edit: It's been pointed out that the kind values I've used (2,4,8) are not portable - different compilers/machines may give different values for huge(1_4), for example.
It is standard Fortran, as of Fortran 90, though the set of valid kind values for each type and the meaning of a kind value is processor dependent.
The Fortran standard is the definitive source for what is "standard" Fortran. ISO/IEC 1539-1:2010 is the current edition, which you can buy, or pre-publication drafts of that document are available from various places. https://gcc.gnu.org/wiki/GFortranStandards has a collection of useful links.
I would expect that many compiler manuals (e.g - see section 2.2 of the current PGI Fortran reference manual) and all reasonable textbooks on modern Fortran would also describe this feature.
As already answered, this notation is standard fortran, but using these specific numeric values for kinds is not portable. Previous answers have described compilers that use other schemes. There are several other approaches that are portable.
First, use the kind scheme to define symbols, then use those symbols for numeric constants:
integer, parameter :: RegInt_K = selected_int_kind (8)
write (*, *) huge (1_RegInt_K)
Or use the kind definitions that are provided in the ISO_FORTRAN_ENV module, e.g.,
write (*, *) huge (1_int32)
The kinds of this module are specified in the number of bits used for storage. Some of the kinds are only available with Fortran 2008. If those are missing in your compiler, you can use the kind definitions provided with the ISO_C_BINDING, which is older.
To add to IanH's answer the specification for an integer literal constant in Fortran 2008 is given in 4.4.2.2. Something like 1_8 fits in with R407 and R408 (for the obvious digit-string):
int-literal-constant is digit-string [_kind-param]
kind-param is digit-string or scalar-int-constant-name
You can find similar for other data types (although note that for characters the kind parameter is at the front of the literal constant).
My apologies if this is a very stupid question; my Fortran isn't great. I'm porting some old Fortran code and have come across this subroutine definition:
SUBROUTINE SET_HYDROMODULE(HYDROMODULE)
IMPLICIT NONE
INTEGER*4 HYDROMODULE [VALUE]
...
END
Intel Fortran passes this through without blinking an eye, though with warnings for non-standard language features enabled it gives this warning:
warning #7009: Attribute syntax is not standard F95
gfortran assumes that it's an attempt at a coarray specification, though it's not a valid one.
Can someone tell me what the meaning of the [VALUE] clause is?
Edit Is it a non-standard way of specifying pass-by-value? Is it equivalent to this:
INTEGER*4, VALUE :: HYDROMODULE
I seem to see it a lot in c-interoperability code, which would suggest this.
The VALUE attribute was added in Fortran 2003, so it is not surprising that it doesn't work with Fortran 95. The Fortran Standard (2008) specifies in section 5.3.18 "VALUE attribute". From what I read there, it needs to be specified as
INTEGER*4, VALUE :: HYDROMODULE
Section 5.4.16 in the Standard defines a second form, the VALUE statement:
INTEGER*4 :: HYDROMODULE
VALUE :: HYDROMODULE
The other form you gave seems to be an Intel extension. gfortran supports the VALUE attribute (at least in version 4.9).
A quick search revealed that apart from ensuring inter-operability the VALUE attribute can indeed by used to enforce some kind of call by value, from here:
When this attribute is specified, the effect is as if the actual
argument is assigned to a temporary, and the temporary is the argument
associated with the dummy argument. The actual mechanism by which this
happens is determined by the processor.