program main
real, parameter :: a = 1
!real :: a
!a=1
res = func(a)
write(*,*) res
end program main
function func(a)
real, parameter :: b=a+1 !(*)
func = b
return
end function func
My compiler complains at the line marked (*). Is there a way to set the value of a constant with a value coming outside that function?
You can't declare "b" as a parameter since its value is not constant at compile time, since it depends on the function argument.
It is a good idea to use "implicit none" so that you are sure to declare all variables. Also to place your procedures into a module and "use" that module so that the interface is known to the caller. As in:
module my_funcs
implicit none
contains
function func(a)
real :: func
real, intent (in) :: a
real :: b
b = a + 1
func = b
return
end function func
end module my_funcs
program main
use my_funcs
implicit none
real, parameter :: a = 1
real :: res
res = func(a)
write(*,*) res
end program main
#M. S. B.'s answer is fine if run-time initialization is acceptable to you. If you really do want a Fortran parameter, which is set at compile time, then you can do it like this:
program main
implicit none
real, parameter :: a = 1.0
real :: res
res = func()
write(*,*) res
contains
function func()
real, parameter :: b = a + 1.0
real :: func
func = b
end function func
end program main
I suspect part of the confusion is due to differences in language. Often "parameter" is used to mean an argument of a function, but in Fortran it is never used that way. Instead it means something similar to const in C/C++. So, it is not clear to me from your question whether you really want a Fortran parameter or not.
In my example above, the parameter a is known inside func via host association, which is Fortran lingo for nested scopes. You can also do it with modules, via use association, but it is a bit more verbose:
module mypars
implicit none
real, parameter :: a = 1.0
end module mypars
module myfuncs
implicit none
contains
function func()
use mypars, only: a
real, parameter :: b = a + 1.0
real :: func
func = b
end function func
end module myfuncs
program main
use myfuncs, only: func
implicit none
real :: res
res = func()
print *, res
end program main
Related
I would like to create a parametrized derived type inside a procedure and operate on the type's member. The following code works and writes out 4 and 8, as expected.
module mod1
implicit none
type :: pdt(n)
integer, len :: n
integer :: a(n), b(n)
end type
end module mod1
program main
use mod1
implicit none
type(pdt(4)) :: aa
print *, aa%n
print *, func(4)
contains
integer function func(n) result(m)
integer :: n
type(pdt(n)) :: pdttest
m = 2*pdttest%n
end function
end program
The problem arises when I place the procedure func in a separate module, in which case pdttest%n is uninitialized. Compiling using gfortran 11.2.0 with the flag -Wall returns:
Warning: ‘pdttest.n’ is used uninitialized [-Wuninitialized]
What could be the cause of this?
module mod2
use mod1
implicit none
contains
integer function func(n) result(m)
integer :: n
type(pdt(n)) :: pdttest
m = 2*pdttest%n
end function
end module
I want to combine C++ and Fortran together. My Fortran code will use a C++ function and C++ function changes variables of Fortran and sends them back. The C++ function is built with other C++ codes, e.g. the C++ function will use some sub-function in other .cpp file. I make the Fortran code with ifort and I added that C++ function as one object file, test.o in my Fortran makefile. I also put every needed C++ .o file(support test.o) in makefile. It shows the error
#6633, "The type of the actual argument differs from the type of the dummy argument".
Here is the code.
Fortran code
use, intrinsic :: ISO_C_BINDING, only: C_INT, C_DOUBLE
implicit double precision(a-h,o-z),integer(i-n)
Interface
integer (C_INT) function SolveBIE_(x, y, aa, m) BIND(C, NAME='SolveBIE_')
use, intrinsic :: ISO_C_BINDING
implicit none
type (C_PTR), value :: x
type (C_PTR), value :: y
type (C_PTR), value :: aa
integer (C_INT), value :: m
end function SolveBIE_
end Interface
integer (C_INT) :: m
real (C_DOUBLE), ALLOCATABLE, DIMENSION(:,:), target :: x
real (C_DOUBLE), ALLOCATABLE, DIMENSION(:,:), target :: y
real (C_DOUBLE), ALLOCATABLE, DIMENSION(:,:), target :: aa
ALLOCATE(x(0:MAXLEN,MAXINTERFACES))
ALLOCATE(y(0:MAXLEN,MAXINTERFACES))
ALLOCATE(aa(0:MAXLEN,MAXINTERFACES))
My Fortran code run
mm = SolveBIE_(x(1,1),y(1,1),aa(1,1),m)
Using the C++ code and where the error is from, on x, y, aa
I use x(1,1) instead of x, because if using x, then there is another error
#6634,"the shape matching rules of actual arguments and dummy arguments have been violated"`
I don't understand why it should be x(1,1). Why is this working, not x?
My C++ code
#ifdef __cplusplus
extern "C" {
#endif
int solveBIE_(double *ini_bdry_x, double *ini_bdry_y, double *ini_bdry_um, int *fM)
{
double(*bdry_node)[2] = new double[M1][2];
for (int k = 0; k < M; k++) {
bdry_node[k+1][0] = ini_bdry_x[k+1];
bdry_node[k+1][1] = ini_bdry_y[k+1];
bdry_theta[k+1] = Atan(ini_bdry_x[k+1], ini_bdry_y[k+1]);}
... some functions in other .cpp file
The way your interface is written, you have to construct a C_PTR to array x and pass that as the first argument:
use, intrinsic :: ISO_C_BINDING, only: C_INT, C_DOUBLE, C_PTR, C_LOC
! ...
type(C_PTR) PTRx
! ...
PTRx = C_LOC(x(LBOUND(x,1),LBOUND(x,2)))
! ...
mm = solveBIE_(PTRx, PTRy, PTRaa, m)
As shown above, you would have to fix the next two arguments as well. But you need to rewrite the interface for argument fM because as matters stand, Fortran will pass an integer by value whereas C++ is expecting a pointer. Given that, I would rewrite the interface completely, using the names given for the arguments in the C++ function and passing everything by reference. Names for dummy arguments are potentially visible in Fortran, so it's useful for them to be meaningful. In the following I assume that fM points to a scalar in the callee:
Interface
function SolveBIE_(ini_bdry_x, ini_bdry_y, ini_bdry_um, fM) &
BIND(C, NAME='SolveBIE_')
import
implicit none
integer(C_INT) SolveBIE_
real(C_DOUBLE) :: ini_bdry_x(*)
real(C_DOUBLE) :: ini_bdry_y(*)
real(C_DOUBLE) :: ini_bdry_um(*)
integer (C_INT) :: fM
end function SolveBIE_
end Interface
Then later on you can invoke it more or less normally as
mm = SolveBIE_(x,y,aa,m)
Note that x(1,1) was wrong because LBOUND(x,1) = 0, not 1!
I am using Fortran 90 and the Intel compiler.
I am very confused using a function in a subroutine. My code is (I deleted everything unimportant):
program test
INTEGER :: seed=5
REAL :: nor_ran_number1, nor_ran_number2
CALL Box_Muller_transform(seed,nor_ran_number1,nor_ran_number2)
end program test
double precision function grnd(SEED)
grnd=5
return
end
SUBROUTINE Box_Muller_transform (seed,nor_ran_number1,nor_ran_number2)
implicit none
INTEGER, INTENT(in) :: seed
REAL, INTENT(out) :: nor_ran_number1, nor_ran_number2
nor_ran_number1 = grnd(seed)
nor_ran_number2 = grnd(seed)
end SUBROUTINE Box_Muller_transform
The compiler returns:
error #6404: This name does not have a type, and must have an explicit
type. [GRND]
nor_ran_number1 = grnd(seed)
------------------^
I found this and understand that the function "grad" is not visible inside "Box_Muller_transform". However then I would expect the following code to produce the same error:
program test
INTEGER ::a=5, b
call sub(a,b)
write(*,*) b
end program
SUBROUTINE sub(a,b)
INTEGER, INTENT(in) ::a
INTEGER, INTENT(out) ::b
b = fun(a)
end subroutine sub
function fun(a)
INTEGER :: fun
INTEGER :: a
fun = a*a
end function fun
But this is working.
I would be very happy if someone could point out the difference and explain the simplest way to solve this problem.
Functions must have their return value defined. Since you are using implicit none in your first example, the type of the return value of grnd must be defined explicitly:
SUBROUTINE Box_Muller_transform (seed,nor_ran_number1,nor_ran_number2)
implicit none
INTEGER, INTENT(in) :: seed
REAL, INTENT(out) :: nor_ran_number1, nor_ran_number2
double precision :: grnd
nor_ran_number1 = grnd(seed)
nor_ran_number2 = grnd(seed)
end SUBROUTINE Box_Muller_transform
In the second example, you have not specified implicit none in sub, therefore fun is assumed to be of (implicit) type real. The compiler seems to silently cast this to integer.
Is it possible to pass real part of a complex array to a subroutine in Fortran without storing the real part in another array and pass that? e.g. instead of
Z = complex array;
X = real(Z)
call foo(X)
Do the following
Z = complex array
call foo(real(Z))
This gives me a compiler error! I am using an intel compiler ifort.
Sure, it works:
module testmod
implicit none
integer, parameter :: dp = kind(1.0d0)
contains
subroutine realsub(array)
real(dp), intent(in) :: array(:)
print *, array
end subroutine realsub
end module testmod
program testprog
use testmod
implicit none
complex(dp) :: array(3)
array(:) = [ (1.0_dp, 1.0_dp), (3.0_dp, 2.0_dp), (-1.0_dp, 3.0_dp) ]
call realsub(real(array))
end program testprog
I'm enough of a novice to not know the terminology, so I can't search the Web for the answer to this.
More than once, in programming, I've wanted to do something like this.
A and B are subroutines, c and d are functions. A and B each call a function multiple times inside them.
call A(c(x))
call A(d(x))
call B(c(x))
call B(d(x))
This structure doesn't work. I'm told that Fortran doesn't support aliasing of functions, at least in this context. (Most search results involving "aliasing" refer to aliasing variables rather than functions, which is why I haven't found an answer.)
So what structure can I use to do this without having to write multiple versions of A and B?
Not totally sure I understand what you want, but is it something like the following?
Program f
Implicit None
Interface
Integer Function c( x )
Implicit None
Integer, Intent( In ) :: x
End Function c
Integer Function d( x )
Implicit None
Integer, Intent( In ) :: x
End Function d
End Interface
Call a( 3, c )
Call a( 4, d )
Call b( 5, c )
Call b( 6, d )
Contains
Subroutine a( x, func )
Integer, Intent( In ) :: x
Interface
Integer Function func( x )
Implicit None
Integer, Intent( In ) :: x
End Function func
End Interface
Write( *, * ) 'In a. Func = ', func( x )
End Subroutine a
Subroutine b( x, func )
Integer, Intent( In ) :: x
Interface
Integer Function func( x )
Implicit None
Integer, Intent( In ) :: x
End Function func
End Interface
Write( *, * ) 'In b. Func = ', func( x )
End Subroutine b
End Program f
Integer Function c( x )
Implicit None
Integer, Intent( In ) :: x
c = 2 * x
End Function c
Integer Function d( x )
Implicit None
Integer, Intent( In ) :: x
d = 10 * x
End Function d
Wot now? gfortran -std=f95 f.f90
Wot now? ./a.out
In a. Func = 6
In a. Func = 40
In b. Func = 10
In b. Func = 60
Wot now?
An alternative is procedure pointers, but you'll need a f2003 compiler for that and those are not so common yet - the above is fine back to f90 and even earlier than that External will do what you want, but has less error checking capabilities
call A(c(x)) looks like evaluate c(x) and pass that to subroutine A, as IanH says in his comment.
If you want to pass a function "C" that takes an argument of type such as X to subroutine A, there are several ways to do that.
As already mentioned, procedure pointers are a new way. While extremely few compilers exist that support all of the Fortran 2003 standard, this portion is widely supported.
Here is an example adapted from Function pointer arrays in Fortran
module ProcsMod
implicit none
contains
function f1 (x)
real :: f1
real, intent (in) :: x
f1 = 2.0 * x
return
end function f1
function f2 (x)
real :: f2
real, intent (in) :: x
f2 = 3.0 * x**2
return
end function f2
subroutine fancy (func, x, answer)
real, intent (in) :: x
real, intent (out) :: answer
interface AFunc
function func (y)
real :: func
real, intent (in) ::y
end function func
end interface AFunc
answer = func (x)
end subroutine fancy
end module ProcsMod
program test_proc_ptr
use ProcsMod
implicit none
interface
function func (z)
real :: func
real, intent (in) :: z
end function func
end interface
procedure (func), pointer :: f_ptr => null ()
real :: answer
f_ptr => f1
call fancy (f_ptr, 2.0, answer)
write (*, *) answer
f_ptr => f2
call fancy (f_ptr, 2.0, answer)
write (*, *) answer
stop
end program test_proc_ptr
The calls "call fancy (f_ptr, 2.0, answer)" look the same, but by changing the function that the function pointer f_ptr points to, a different function is passed to the subroutine fancy.
This compiles with both gfortran (versions 4.4 to 4.7) and ifort.
I think M.S.B.'s answer describes what you mean by aliasing of functions; the Fortran terminology is "procedure pointers". As an alternative to this and Ian's answer, you can also use procedure dummy arguments (which are not necessarily pointers). Note that any procedure declaration is only supported since F2003, but gfortran 4.7 and ifort 13 both support this. It can be done with or without an (abstract) interface block:
module dummy_procedure
implicit none
abstract interface
real function myfunc(x)
real, intent(in) :: x
end function
end interface
contains
subroutine a(func)
! Using the interface block:
procedure(myfunc) :: func
print*, 'a:', func(.5)
end subroutine
subroutine b(func)
! Using the explicit interface of a known procedure:
procedure(f1) :: func
print*, 'b:', func(.5)
end subroutine
real function f1(x)
real, intent(in) :: x
f1 = 2.0 * x
end function
real function f2(x)
real, intent(in) :: x
f2 = 3.0 * x**2
end function
end module
Now you can pass f1 and f2 directly into a and b, and the output is as expected:
program main
use dummy_procedure
call a(f1) ! a: 1.0
call a(f2) ! a: 0.75
call b(f1) ! b: 1.0
call b(f2) ! b: 0.75
end program
If I understand what you're trying to do:
1) Define your functions in a module.
2) Use the module.
3) Supply the function and the input data to the subroutine as separate arguments.
Here's a code that worked for me:
module iterfuncs
contains
! two example functions:
function approach_golden_ratio(a) result(agr)
agr=1./a+1.
end function approach_golden_ratio
function approach_other_ratio(a) result(aor)
aor=1./(a-1)
end function approach_other_ratio
end module
program use_some_functions
use iterfuncs
real :: final_res
final_res=2.3
! call subroutine with 1st function
call iterate(final_res,approach_golden_ratio)
print *,final_res
final_res=2.3
! call subroutine with 2nd function
call iterate(final_res,approach_other_ratio)
print *,final_res
end program
subroutine iterate(res,func)
use iterfuncs
do n=1,100
res=func(res)
enddo
return
end subroutine