Why do I have to specify implicitly for a double precision return value of a function in Fortran?
I am new to Fortran and I am trying on the common
block. My code is simple
program main
implicit double precision (p)
real * 8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end program main
function power(x)
implicit none
real * 8 :: power
real * 8 :: x, y
common /yvalue/ y
power = x ** y
end function power
It works but if I comment out the second line, which implicitly declares variables starting with p
to be double precision, the compiler complains the following
Error: Return type mismatch of function ‘power’ at (1) (REAL(4)/REAL(8))
I do get the point that the return value power
is by default a single precision variable, but why declaring power
as double precision in the function is not enough? And why writing real * 8 power
in main
would not work either?
fortran precision fortran90
|
show 1 more comment
I am new to Fortran and I am trying on the common
block. My code is simple
program main
implicit double precision (p)
real * 8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end program main
function power(x)
implicit none
real * 8 :: power
real * 8 :: x, y
common /yvalue/ y
power = x ** y
end function power
It works but if I comment out the second line, which implicitly declares variables starting with p
to be double precision, the compiler complains the following
Error: Return type mismatch of function ‘power’ at (1) (REAL(4)/REAL(8))
I do get the point that the return value power
is by default a single precision variable, but why declaring power
as double precision in the function is not enough? And why writing real * 8 power
in main
would not work either?
fortran precision fortran90
3
Explicitly declaringpower
to bereal*8
in the main works for me. Since you are learning Fortran I would advise you to steer well clear of "features" likeCOMMON
, implicit delarations andreal*8
.
– RussF
Nov 22 '18 at 6:09
3
Note real*8 is not part of standard Fortran, has never been part of standard Fortran, and if that is what you are being talught I worry about the quality of the rest of the teaching - especially if it is covering common and implicit typing as well, things that shouldn't have been used for 25 years. Learn instead about Fortran's kind mechansim
– Ian Bush
Nov 22 '18 at 6:52
2
To reinforce what @RussF has already advised: if you are new to Fortran don't learn about common blocks. Your first contact with them should come when you start to modify old codes.
– High Performance Mark
Nov 22 '18 at 8:21
1
Mixing real data type widths between caller and callee "worked" for a long time on 387 architecture and may still do so in non-sse mode with common 32-bit compilers, as the value would be returned and consumed from the same 387 stack register, and some compilers didn't check this. With an explicit interface (as advised below), a single declaration seen by both caller and callee could do the job. The undeclared type mixing is unlikely to "work" for the function arguments and cannot work for COMMON.
– tim18
Nov 22 '18 at 10:29
1
Old codes are NOT a good place to learn Fortran, unless you have a one-off task to modify some legacy thing and move on to a different language.
– Vladimir F
Nov 24 '18 at 11:06
|
show 1 more comment
I am new to Fortran and I am trying on the common
block. My code is simple
program main
implicit double precision (p)
real * 8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end program main
function power(x)
implicit none
real * 8 :: power
real * 8 :: x, y
common /yvalue/ y
power = x ** y
end function power
It works but if I comment out the second line, which implicitly declares variables starting with p
to be double precision, the compiler complains the following
Error: Return type mismatch of function ‘power’ at (1) (REAL(4)/REAL(8))
I do get the point that the return value power
is by default a single precision variable, but why declaring power
as double precision in the function is not enough? And why writing real * 8 power
in main
would not work either?
fortran precision fortran90
I am new to Fortran and I am trying on the common
block. My code is simple
program main
implicit double precision (p)
real * 8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end program main
function power(x)
implicit none
real * 8 :: power
real * 8 :: x, y
common /yvalue/ y
power = x ** y
end function power
It works but if I comment out the second line, which implicitly declares variables starting with p
to be double precision, the compiler complains the following
Error: Return type mismatch of function ‘power’ at (1) (REAL(4)/REAL(8))
I do get the point that the return value power
is by default a single precision variable, but why declaring power
as double precision in the function is not enough? And why writing real * 8 power
in main
would not work either?
fortran precision fortran90
fortran precision fortran90
asked Nov 22 '18 at 4:14


zyyzyy
1548
1548
3
Explicitly declaringpower
to bereal*8
in the main works for me. Since you are learning Fortran I would advise you to steer well clear of "features" likeCOMMON
, implicit delarations andreal*8
.
– RussF
Nov 22 '18 at 6:09
3
Note real*8 is not part of standard Fortran, has never been part of standard Fortran, and if that is what you are being talught I worry about the quality of the rest of the teaching - especially if it is covering common and implicit typing as well, things that shouldn't have been used for 25 years. Learn instead about Fortran's kind mechansim
– Ian Bush
Nov 22 '18 at 6:52
2
To reinforce what @RussF has already advised: if you are new to Fortran don't learn about common blocks. Your first contact with them should come when you start to modify old codes.
– High Performance Mark
Nov 22 '18 at 8:21
1
Mixing real data type widths between caller and callee "worked" for a long time on 387 architecture and may still do so in non-sse mode with common 32-bit compilers, as the value would be returned and consumed from the same 387 stack register, and some compilers didn't check this. With an explicit interface (as advised below), a single declaration seen by both caller and callee could do the job. The undeclared type mixing is unlikely to "work" for the function arguments and cannot work for COMMON.
– tim18
Nov 22 '18 at 10:29
1
Old codes are NOT a good place to learn Fortran, unless you have a one-off task to modify some legacy thing and move on to a different language.
– Vladimir F
Nov 24 '18 at 11:06
|
show 1 more comment
3
Explicitly declaringpower
to bereal*8
in the main works for me. Since you are learning Fortran I would advise you to steer well clear of "features" likeCOMMON
, implicit delarations andreal*8
.
– RussF
Nov 22 '18 at 6:09
3
Note real*8 is not part of standard Fortran, has never been part of standard Fortran, and if that is what you are being talught I worry about the quality of the rest of the teaching - especially if it is covering common and implicit typing as well, things that shouldn't have been used for 25 years. Learn instead about Fortran's kind mechansim
– Ian Bush
Nov 22 '18 at 6:52
2
To reinforce what @RussF has already advised: if you are new to Fortran don't learn about common blocks. Your first contact with them should come when you start to modify old codes.
– High Performance Mark
Nov 22 '18 at 8:21
1
Mixing real data type widths between caller and callee "worked" for a long time on 387 architecture and may still do so in non-sse mode with common 32-bit compilers, as the value would be returned and consumed from the same 387 stack register, and some compilers didn't check this. With an explicit interface (as advised below), a single declaration seen by both caller and callee could do the job. The undeclared type mixing is unlikely to "work" for the function arguments and cannot work for COMMON.
– tim18
Nov 22 '18 at 10:29
1
Old codes are NOT a good place to learn Fortran, unless you have a one-off task to modify some legacy thing and move on to a different language.
– Vladimir F
Nov 24 '18 at 11:06
3
3
Explicitly declaring
power
to be real*8
in the main works for me. Since you are learning Fortran I would advise you to steer well clear of "features" like COMMON
, implicit delarations and real*8
.– RussF
Nov 22 '18 at 6:09
Explicitly declaring
power
to be real*8
in the main works for me. Since you are learning Fortran I would advise you to steer well clear of "features" like COMMON
, implicit delarations and real*8
.– RussF
Nov 22 '18 at 6:09
3
3
Note real*8 is not part of standard Fortran, has never been part of standard Fortran, and if that is what you are being talught I worry about the quality of the rest of the teaching - especially if it is covering common and implicit typing as well, things that shouldn't have been used for 25 years. Learn instead about Fortran's kind mechansim
– Ian Bush
Nov 22 '18 at 6:52
Note real*8 is not part of standard Fortran, has never been part of standard Fortran, and if that is what you are being talught I worry about the quality of the rest of the teaching - especially if it is covering common and implicit typing as well, things that shouldn't have been used for 25 years. Learn instead about Fortran's kind mechansim
– Ian Bush
Nov 22 '18 at 6:52
2
2
To reinforce what @RussF has already advised: if you are new to Fortran don't learn about common blocks. Your first contact with them should come when you start to modify old codes.
– High Performance Mark
Nov 22 '18 at 8:21
To reinforce what @RussF has already advised: if you are new to Fortran don't learn about common blocks. Your first contact with them should come when you start to modify old codes.
– High Performance Mark
Nov 22 '18 at 8:21
1
1
Mixing real data type widths between caller and callee "worked" for a long time on 387 architecture and may still do so in non-sse mode with common 32-bit compilers, as the value would be returned and consumed from the same 387 stack register, and some compilers didn't check this. With an explicit interface (as advised below), a single declaration seen by both caller and callee could do the job. The undeclared type mixing is unlikely to "work" for the function arguments and cannot work for COMMON.
– tim18
Nov 22 '18 at 10:29
Mixing real data type widths between caller and callee "worked" for a long time on 387 architecture and may still do so in non-sse mode with common 32-bit compilers, as the value would be returned and consumed from the same 387 stack register, and some compilers didn't check this. With an explicit interface (as advised below), a single declaration seen by both caller and callee could do the job. The undeclared type mixing is unlikely to "work" for the function arguments and cannot work for COMMON.
– tim18
Nov 22 '18 at 10:29
1
1
Old codes are NOT a good place to learn Fortran, unless you have a one-off task to modify some legacy thing and move on to a different language.
– Vladimir F
Nov 24 '18 at 11:06
Old codes are NOT a good place to learn Fortran, unless you have a one-off task to modify some legacy thing and move on to a different language.
– Vladimir F
Nov 24 '18 at 11:06
|
show 1 more comment
2 Answers
2
active
oldest
votes
When a procedure (function or subroutine) that you are trying to invoke in your code lays outside the body of your program
and also is not part of any module
, it's named an external function (or subroutine).
Fortran is a statically-typed language, so the types of all variables and functions must be known at compile-time. So, if you want to reference an external function in your program, there must be a way for the program to know its return type. You have 3 (bad) options for this, and I'll list them, starting from the worst:
WORST: Rely on an implicit-typing rule that happens to match the return type of the external function with the type associated with its identifier in the caller (as you did in your sample).
Why you shouldn't do that? Because it is cancer. It makes the meaning of the code obscure, you can't know what this name reference to. It may even look just like an array variable in some circumstances, instead of a function. Also, the compiler doesn't check argument conformance in this case, so if you don't have specific compiler options turned on, the code will fail at runtime, or worse, will give wrong results. Moreover, implicit-typing is very very rarely useful these days, most of the time it's an ask for trouble. Always use implicit none
!
As you noted, by the default rules of implicit-typing, any variable with a name starting with p
will be default real
type (in your compiler, it is real(4)
). As you declared the function result as real*8
, that your compiler interpret as real(8)
(see final note), the error arises.
BAD: Declare the function's name and type in the caller's specification area.
You'd do that just like you'd declare a variable, like this:
program main
implicit none
real*8 :: x, y, power
By the way, the attribute external
may be applied to external procedures like yours. More than giving some properties to the procedure (can be passed as an actual argument, disambiguation from intrinsic procedures), it would make the origin of the identifier clearer.
program main
implicit none
real*8 :: x, y, power
external :: power
Why you shouldn't do that? There is no argument checking by the compiler either. This severely limits your options for communicating to external functions: the arguments cannot be assumed-shape, assumed-rank, polymorphic, parameterized, coarray, or be declared on the callee side as allocatable
, optional
, pointer
, target
, asynchronous
, volatile
or value
; the return type cannot be an array, or pointer, or allocatable; the function cannot be passed as argument, be elemental
and, if pure
, can't be used in such contexts. And the reason for all this is the lack of an explicit interface.
ACCEPTABLE: Specify aninterface
for your external function in the caller.
Like this:
program main
implicit none
interface
real*8 function power(y)
real*8 :: y
end function
end interface
This way, the compiler is able to know all details of declaration and all the restrictions I mentioned won't apply. Total freedom and code clarity!
Why you shouldn't do that? Because there is a better way, that is using modules
! Well, it's totally ok to do this in contexts were you can't go for modules, e.g. when working with already existent large old code. The downside is that, you have almost the same code in two different places, and they must always match.
Bonus: BETTER: Use modules.
program main
use :: aux_module
implicit none
real*8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
contains
function power(x)
real*8 :: power
real*8 :: x, y
common /yvalue/ y
power = x ** y
end
end
Why you should definitely do that? Because with modules, interfaces are automatically and implicitly available (less code duplication, no restrictions); modules can be recompiled separately and updated without breaking code. Also, you can declare shared variables in the scope of the module and avoid using common
declarations. An even better version of your code would be:
program main
use aux_module
implicit none
real*8 :: x
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
real*8 :: y
contains
function power(x)
real*8 :: power
real*8 :: x
power = x ** y
end
end
There is even the option to include your functions directly into your program
, after contains
. This is recommended only if you don't plan to reuse this function in other program units. @IanBush's answer covers this case.
Final note: take a look on this answer to see why the syntax real*8
is non-standard and should be avoided.
I had this weird problem ofno such file or directory
when compiling your code withmodule
. The problem is solved after I move the module you defined up to the front ofmain
. How could I make this module usable even if I define it aftermain
?
– zyy
Nov 22 '18 at 15:26
1
you can have them in separate files and order them for compile, manually or through a makefile. Or, you can compile the modules separately and only link the module-objects when compiling the main program
– Rodrigo Rodrigues
Nov 23 '18 at 0:15
@zzy strictly speaking you can't. The module must be compiled first, before the main program. You can do that by moving it before the main or by compiling it first in a different file.
– Vladimir F
Nov 24 '18 at 11:09
add a comment |
As stated in the comments simply declaring the function in not only its own scope but also the scope that it is called will solve your problem. However I also want to discourage you from using common, implicit typing, and the completely non-standard real*8. As such here is a version of your program in a more modern dialect
ian@eris:~/work/stackoverflow$ cat power.f90
Program power_program
Implicit None
Integer, Parameter :: wp = Selected_real_kind( 14, 70 )
Real( wp ) :: x, y
x = 3.0_wp
y = 3.0_wp
! Return type and kind of the function power in scope
! due to the implicit interface
Write( *, '( 3( a, 1x, f0.6, 1x ) )' ) &
'x =', x, 'y = ', y, 'x**y = ', power( x, y )
Contains
Pure Function power( x, y ) Result( r )
Real( wp ) :: r
Real( wp ), Intent( In ) :: x
Real( wp ), Intent( In ) :: y
r = x ** y
End Function power
End Program power_program
ian@eris:~/work/stackoverflow$ gfortran -std=f2003 -Wall -Wextra -O power.f90
ian@eris:~/work/stackoverflow$ ./a.out
x = 3.000000 y = 3.000000 x**y = 27.000000
ian@eris:~/work/stackoverflow$
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53423806%2fwhy-do-i-have-to-specify-implicitly-for-a-double-precision-return-value-of-a-fun%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
When a procedure (function or subroutine) that you are trying to invoke in your code lays outside the body of your program
and also is not part of any module
, it's named an external function (or subroutine).
Fortran is a statically-typed language, so the types of all variables and functions must be known at compile-time. So, if you want to reference an external function in your program, there must be a way for the program to know its return type. You have 3 (bad) options for this, and I'll list them, starting from the worst:
WORST: Rely on an implicit-typing rule that happens to match the return type of the external function with the type associated with its identifier in the caller (as you did in your sample).
Why you shouldn't do that? Because it is cancer. It makes the meaning of the code obscure, you can't know what this name reference to. It may even look just like an array variable in some circumstances, instead of a function. Also, the compiler doesn't check argument conformance in this case, so if you don't have specific compiler options turned on, the code will fail at runtime, or worse, will give wrong results. Moreover, implicit-typing is very very rarely useful these days, most of the time it's an ask for trouble. Always use implicit none
!
As you noted, by the default rules of implicit-typing, any variable with a name starting with p
will be default real
type (in your compiler, it is real(4)
). As you declared the function result as real*8
, that your compiler interpret as real(8)
(see final note), the error arises.
BAD: Declare the function's name and type in the caller's specification area.
You'd do that just like you'd declare a variable, like this:
program main
implicit none
real*8 :: x, y, power
By the way, the attribute external
may be applied to external procedures like yours. More than giving some properties to the procedure (can be passed as an actual argument, disambiguation from intrinsic procedures), it would make the origin of the identifier clearer.
program main
implicit none
real*8 :: x, y, power
external :: power
Why you shouldn't do that? There is no argument checking by the compiler either. This severely limits your options for communicating to external functions: the arguments cannot be assumed-shape, assumed-rank, polymorphic, parameterized, coarray, or be declared on the callee side as allocatable
, optional
, pointer
, target
, asynchronous
, volatile
or value
; the return type cannot be an array, or pointer, or allocatable; the function cannot be passed as argument, be elemental
and, if pure
, can't be used in such contexts. And the reason for all this is the lack of an explicit interface.
ACCEPTABLE: Specify aninterface
for your external function in the caller.
Like this:
program main
implicit none
interface
real*8 function power(y)
real*8 :: y
end function
end interface
This way, the compiler is able to know all details of declaration and all the restrictions I mentioned won't apply. Total freedom and code clarity!
Why you shouldn't do that? Because there is a better way, that is using modules
! Well, it's totally ok to do this in contexts were you can't go for modules, e.g. when working with already existent large old code. The downside is that, you have almost the same code in two different places, and they must always match.
Bonus: BETTER: Use modules.
program main
use :: aux_module
implicit none
real*8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
contains
function power(x)
real*8 :: power
real*8 :: x, y
common /yvalue/ y
power = x ** y
end
end
Why you should definitely do that? Because with modules, interfaces are automatically and implicitly available (less code duplication, no restrictions); modules can be recompiled separately and updated without breaking code. Also, you can declare shared variables in the scope of the module and avoid using common
declarations. An even better version of your code would be:
program main
use aux_module
implicit none
real*8 :: x
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
real*8 :: y
contains
function power(x)
real*8 :: power
real*8 :: x
power = x ** y
end
end
There is even the option to include your functions directly into your program
, after contains
. This is recommended only if you don't plan to reuse this function in other program units. @IanBush's answer covers this case.
Final note: take a look on this answer to see why the syntax real*8
is non-standard and should be avoided.
I had this weird problem ofno such file or directory
when compiling your code withmodule
. The problem is solved after I move the module you defined up to the front ofmain
. How could I make this module usable even if I define it aftermain
?
– zyy
Nov 22 '18 at 15:26
1
you can have them in separate files and order them for compile, manually or through a makefile. Or, you can compile the modules separately and only link the module-objects when compiling the main program
– Rodrigo Rodrigues
Nov 23 '18 at 0:15
@zzy strictly speaking you can't. The module must be compiled first, before the main program. You can do that by moving it before the main or by compiling it first in a different file.
– Vladimir F
Nov 24 '18 at 11:09
add a comment |
When a procedure (function or subroutine) that you are trying to invoke in your code lays outside the body of your program
and also is not part of any module
, it's named an external function (or subroutine).
Fortran is a statically-typed language, so the types of all variables and functions must be known at compile-time. So, if you want to reference an external function in your program, there must be a way for the program to know its return type. You have 3 (bad) options for this, and I'll list them, starting from the worst:
WORST: Rely on an implicit-typing rule that happens to match the return type of the external function with the type associated with its identifier in the caller (as you did in your sample).
Why you shouldn't do that? Because it is cancer. It makes the meaning of the code obscure, you can't know what this name reference to. It may even look just like an array variable in some circumstances, instead of a function. Also, the compiler doesn't check argument conformance in this case, so if you don't have specific compiler options turned on, the code will fail at runtime, or worse, will give wrong results. Moreover, implicit-typing is very very rarely useful these days, most of the time it's an ask for trouble. Always use implicit none
!
As you noted, by the default rules of implicit-typing, any variable with a name starting with p
will be default real
type (in your compiler, it is real(4)
). As you declared the function result as real*8
, that your compiler interpret as real(8)
(see final note), the error arises.
BAD: Declare the function's name and type in the caller's specification area.
You'd do that just like you'd declare a variable, like this:
program main
implicit none
real*8 :: x, y, power
By the way, the attribute external
may be applied to external procedures like yours. More than giving some properties to the procedure (can be passed as an actual argument, disambiguation from intrinsic procedures), it would make the origin of the identifier clearer.
program main
implicit none
real*8 :: x, y, power
external :: power
Why you shouldn't do that? There is no argument checking by the compiler either. This severely limits your options for communicating to external functions: the arguments cannot be assumed-shape, assumed-rank, polymorphic, parameterized, coarray, or be declared on the callee side as allocatable
, optional
, pointer
, target
, asynchronous
, volatile
or value
; the return type cannot be an array, or pointer, or allocatable; the function cannot be passed as argument, be elemental
and, if pure
, can't be used in such contexts. And the reason for all this is the lack of an explicit interface.
ACCEPTABLE: Specify aninterface
for your external function in the caller.
Like this:
program main
implicit none
interface
real*8 function power(y)
real*8 :: y
end function
end interface
This way, the compiler is able to know all details of declaration and all the restrictions I mentioned won't apply. Total freedom and code clarity!
Why you shouldn't do that? Because there is a better way, that is using modules
! Well, it's totally ok to do this in contexts were you can't go for modules, e.g. when working with already existent large old code. The downside is that, you have almost the same code in two different places, and they must always match.
Bonus: BETTER: Use modules.
program main
use :: aux_module
implicit none
real*8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
contains
function power(x)
real*8 :: power
real*8 :: x, y
common /yvalue/ y
power = x ** y
end
end
Why you should definitely do that? Because with modules, interfaces are automatically and implicitly available (less code duplication, no restrictions); modules can be recompiled separately and updated without breaking code. Also, you can declare shared variables in the scope of the module and avoid using common
declarations. An even better version of your code would be:
program main
use aux_module
implicit none
real*8 :: x
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
real*8 :: y
contains
function power(x)
real*8 :: power
real*8 :: x
power = x ** y
end
end
There is even the option to include your functions directly into your program
, after contains
. This is recommended only if you don't plan to reuse this function in other program units. @IanBush's answer covers this case.
Final note: take a look on this answer to see why the syntax real*8
is non-standard and should be avoided.
I had this weird problem ofno such file or directory
when compiling your code withmodule
. The problem is solved after I move the module you defined up to the front ofmain
. How could I make this module usable even if I define it aftermain
?
– zyy
Nov 22 '18 at 15:26
1
you can have them in separate files and order them for compile, manually or through a makefile. Or, you can compile the modules separately and only link the module-objects when compiling the main program
– Rodrigo Rodrigues
Nov 23 '18 at 0:15
@zzy strictly speaking you can't. The module must be compiled first, before the main program. You can do that by moving it before the main or by compiling it first in a different file.
– Vladimir F
Nov 24 '18 at 11:09
add a comment |
When a procedure (function or subroutine) that you are trying to invoke in your code lays outside the body of your program
and also is not part of any module
, it's named an external function (or subroutine).
Fortran is a statically-typed language, so the types of all variables and functions must be known at compile-time. So, if you want to reference an external function in your program, there must be a way for the program to know its return type. You have 3 (bad) options for this, and I'll list them, starting from the worst:
WORST: Rely on an implicit-typing rule that happens to match the return type of the external function with the type associated with its identifier in the caller (as you did in your sample).
Why you shouldn't do that? Because it is cancer. It makes the meaning of the code obscure, you can't know what this name reference to. It may even look just like an array variable in some circumstances, instead of a function. Also, the compiler doesn't check argument conformance in this case, so if you don't have specific compiler options turned on, the code will fail at runtime, or worse, will give wrong results. Moreover, implicit-typing is very very rarely useful these days, most of the time it's an ask for trouble. Always use implicit none
!
As you noted, by the default rules of implicit-typing, any variable with a name starting with p
will be default real
type (in your compiler, it is real(4)
). As you declared the function result as real*8
, that your compiler interpret as real(8)
(see final note), the error arises.
BAD: Declare the function's name and type in the caller's specification area.
You'd do that just like you'd declare a variable, like this:
program main
implicit none
real*8 :: x, y, power
By the way, the attribute external
may be applied to external procedures like yours. More than giving some properties to the procedure (can be passed as an actual argument, disambiguation from intrinsic procedures), it would make the origin of the identifier clearer.
program main
implicit none
real*8 :: x, y, power
external :: power
Why you shouldn't do that? There is no argument checking by the compiler either. This severely limits your options for communicating to external functions: the arguments cannot be assumed-shape, assumed-rank, polymorphic, parameterized, coarray, or be declared on the callee side as allocatable
, optional
, pointer
, target
, asynchronous
, volatile
or value
; the return type cannot be an array, or pointer, or allocatable; the function cannot be passed as argument, be elemental
and, if pure
, can't be used in such contexts. And the reason for all this is the lack of an explicit interface.
ACCEPTABLE: Specify aninterface
for your external function in the caller.
Like this:
program main
implicit none
interface
real*8 function power(y)
real*8 :: y
end function
end interface
This way, the compiler is able to know all details of declaration and all the restrictions I mentioned won't apply. Total freedom and code clarity!
Why you shouldn't do that? Because there is a better way, that is using modules
! Well, it's totally ok to do this in contexts were you can't go for modules, e.g. when working with already existent large old code. The downside is that, you have almost the same code in two different places, and they must always match.
Bonus: BETTER: Use modules.
program main
use :: aux_module
implicit none
real*8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
contains
function power(x)
real*8 :: power
real*8 :: x, y
common /yvalue/ y
power = x ** y
end
end
Why you should definitely do that? Because with modules, interfaces are automatically and implicitly available (less code duplication, no restrictions); modules can be recompiled separately and updated without breaking code. Also, you can declare shared variables in the scope of the module and avoid using common
declarations. An even better version of your code would be:
program main
use aux_module
implicit none
real*8 :: x
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
real*8 :: y
contains
function power(x)
real*8 :: power
real*8 :: x
power = x ** y
end
end
There is even the option to include your functions directly into your program
, after contains
. This is recommended only if you don't plan to reuse this function in other program units. @IanBush's answer covers this case.
Final note: take a look on this answer to see why the syntax real*8
is non-standard and should be avoided.
When a procedure (function or subroutine) that you are trying to invoke in your code lays outside the body of your program
and also is not part of any module
, it's named an external function (or subroutine).
Fortran is a statically-typed language, so the types of all variables and functions must be known at compile-time. So, if you want to reference an external function in your program, there must be a way for the program to know its return type. You have 3 (bad) options for this, and I'll list them, starting from the worst:
WORST: Rely on an implicit-typing rule that happens to match the return type of the external function with the type associated with its identifier in the caller (as you did in your sample).
Why you shouldn't do that? Because it is cancer. It makes the meaning of the code obscure, you can't know what this name reference to. It may even look just like an array variable in some circumstances, instead of a function. Also, the compiler doesn't check argument conformance in this case, so if you don't have specific compiler options turned on, the code will fail at runtime, or worse, will give wrong results. Moreover, implicit-typing is very very rarely useful these days, most of the time it's an ask for trouble. Always use implicit none
!
As you noted, by the default rules of implicit-typing, any variable with a name starting with p
will be default real
type (in your compiler, it is real(4)
). As you declared the function result as real*8
, that your compiler interpret as real(8)
(see final note), the error arises.
BAD: Declare the function's name and type in the caller's specification area.
You'd do that just like you'd declare a variable, like this:
program main
implicit none
real*8 :: x, y, power
By the way, the attribute external
may be applied to external procedures like yours. More than giving some properties to the procedure (can be passed as an actual argument, disambiguation from intrinsic procedures), it would make the origin of the identifier clearer.
program main
implicit none
real*8 :: x, y, power
external :: power
Why you shouldn't do that? There is no argument checking by the compiler either. This severely limits your options for communicating to external functions: the arguments cannot be assumed-shape, assumed-rank, polymorphic, parameterized, coarray, or be declared on the callee side as allocatable
, optional
, pointer
, target
, asynchronous
, volatile
or value
; the return type cannot be an array, or pointer, or allocatable; the function cannot be passed as argument, be elemental
and, if pure
, can't be used in such contexts. And the reason for all this is the lack of an explicit interface.
ACCEPTABLE: Specify aninterface
for your external function in the caller.
Like this:
program main
implicit none
interface
real*8 function power(y)
real*8 :: y
end function
end interface
This way, the compiler is able to know all details of declaration and all the restrictions I mentioned won't apply. Total freedom and code clarity!
Why you shouldn't do that? Because there is a better way, that is using modules
! Well, it's totally ok to do this in contexts were you can't go for modules, e.g. when working with already existent large old code. The downside is that, you have almost the same code in two different places, and they must always match.
Bonus: BETTER: Use modules.
program main
use :: aux_module
implicit none
real*8 :: x, y
common /yvalue/ y
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
contains
function power(x)
real*8 :: power
real*8 :: x, y
common /yvalue/ y
power = x ** y
end
end
Why you should definitely do that? Because with modules, interfaces are automatically and implicitly available (less code duplication, no restrictions); modules can be recompiled separately and updated without breaking code. Also, you can declare shared variables in the scope of the module and avoid using common
declarations. An even better version of your code would be:
program main
use aux_module
implicit none
real*8 :: x
x = 3d0
y = 3d0
print *, power(x)
end
module aux_module
implicit none
real*8 :: y
contains
function power(x)
real*8 :: power
real*8 :: x
power = x ** y
end
end
There is even the option to include your functions directly into your program
, after contains
. This is recommended only if you don't plan to reuse this function in other program units. @IanBush's answer covers this case.
Final note: take a look on this answer to see why the syntax real*8
is non-standard and should be avoided.
edited Nov 22 '18 at 9:13
answered Nov 22 '18 at 7:40
Rodrigo RodriguesRodrigo Rodrigues
3,1521721
3,1521721
I had this weird problem ofno such file or directory
when compiling your code withmodule
. The problem is solved after I move the module you defined up to the front ofmain
. How could I make this module usable even if I define it aftermain
?
– zyy
Nov 22 '18 at 15:26
1
you can have them in separate files and order them for compile, manually or through a makefile. Or, you can compile the modules separately and only link the module-objects when compiling the main program
– Rodrigo Rodrigues
Nov 23 '18 at 0:15
@zzy strictly speaking you can't. The module must be compiled first, before the main program. You can do that by moving it before the main or by compiling it first in a different file.
– Vladimir F
Nov 24 '18 at 11:09
add a comment |
I had this weird problem ofno such file or directory
when compiling your code withmodule
. The problem is solved after I move the module you defined up to the front ofmain
. How could I make this module usable even if I define it aftermain
?
– zyy
Nov 22 '18 at 15:26
1
you can have them in separate files and order them for compile, manually or through a makefile. Or, you can compile the modules separately and only link the module-objects when compiling the main program
– Rodrigo Rodrigues
Nov 23 '18 at 0:15
@zzy strictly speaking you can't. The module must be compiled first, before the main program. You can do that by moving it before the main or by compiling it first in a different file.
– Vladimir F
Nov 24 '18 at 11:09
I had this weird problem of
no such file or directory
when compiling your code with module
. The problem is solved after I move the module you defined up to the front of main
. How could I make this module usable even if I define it after main
?– zyy
Nov 22 '18 at 15:26
I had this weird problem of
no such file or directory
when compiling your code with module
. The problem is solved after I move the module you defined up to the front of main
. How could I make this module usable even if I define it after main
?– zyy
Nov 22 '18 at 15:26
1
1
you can have them in separate files and order them for compile, manually or through a makefile. Or, you can compile the modules separately and only link the module-objects when compiling the main program
– Rodrigo Rodrigues
Nov 23 '18 at 0:15
you can have them in separate files and order them for compile, manually or through a makefile. Or, you can compile the modules separately and only link the module-objects when compiling the main program
– Rodrigo Rodrigues
Nov 23 '18 at 0:15
@zzy strictly speaking you can't. The module must be compiled first, before the main program. You can do that by moving it before the main or by compiling it first in a different file.
– Vladimir F
Nov 24 '18 at 11:09
@zzy strictly speaking you can't. The module must be compiled first, before the main program. You can do that by moving it before the main or by compiling it first in a different file.
– Vladimir F
Nov 24 '18 at 11:09
add a comment |
As stated in the comments simply declaring the function in not only its own scope but also the scope that it is called will solve your problem. However I also want to discourage you from using common, implicit typing, and the completely non-standard real*8. As such here is a version of your program in a more modern dialect
ian@eris:~/work/stackoverflow$ cat power.f90
Program power_program
Implicit None
Integer, Parameter :: wp = Selected_real_kind( 14, 70 )
Real( wp ) :: x, y
x = 3.0_wp
y = 3.0_wp
! Return type and kind of the function power in scope
! due to the implicit interface
Write( *, '( 3( a, 1x, f0.6, 1x ) )' ) &
'x =', x, 'y = ', y, 'x**y = ', power( x, y )
Contains
Pure Function power( x, y ) Result( r )
Real( wp ) :: r
Real( wp ), Intent( In ) :: x
Real( wp ), Intent( In ) :: y
r = x ** y
End Function power
End Program power_program
ian@eris:~/work/stackoverflow$ gfortran -std=f2003 -Wall -Wextra -O power.f90
ian@eris:~/work/stackoverflow$ ./a.out
x = 3.000000 y = 3.000000 x**y = 27.000000
ian@eris:~/work/stackoverflow$
add a comment |
As stated in the comments simply declaring the function in not only its own scope but also the scope that it is called will solve your problem. However I also want to discourage you from using common, implicit typing, and the completely non-standard real*8. As such here is a version of your program in a more modern dialect
ian@eris:~/work/stackoverflow$ cat power.f90
Program power_program
Implicit None
Integer, Parameter :: wp = Selected_real_kind( 14, 70 )
Real( wp ) :: x, y
x = 3.0_wp
y = 3.0_wp
! Return type and kind of the function power in scope
! due to the implicit interface
Write( *, '( 3( a, 1x, f0.6, 1x ) )' ) &
'x =', x, 'y = ', y, 'x**y = ', power( x, y )
Contains
Pure Function power( x, y ) Result( r )
Real( wp ) :: r
Real( wp ), Intent( In ) :: x
Real( wp ), Intent( In ) :: y
r = x ** y
End Function power
End Program power_program
ian@eris:~/work/stackoverflow$ gfortran -std=f2003 -Wall -Wextra -O power.f90
ian@eris:~/work/stackoverflow$ ./a.out
x = 3.000000 y = 3.000000 x**y = 27.000000
ian@eris:~/work/stackoverflow$
add a comment |
As stated in the comments simply declaring the function in not only its own scope but also the scope that it is called will solve your problem. However I also want to discourage you from using common, implicit typing, and the completely non-standard real*8. As such here is a version of your program in a more modern dialect
ian@eris:~/work/stackoverflow$ cat power.f90
Program power_program
Implicit None
Integer, Parameter :: wp = Selected_real_kind( 14, 70 )
Real( wp ) :: x, y
x = 3.0_wp
y = 3.0_wp
! Return type and kind of the function power in scope
! due to the implicit interface
Write( *, '( 3( a, 1x, f0.6, 1x ) )' ) &
'x =', x, 'y = ', y, 'x**y = ', power( x, y )
Contains
Pure Function power( x, y ) Result( r )
Real( wp ) :: r
Real( wp ), Intent( In ) :: x
Real( wp ), Intent( In ) :: y
r = x ** y
End Function power
End Program power_program
ian@eris:~/work/stackoverflow$ gfortran -std=f2003 -Wall -Wextra -O power.f90
ian@eris:~/work/stackoverflow$ ./a.out
x = 3.000000 y = 3.000000 x**y = 27.000000
ian@eris:~/work/stackoverflow$
As stated in the comments simply declaring the function in not only its own scope but also the scope that it is called will solve your problem. However I also want to discourage you from using common, implicit typing, and the completely non-standard real*8. As such here is a version of your program in a more modern dialect
ian@eris:~/work/stackoverflow$ cat power.f90
Program power_program
Implicit None
Integer, Parameter :: wp = Selected_real_kind( 14, 70 )
Real( wp ) :: x, y
x = 3.0_wp
y = 3.0_wp
! Return type and kind of the function power in scope
! due to the implicit interface
Write( *, '( 3( a, 1x, f0.6, 1x ) )' ) &
'x =', x, 'y = ', y, 'x**y = ', power( x, y )
Contains
Pure Function power( x, y ) Result( r )
Real( wp ) :: r
Real( wp ), Intent( In ) :: x
Real( wp ), Intent( In ) :: y
r = x ** y
End Function power
End Program power_program
ian@eris:~/work/stackoverflow$ gfortran -std=f2003 -Wall -Wextra -O power.f90
ian@eris:~/work/stackoverflow$ ./a.out
x = 3.000000 y = 3.000000 x**y = 27.000000
ian@eris:~/work/stackoverflow$
edited Nov 24 '18 at 10:06
answered Nov 22 '18 at 7:04
Ian BushIan Bush
2,3791714
2,3791714
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53423806%2fwhy-do-i-have-to-specify-implicitly-for-a-double-precision-return-value-of-a-fun%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
Explicitly declaring
power
to bereal*8
in the main works for me. Since you are learning Fortran I would advise you to steer well clear of "features" likeCOMMON
, implicit delarations andreal*8
.– RussF
Nov 22 '18 at 6:09
3
Note real*8 is not part of standard Fortran, has never been part of standard Fortran, and if that is what you are being talught I worry about the quality of the rest of the teaching - especially if it is covering common and implicit typing as well, things that shouldn't have been used for 25 years. Learn instead about Fortran's kind mechansim
– Ian Bush
Nov 22 '18 at 6:52
2
To reinforce what @RussF has already advised: if you are new to Fortran don't learn about common blocks. Your first contact with them should come when you start to modify old codes.
– High Performance Mark
Nov 22 '18 at 8:21
1
Mixing real data type widths between caller and callee "worked" for a long time on 387 architecture and may still do so in non-sse mode with common 32-bit compilers, as the value would be returned and consumed from the same 387 stack register, and some compilers didn't check this. With an explicit interface (as advised below), a single declaration seen by both caller and callee could do the job. The undeclared type mixing is unlikely to "work" for the function arguments and cannot work for COMMON.
– tim18
Nov 22 '18 at 10:29
1
Old codes are NOT a good place to learn Fortran, unless you have a one-off task to modify some legacy thing and move on to a different language.
– Vladimir F
Nov 24 '18 at 11:06