I've defined a code module (a Fortran F90 file) and supplied it with these two subroutines:
pure Subroutine XRotation (x, y, z, Xrot, xp, yp, zp)
! Rotate about X-axis through the angle Xrot
real*4, INTENT(IN) :: x, y, z, xrot
real*4, INTENT(OUT) :: xp, yp, zp
real*4 xrad
Xrad = Xrot * 3.141592627 / 180 ! Convert to radians
yp = y * COS(Xrad) + z * SIN(Xrad)
xp = x
zp = z * COS(Xrad) - y * SIN(Xrad)
END
Pure Subroutine DummyDummy()
Call XRotation(1,2,3,4,5,6,7)
End Subroutine
The compiler (Intel Fortran 12, targeting 32-bit Windows, for whatever that's worth) returns a single error message:
error #7137: Any procedure referenced in a PURE procedure, including
one referenced via a defined operation or assignment, must be
explicitly declared PURE. [XROTATION]
I'm a little bit stumped. How can I change this code so that the PURE Subroutine "DummyDummy" compiles?
i don't know much about fortran 90 (back in my day etc etc) but if you place that in a module it works. i get the impression that modules are needed for various "modern" fortran features.
anyway, someone smarter (or younger?) than me can explain, but that should help you continue.
module foo
implicit none
contains
pure Subroutine XRotation (x, y, z, Xrot, xp, yp, zp)
....
end module foo
ah, here's an explanation (see the answers) - Writing and calling pure subroutines in Fortran 90 using gfortran
ps i also get a type warning as you're passing in integers to float arguments.
Related
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?
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 an interface 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.
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$
I've been having some trouble with variables precision in my code...
For a while i've been declaring variables as real(kind=8) :: var and I now understand that this is not very portable and has some other complications, but basically I'm getting a lot of imprecision in numerical calculations.
Now I'm using:
INTEGER, PARAMETER :: R8 = SELECTED_REAL_KIND (30, 300)
with variable declaration: real(R8) :: var1,var2.
Before I usually initialized variables as var1 = 1.0D0 and now I'm using var1 = 1.0_R8 but what should I do with var1 = 1.0D-20? I've run a simple code which proved that 1.0D-20 won't give me an accurate result but something like 10.0_r8**(-20.0_r8) will. Is there an easier way to define the variable? I know that 1D-20 is very small but the code I'm using really needs 30 decimal case precision.
Thank you for your help!
There's really two things happening here. First, declaring an exponent using d notation is the same as declaring it as type double precision.
Second, the r8 variable you declare requires more precision than most (all?) 8-byte representations. So you're actually declaring most of your variables as quad, then initializing them as double, which is the source of your problem.
As mentioned in the comments, the answer to your explicit question is to declare exponents using the following notation
real(mytype) :: a = 1.23e-20_mytype
This notation is cumbersome but easy to get used to for constant declaration.
Here's a little sample code I used to test your types:
program main
use ISO_FORTRAN_ENV, only : REAL64 => REAL64, REAL128
implicit none
INTEGER, PARAMETER :: R8 = SELECTED_REAL_KIND (30, 300)
real(r8) :: x, y, z
real(REAL64) :: a, b, c
x = 1.23d-20
y = 1.23e-20_r8
z = 1.23_r8*(10._r8**-20)
write(*,*) x
write(*,*) y
write(*,*) z
a = 1.23d-20
b = 1.23e-20_REAL64
c = 1.23_REAL64*(10._REAL64**-20)
write(*,*) a
write(*,*) b
write(*,*) c
write(*,*) 'Types: ', REAL64, R8, REAL128
end program main
for Intel 16.0, this gives:
mach5% ifort main.f90 && ./a.out
1.230000000000000057423043720037598E-0020
1.230000000000000000000000000000000E-0020
1.230000000000000000000000000000002E-0020
1.230000000000000E-020
1.230000000000000E-020
1.230000000000000E-020
Types: 8 16 16
I am writing a code for high-performance computing. I found it handy to use the result keyword for naming a function's return value. I wonder if there is any performance issue here? In particular, would compilers make a temporary variable for the indicated 'result-name' to be copied eventually in the variable associated with the function name, or is the 'result-name' just an alias?
I compiled the following two codes with 'gfortran -S':
program test_result
real*8 :: a, b, c
a = 10.0
b = 20.0
c = myfunc(a, b)
contains
function myfunc(x, y)
real*8 :: myfunc
real*8 :: x, y
myfunc = x * y
end function myfunc
end program test_result
program test_result
real*8 :: a, b, c
a = 10.0
b = 20.0
c = myfunc(a, b)
contains
function myfunc(x, y) result(f)
real*8 :: f
real*8 :: x, y
f = x * y
end function myfunc
end program test_result
without optimization the compiler gave me two different assembly outputs, with optimization though the resulting assembly lines look the same. Does anybody know the implications here?
Thanks!
No there is not any performance penalty, it is just a syntactic issue, the generated code is identical. It is really just an "alias".
There should not be any differences even with optimizations disabled. My test confirms that. If it is not the case for you, you should show the differences you get from your compiler.
Could anyone please tell me why this simple program give me a segmentation fault?
I'm using gfortran, and I need to use a function inside a subroutine.
program tst
implicit none
real z,x,y
x=10.
y=2.
call s(10.,10.,z)
print*,z
end program
real function c(x,y)
implicit none
real x, y
c = x*y
return
end
subroutine s(x,y,z)
implicit none
real x, y
real z
real c
z = c(x,y)
end
Better to put your procedures into a module so that their interfaces will be known to each other and any procedure or program useing the module:
module MyStuff
contains
function c(x,y)
implicit none
real :: c
real :: x, y
c = x*y
return
end
subroutine s(x,y,z)
implicit none
real :: x, y, z
z = c(x,y)
end
end module MyStuff
program tst
use MyStuff
implicit none
real z,x,y
x=10.
y=2.
call s(10.,10.,z)
print*,z
end program
It works, giving answer 100.
There is a F77 code, slightly modified from me. The code calls a particular routine, but it seems that compilation does not stop (and I believe there is no problem with loops). This makes me wonder why this might happen.
Second i cannot really understand what the output of that routine will be. Can anyone help here?
this is the section of the code that calls the routine/function. By working a MWE,
integer, parameter:: nf=101, ns=7, nas=427, na=61, nxm=3
integer:: i,j,k,
allocate(xf(nf), xa(na))
allocate(absa(nxm,na-1), wgta(nxm,na-1),absf(nxm,nf-1), wgtf(nxm,nf-1))
do 150 i=1,na-1
call qgausl (nxp(i), xa(i), xa(i+1), absa(1,i), wgta(1,i))
150 continue
do 160 i=1,nf-1
call qgausl (nxp(i), xf(i), xf(i+1), absf(1,i), wgtf(1,i))
160 continue
And this is the routine
subroutine qgausl(n,x1,x2,x,w)
implicit none
integer:: n, m
real*8:: xl,x2, x1, xm, eps, z, p1,p2,p3, pp, z1
real*8:: x(n), w(n)
eps=1.0e-8
m=(n+1)/2
xm=0.5*(x2+x1)
xl=0.5*(x2-x1)
do 12 i=1,m
z = cos(3.141592654*(i-.25)/(n+.5))
1 continue
print*, z
p1 = 1.0
p2 = 0.0
do 11 j=1,n
p3 = p2
p2 = p1
p1 = ((2.0*j-1.0)*z*p2-(j-1.0)*p3)/j
11 continue
pp = n*(z*p1-p2)/(z*z-1.0)
z1 = z
z = z1-p1/pp
if (dabs(z-z1).gt.eps) go to 1
x(i) = xm-xl*z
x(n+1-i) = xm+xl*z
w(i) = 2.0*xl/((1.0-z*z)*pp*pp)
w(n+1-i) = w(i)
12 continue
return
end subroutine
For your information and if I made a good job, i translated this into Matlab and seems that there is no problem with the loops in the routine.
A bit of an extended comment:
One thing I notice is you tagged this as fortran77 but in fact it will not compile if this is indeed an f77-type external subroutine (ie. not in a module/contains construct) because you use implicit none but fail to declare i in the subroutine.
( There are numerous other post-f77 syntax features in there as well. )
So...assuming this subroutine is internal (ie. lives within contains in the calling routine) the i here :
do 12 i=1,m
is the same i from the scope of the calling routine, ie. you are effectively using the same variable for two nested loops.
This is obviously an illegal thing to do, and I must say I'm disturbed to see that gfortran silently compiles such and runs off in an endless loop.. (!?!)
I'd suggest moving the subroutine to a module or simply making it external if you think this is the case. Then the compiler will flag your failure to declare i
example
both gfortran and ifort compile this without warnings:
implicit none
integer j
do j = 1,2
call x()
enddo
contains
subroutine x()
implicit none
do j=3,4
write(*,*)j
enddo
end subroutine
end
the gfortran version runs away endlessly printing 3,4,3,4. The intel version writes 3,4 just once (ie not what you might expect either)
declaring j in the subroutine fixes it of course..