Internet has a lot of open source code written in the Fortran programming language. Sometimes the 'intrinsic' keyword can be met in a code. I saw that the 'intrinsic' keyword can be used with 'use' keyword. Here is an example:
program main
use, intrinsic :: iso_fortran_env, only : int8, int16, int32, int64
implicit none
!
! Some code
!
end program main
I would like to understand better and more correctly the purpose of the application of this keyword in this context.
Related
I have a colleague who writes Fortran, generally following the F77 standard. I have had to work with some of their source code and I find the use of implicit type declarations (not using implicit none) really confusing and frustrating. Their reason for doing so is to "eliminate all of those type declarations at the beginning of my program(s)." In my opinion, this is a poor trade off for ruining readability and comprehension of the program and its many subroutines. Are there any other, more valid, reasons for not including implicit none in Fortran programs and subroutines?
Just to be entirely clear, relying on implicit typing is frowned upon by many. With good cause. However, there is one case where where some may view implicit typing the lesser of two evils.
Implicit typing allows one to have an object which is of a type whose name is not accessible in a scope:
implicit type(badexample) (d)
type badexample
integer :: neverever=4
end type badexample
call sub
contains
subroutine reallybad(badexample)
integer, optional :: badexample
! With the declaration above we can't declare a local variable of explicit
! type badexample:
! type(badexample) dontdothis
print*, dontdothis%neverever
end subroutine reallybad
end
Really, this is a poor excuse to use implicit typing. One which can be avoided by other design choices.
Under Fortran 77, of course, one cannot use implicit none.
When your code is a stack of punch cards that must not be dropped or brought out of order, methods to reduce line count make sense. In modern time there is no reason for implicit typing.
I had an old guard colleague who could not be dissuaded from using implicit typing. He claimed that using implicit typing for most variables and explicit typing only for those few variables that don't follow Hungarian notation makes these variables stand out more and that helps him to better understand the code.
Use comments for readability. That's what they're there for.
Well, I used punch cards but I usually use implicit none in my Fortran codes as well. Much of my Fortran coding now, however, is just to write a pre-processor or post-processor of data. Things that people use python for now. I know python but my programming skills in python are not that good. So when you're writing 100-300 lines of code only the implicit none can be a pain. I use it so people won't make fun of me but for short utility codes, implicit none buys you little. imho!
What does it mean when the intrinsic keyword is added to the use statement for a module, as in the following example?
use, intrinsic :: iso_c_binding
(From
7.1 Overview of Fortran interface, FFTW 3.3.6-pl1)
Does it specify that a module of that name provided with the compiler should be used, even if there is another module of the same name written by the user?
With use, intrinsic :: ... the intrinsic module is indeed chosen.
There is perhaps a slight subtlety in the question worth addressing. With regards to "a module of that name provided with the compiler should be used", this "should" doesn't indicate a preference but a strong requirement. That is, if there's no such intrinsic module then compilation cannot succeed. This shouldn't be a problem with iso_c_binding but compilers often offer their own non-standard intrinsic modules.
There is no way to say "use the intrinsic module if it's available, but the user-provided one if not".
In the documentation of the GNU Fortran compiler, for a specific intrinsic function, there is a standard. For example, CPU_TIME is an intrinsic procedure for which it is indicated that the standard is Fortran 95 and later. My question is about the meaning of this.
I understand the Fortran standard to be like a set of rules to follow for your code to be defined as standard-compliant (to Fortran 77,90,95,2003 or 2008). Does this mean that CPU_TIME can only be used with Fortran 95+? Actually, I already know the answer, I can use CPU_TIME within a Fortran 77 file with the .f extension without the compiler to complain, compiling with a Gfortran version > 5. Is that because the compiler is able to treat any standard encountered in a code? I am aware of the -std flag but how can I be sure that for instance a Fortran 77 code uses only intrinsic procedures for Fortran 77?
Short answer, you can not distinguish standard below f95 with gnu compilers. From f95 and above, you can use the option -std to force the compiler to consider features of standard above as errors.
Long answer:
The documentation of gnu compiler says this:
-std=std
Specify the standard to which the program is expected to conform, which may be one of ‘f95’, ‘f2003’, ‘f2008’, ‘gnu’, or ‘legacy’. The
default value for std is ‘gnu’, which specifies a superset of the
Fortran 95 standard that includes all of the extensions supported by
GNU Fortran, although warnings will be given for obsolete extensions
not recommended for use in new code. The ‘legacy’ value is equivalent
but without the warnings for obsolete extensions, and may be useful
for old non-standard programs. The ‘f95’, ‘f2003’ and ‘f2008’ values
specify strict conformance to the Fortran 95, Fortran 2003 and Fortran
2008 standards, respectively; errors are given for all extensions
beyond the relevant language standard, and warnings are given for the
Fortran 77 features that are permitted but obsolescent in later
standards. ‘-std=f2008ts’ allows the Fortran 2008 standard including
the additions of the Technical Specification (TS) 29113 on Further
Interoperability of Fortran with C and TS 18508 on Additional Parallel
Features in Fortran.
- `-std=f95` will consider features above f95 as errors
- `-std=f2003` will consider features above f2003 as errors
- `-std=f2008` will consider features above f2008 as errors
- etc.
You might want to check with other compilers.
Easy verification:, compile the following program (courtesy of Fortran wiki) with and without the option -std=f95 and see what happens.
module class_Circle
implicit none
private
real :: pi = 3.1415926535897931d0 ! Class-wide private constant
type, public :: Circle
real :: radius
contains
procedure :: area => circle_area
procedure :: print => circle_print
end type Circle
contains
function circle_area(this) result(area)
class(Circle), intent(in) :: this
real :: area
area = pi * this%radius**2
end function circle_area
subroutine circle_print(this)
class(Circle), intent(in) :: this
real :: area
area = this%area() ! Call the type-bound function
print *, 'Circle: r = ', this%radius, ' area = ', area
end subroutine circle_print
end module class_Circle
program circle_test
use class_Circle
implicit none
type(Circle) :: c ! Declare a variable of type Circle.
c = Circle(1.5) ! Use the implicit constructor, radius = 1.5.
call c%print ! Call the type-bound subroutine
end program circle_test
I've written a scientific fortran code without using any specific fortran standard. But I have now to declare which fortran standard I'm using.
I said I'm using fortran 2003 because I need the get_command_argument and command_argument_count intrinsic functions. However when using the flag -std=f2003 to check the code standards the compilation fails.
I get errors concerning the type declaration of reals in some parts. For example when I declare variables in the module:
module innout
implicit none
real*8,parameter :: nan=-1.
real*8,allocatable,save :: windU(:),windV(:)
real*8,allocatable,save :: input_param(:,:),input_rad(:,:)
real*8,allocatable,save :: prein(:),input(:),ref_lev(:)
character(30),allocatable,save :: sceneclass(:)
end module innout
I get the messages "Nonstandard type declaration REAL*8" in all real variables.
Anyone knows what's happening?
real*8 is not, and never has been, a Fortran-standard type declaration. These days the simplest approach to declaring a 64-bit real is probably to import the named-constant real64 from the intrinsic module iso_fortan_env, like this:
use, intrinsic :: iso_fortran_env
...
real(real64) :: my_var
There are other ways, involving selected_real_kind and other mechanisms, but if you want to program with IEEE floating-point types then real64 and real32 are a good way to go.
As #AlexanderVogt has pointed out in a comment these standard named constants were added to the language in the 2008 standard. Most recent compiler versions I have worked with already implement them.
The kind specifier is the way to go...
If you limit yourself to Fortran 2003 Standard, then you need to use the kind() or selected_real_kind() function to determine the corresponding kind first:
module innout
implicit none
integer,parameter :: REAL64 = kind(1.d0)
real(kind=REAL64),parameter :: nan=-1._REAL64
real(kind=REAL64),allocatable,save :: windU(:),windV(:)
real(kind=REAL64),allocatable,save :: input_param(:,:),input_rad(:,:)
real(kind=REAL64),allocatable,save :: prein(:),input(:),ref_lev(:)
character(30),allocatable,save :: sceneclass(:)
end module innout
If you are allowed to/your compiler supports Fortran 2008, I would recommend the module ISO_Fortran_env and the pre-defined constant REAL64:
module innout
use,intrinsic :: ISO_Fortran_env, only: REAL64
implicit none
real(kind=REAL64),parameter :: nan=-1._REAL64
real(kind=REAL64),allocatable,save :: windU(:),windV(:)
real(kind=REAL64),allocatable,save :: input_param(:,:),input_rad(:,:)
real(kind=REAL64),allocatable,save :: prein(:),input(:),ref_lev(:)
character(30),allocatable,save :: sceneclass(:)
end module innout
I found already the answer.
Using the following in the variable declaration, it seems to work fine:
integer, parameter :: dp = selected_real_kind(15, 307)
From http://fortranwiki.org/fortran/show/Real+precision
The source code I am working with was originally written for the Intel Fortran compiler so it has preprocessor directives such as
!DEC$ATTRIBUTES DLLEXPORT::MYDLL
!DEC$ATTRIBUTES STDCALL::MYSUBROUTINE
!DEC$ATTRIBUTES ALIAS: 'MYENTRYPOINT'::MYSUBROUTINE
How do I convert this to work with gfortran.
Mainly I want to be able to define and name entry points. Right now when I compile with gfortran every subroutine gets exposed as an entry point. Also the entry point name are all lower case with a underscore at the end.
If you place your routines into a module and put the statement PRIVATE at the top of the module, then PUBLIC :: name1, name2, only the procedures name1 and name2 will be visible outside of the module. This should follow through to a library into which you place object code containing the module. This has been supported since Fortran 90.
As already answered by #janneb, you can use the bind (C,name=X) approach to take complete control of the externally visible name of a procedure, overriding the Fortran name of the procedure. This is part of Fortran 2003 and is supported by numerous compilers for years. A possible issue with the bind(C) approach that it specifies that the calling convention of the routine should be that of C. If this is different from that Fortran and you wish to call these routines from Fortran the complexity increases. Then you would have to specify an interface to inform the calling Fortran routines that they are calling what looks like a C routine. Since people rarely care about the name visible to the linker unless they are calling from C, you might want the C calling convention?
Examples at Private function in Fortran and C/C++, FORTRAN, underscores, and GNU Autotools
GFortran supports some attributes, see
http://gcc.gnu.org/onlinedocs/gfortran/GNU-Fortran-Compiler-Directives.html#GNU-Fortran-Compiler-Directives
For changing the symbol name, you can use the bind(C, name=) specifier of ISO_C_BINDING, see e.g.
http://gcc.gnu.org/onlinedocs/gfortran/Interoperable-Subroutines-and-Functions.html#Interoperable-Subroutines-and-Functions
http://gcc.gnu.org/onlinedocs/gfortran/Interoperable-Global-Variables.html#Interoperable-Global-Variables