pointer as a dummy argument - pointers

I am somewhat puzzled by the following program
module test
implicit none
type TestType
integer :: i
end type
contains
subroutine foo(test)
type (TestType), intent(out) :: test
test%i = 5
end subroutine
subroutine bar(test)
type (TestType), intent(out) :: test
test%i = 6
end subroutine
end module
program hello
use test
type(TestType) :: t
call foo(t)
print *, t%i
call bar(t)
print *, t%i
end program hello
and its derivatives. More on those later. As we know, Fortran transfers routine arguments as a pass-by-reference, meaning that the entity emerging at the dummy argument test for both foo and bar is the same memory space granted on the stack in program hello. So far so good.
Suppose I define in program hello the type(TestType) :: t as a pointer, and allocate it.
program hello
use test
type(TestType), pointer :: t
allocate(t)
call foo(t)
print *, t%i
call bar(t)
print *, t%i
deallocate(t)
end program hello
The code works as before, the only difference being that the object was not allocated on the stack, but on the heap.
Now assume to go back to the stack-allocated program and that subroutine bar is instead defined as
subroutine bar(test)
type (TestType), pointer :: test
test%i = 6
end subroutine
The program does not compile anymore because you must use the heap-allocated version to make it work, or to be more accurate it is mandatory to pass a pointer to the routine when the routine is defined to accept a pointer as a dummy argument. On the other hand, if the dummy argument does not contain the pointer keyword, the routine would accept both pointers and non-pointers.
This makes me wonder... what's the point of declaring a dummy argument a pointer ?

Reposted from comp.lang.fortran, an answer by Tobias Burns:
Now assume to go back to the stack-allocated program and that
subroutine bar is instead defined as
subroutine bar(test)
type (TestType), pointer :: test
test%i = 6
end subroutine
The program does not compile anymore because you must use the
heap-allocated version to make it work,
That's not quite correct: You can also not pass an ALLOCATABLE variable
to a dummy with POINTER attribute. I think one (practical) reason is
that the pointer address can escape and you would thus cause alias
problems. A formal reason is that an ALLOCATABLE is simply not a
POINTER; additionally, the standard does not talk about heap vs. stack
vs. static memory. And in fact, local arrays [with constant bounds] will
often be created in static memory and not on the stack (unless you use
OpenMP or the RECURSIVE attribute). Thus, your "stack" example could
also be a "static memory" example, depending on the compiler and the
used options.
or to be more accurate it is
mandatory to pass a pointer to the routine when the routine is defined
to accept a pointer as a dummy argument.
That's also not completely true. In Fortran 2008 you can pass a
non-POINTER, which has the TARGET attribute, to a pointer dummy which
has the INTENT(IN) attribute. (Pointer intent is relative to the pointer
association status; for non-pointer dummies the intents are about the
value stored in the variable.)
This makes me wonder... what's the point of declaring a dummy argument
a pointer ?
Well, if the argument has the POINTER attribute, you can allocate and
free the pointer target, you can associate the pointer with some target
etc. Up to Fortran 95 it was not possible to have ALLOCATABLE dummy
arguments thus a pointer had to be used if a (dummy) argument had to be
allocated in a procedure.
If you can, you should try to use rather ALLOCATABLEs than POINTERs -
they are easier to use, do not leak memory and have pose no
alias-analysis problems to the compiler. On the other hand, if you want
to create, e.g., a linked list, you need a pointer. (Though, for a heap
usage, also Fortran 2008's allocatable components could be used.*)
*I mean:
type t
type(t), allocatable :: next
end type
where the component is of the same type as the type being defined;
before F2008 this was only allowed for pointers but not for allocatables.
and by R. Maine
As we know, Fortran transfers routine arguments as a
pass-by-reference,
We apparently know incorectly, then. The standard never specifies that
and, indeed goes quite a lot out of its way to avoid such specification.
Although yours is a common misconception, it was not strictly accurate
even in most older compilers, particularly with optimization turned on.
A strict pass-by-reference would kill many common optimizations.
With recent standards, pass-by-reference is all but disallowed in some
cases. The standard doesn't use those words in its normative text, but
there are things that would be impractical to implement with
pass-by-reference.
When you start getting into things like pointers, the error of assuming
that everything is pass-by-reference will start making itself more
evident than before. You'll have to drop that misconception or many
things wil confuse you.
I think other people have answered the rest of the post adequately. Some
also addressed the above point, but I wanted to emphasize it.
Hope this answers your question.

Related

Passing Fortran POINTER to SUBROUTINES as MODULE PROCEDURE

My first question is, "Can POINTER be passed to subroutines next to INTENT?"
Although passing Fortran POINTER with INTENT(IN) or INTENT(INOUT) seems to be a common practice, the documentation of Intel for Fortran POINTER says(https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-developer-guide-and-reference/top/language-reference/a-to-z-reference/o-to-p/pointer-fortran.html)
The pointer cannot be declared with the INTENT or PARAMETER attributes
which confuses me a lot.
My second question is related to following code.
I tried overloading write_matrix with write_matrix_2d - which is for 2d arrays - and write_matrix_2d_ptr - which is for 2d Fortran POINTERs.
It turned out the code fails to compile with
Ambiguous generic interface WRITE_MATRIX: previously declared specific procedure WRITE_MATRIX_2D is not distinguishable from this declaration. [WRITE_MATRIX_2D_PTR]
If I comment (1) then it complies, and runs fine ( but I suppose this is bad practice since POINTER arguments going into subroutien write_matrix_2d which expects array input.)
Is there any way to overload Fortran subroutines just by their arguments' datatype just like C/C++?
module mod_write
implicit none
interface write_matrix
module procedure write_matrix_2d
(1) !module procedure write_matrix_2d_ptr
end interface
contains
subroutine write_matrix_2d(a)
implicit none
real, intent(in) :: a(:,:)
! local variables
integer :: i, j
print *, "in ARRAY printing subroutine"
do i = lbound(a,1), ubound(a,1)
write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
enddo
end subroutine
subroutine write_matrix_2d_ptr(a)
implicit none
real, pointer, intent(in) :: a(:,:)
! local variables
integer :: i, j
print *, "in POINTER printing subroutine"
do i = lbound(a,1), ubound(a,1)
write(*,*) ( a(i,j), j = lbound(a,2), ubound(a,2) )
enddo
end subroutine
end module
program test
use mod_write
implicit none
real, dimension(9) :: b = (/21, 22, 23, 24, 25, 26, 27, 28, 29/)
real, dimension(3,3) :: c
real, dimension(3,3), target :: ct(3,3)
real, dimension(:,:), pointer :: cptr(:,:)
c = reshape( b, (/3, 3/) )
write(*,*)
write(*,*) 'c'
call write_matrix(c)
(2) !call write_matrix_2d(c)
ct = c
cptr => ct(2:3,2:3)
write(*,*)
write(*,*) 'ct'
call write_matrix(ct)
(2,3)!call write_matrix_2d_ptr(ct)
write(*,*) 'cptr'
call write_matrix(cptr)
(2) !call write_matrix_2d_ptr(cptr)
end program
My third question is again related to the attached code. Overloading is not that big a deal since I can just use write_matrix_2d and write_matrix_2d_ptr separately as (2)s in the code. But, as you can see at (3), call write_matrix_2d_ptr(ct) runs fine with the target input ct while write_matrix_2d_ptr expects pointer input. Is this okay, or should I make another write_matrix_2d_target?
Thank you.
The compiler documentation is wrong (or badly out of date). A dummy argument that is a pointer can also have the intent attribute. The attribute applies to the pointer association status of the argument, not the target.
Procedures in a generic interface can be overloaded if their dummy arguments are distinguishable. Dummy arguments are distinguishable if they have different type, kind or rank. Whether something is a pointer or not is not part of its type. (To be complete, arguments are also distinguishable if one is a pointer without intent(in) and the other is allocatable.) The requirements for distinguishable dummy arguments for different procedures in a generic interface mean that the rules around which specific procedure a particular generic reference resolves to are very simple.
Your example of overloading would be ambiguous - it is fine to pass a(n associated) pointer actual argument to a non-pointer dummy - the actual argument designates the target of the pointer. It is also permitted to pass a non-pointer actual with the target attribute to an intent(in) pointer dummy.
Whether something is a pointer or not is completely orthogonal to whether it is an array or not.
Pointers in Fortran are primarily used to reference different things (targets) during program execution.
Dummy arguments only need to be a pointer if you need to do something inside the procedure that relates to the association status of the pointer - perhaps you want to test the association status, or associate the pointer with something else.
(1) The intent restriction is some copy and paste error or it is in some strange context I do not understand. There was such a resteiction in Fortran 90.
(2) "but I suppose this is bad practice since POINTER arguments going into subroutien write_matrix_2d which expects array input."
There is nothing bad about passing a Fortran pointer variable as an ordinary variable. The default argument passing mechanism is that the target of thee pointer is passed using the normal non-ointer mechanism. One only uses pinter dummy arguments if one has specific reasons to do so. Most often tbat means than one works with the association status inside the subroutine. There are some other uses but you need a specific reason to declare your argument as pointer, otherwise it just complicates things.
(3) target can be passed to pointer, intent(in) in Fortran 2008.

Fortran calls: advantage of passing by pointer vs passing by reference

It is my understanding that in Fortran arrays are passed by reference. So is there an advantage to passing a pointer to a large array (into a subroutine) as opposed to passing the array itself.
Could you also clarify this in the context of recursive functions. I have seen implementations where pointers are used "for efficiency", but if everything is passed by reference, then what's the benefit of pointers.
Here's an example. I have an array X (in reality lets say it's a very large array).
INTEGER :: X(:)
I can define a subrouitne that takes this array as follows:
SUBROUTINE FOO(X)
INTEGER, INTENT(IN) :: X(:)
INTEGER :: I
DO I = 1, 4
WRITE(*,*) X(I)
ENDDO
END SUBROUTINE FOO
When I call the subroutine above then the array X is not copied as fortran passes a reference to it. Now lets say I have a modified version of the subroutine:
SUBROUTINE FOO2(X)
INTEGER, POINTER, INTENT(IN) :: X(:)
INTEGER :: I
DO I = 1, 4
WRITE(*,*) X(I)
ENDDO
END SUBROUTINE FOO2
I can call FOO2 from a program as follows:
PROGRAM TEST
IMPLICIT NONE
INTEGER, TARGET :: X(5)
INTEGER, POINTER :: Y(:)
X = (/1,2,3,4,5/)
Y => X
CALL FOO2(Y)
END PROGRAM TEST
Then here's my question: is there a performance difference between the two versions of foo? Is there any useful scenario where the declaration of FOO2 might be preferable to FOO?
In this simple case there shouldn't be any real difference. Note the program is illegal, you don't have the explicit interface to FOO or FOO2, but I will assume you just ommited it for simplicity and they are in a module or internal.
Both arrays can be non-contiguous in principle, so no difference here. If that slows down the code, the contiguous attribute might help. Or assumed size or explicite size arrays too.
Your subroutine is too simple, so there is no danger of aliasing too. This is the common source of decreasing performance with pointers. There could be potential aliasing with some other argument or another variable you access by host or use association provided it has the target attribute.
The purpose of pointer arguments is actually to either allow disassociated (null()) arguments, or to allow changing of the association status in the subroutines. Your example doesn't use neither and therefore the pointer attribute is superfluous.
There is on last small difference. It is not specified in the standard what is actually passed to the subroutine at the machine code level for the pointer variables. If it is just an address (likely for scalars) it is the same as non-pointer, just the aliasing rules and the allowed usage are different. Otherwise some descriptor is passed, but any overhead should be negligible, the assumed shape arrays use a descriptor too.

Fortran 90 difference between compaq visual fortran and gfortran

This may be a specific question, but I think it pertains to how memory is handled with these two compilers (Compaq visual Fortran Optimizing Compiler Version 6.5 and minGW). I am trying to get an idea of best practices with using pointers in Fortran 90 (which I must use). Here is an example code, which should work "out of the box" with one warning from a gfortran compiler: "POINTER valued function appears on RHS of assignment", and no warnings from the other compiler.
module vectorField_mod
implicit none
type vecField1D
private
real(8),dimension(:),pointer :: x
logical :: TFx = .false.
end type
contains
subroutine setX(this,x)
implicit none
type(vecField1D),intent(inout) :: this
real(8),dimension(:),target :: x
logical,save :: first_entry = .true.
if (first_entry) nullify(this%x); first_entry = .false.
if (associated(this%x)) deallocate(this%x)
allocate(this%x(size(x)))
this%x = x
this%TFx = .true.
end subroutine
function getX(this) result(res)
implicit none
real(8),dimension(:),pointer :: res
type(vecField1D),intent(in) :: this
logical,save :: first_entry = .true.
if (first_entry) nullify(res); first_entry = .false.
if (associated(res)) deallocate(res)
allocate(res(size(this%x)))
if (this%TFx) then
res = this%x
endif
end function
end module
program test
use vectorField_mod
implicit none
integer,parameter :: Nx = 15000
integer :: i
real(8),dimension(Nx) :: f
type(vecField1D) :: f1
do i=1,10**4
f = i
call setX(f1,f)
f = getX(f1)
call setX(f1,f)
if (mod(i,5000).eq.1) then
write(*,*) 'i = ',i,f(1)
endif
enddo
end program
This program runs in both compilers. However, changing the loop from 10**4 to 10**5 causes a serious memory problem with gfortran.
Using CTR-ALT-DLT, and opening "performance", the physical memory increases rapidly when running in gfortran, and doesn't seem to move for the compaq compiler. I usually cancel before my computer crashes, so I'm not sure of the behavior after it reaches the maximum.
This doesn't seem to be the appropriate way to use pointers (which I need in derived data types). So my question is: how can I safely use pointers while maintaining the same sort of interface and functionality?
p.s. I know that the main program does not seem to do anything constructive, but the point is that I don't think that the loop should be limited by the memory, but rather it should be a function of run-time.
Any help is greatly appreciated.
This code has a few problems, perhaps caused by misunderstandings around the language. These problems have nothing to do with the specific compiler - the code itself is broken.
Conceptually, note that:
There is one and only one instance of a saved variable in a procedure per program in Fortran 90.
The variable representing the function result always starts off undefined each time a function is called.
If you want a pointer in a calling scope to point at the result of a function with a pointer result, then you must use pointer assignment.
If a pointer is allocated, you need to have a matching deallocate.
There is a latent logic error, in that the saved first_entry variables in the getX and setX procedures are conflated with object specific state in the setX procedure and procedure instance specific state in the getX procedure.
The first time setX is ever called the x pointer component of the particular this object will be nullified due to the if statement (there's an issue of poor style there too - be careful having multiple statements after an if statement - it is only the first one that is subject to the conditional!). If setX is then called again with a different this, first_entry will have been set to false and the this object will not be correctly set-up. I suspect you are supposed to be testing this%TFX instead.
Similarly, the first time getX is called the otherwise undefined function result variable res will be nullified. However, in all subsequent calls the function result will not be nullified (the function result starts off undefined each execution of the function) and will then be erroneously used in an associated test and also perhaps erroneously in a deallocate statement. (It is illegal to call associated (or deallocate for that matter) on a pointer with an undefined association status - noting that an undefined association status is not the same thing as dissociated.)
getX returns a pointer result - one that is created by the pointer being allocated. This pointer is then lost because "normal" assignment is used to access the value that results from evaluating the function. Because this pointer is lost there can't be (and so there isn't...) a matching deallocate statement to reverse the pointer allocation. The program therefore leaks memory. What almost certainly should be happening is that the thing that captures the value of the getX function in the main program (f in this case, but f is used for multiple things, so I'll call it f_ptr...) itself should be a pointer, and it should be pointer assigned - f_ptr => getX(f1). After the value of f_ptr has been used in the subsequent setX call and write statement, it can then be explicitly deallocated.
The potential for accidental use of normal assignment when pointer assignment is intended is one of the reasons that use of functions with pointer results is discouraged. If you need to return a pointer - then use a subroutine.
Fortran 95 simplifies management of pointer components by allowing default initialization of those components to NULL. (Note that you are using default initialization in your type definition - so your code isn't Fortran 90 anyway!)
Fortran 2003 (or Fortran 95 + the allocatable TR - which is a language level supported by most maintained compilers) introduces allocatable function results - which remove many of the potential errors that can otherwise be made using pointer functions.
Fortran 95 + allocatable TR support is so ubiquitous these days and the language improvements and fixes made to that point are so useful that (unless you are operating on some sort of obscure platform) limiting the language level to Fortran 90 is frankly ridiculous.

Fortran Pointer arithmetic

That's my first question post ever ... don't be cruel, please.
My problem is the following. I'd like to assign a fortran pointer as an expression. I think that's not possible by simple fortran techniques. But since new fortran versions seem to provide ways to handle things used in C and C++ (like c_ptr and c_f_pointer ... ), maybe someone knows a way to solve my problem. (I have not really in idea about C, but I read that pointer arithmetic is possible in C)
To make things more clear, here is the code which came to my mind immediately but isn't working:
program pointer
real(8),target :: a
real(8),pointer :: b
b=>a*2.0d0 ! b=>a is of course working
do i=1,10
a=dble(i)*2.0d0
write(*,*)b
end do
end program
I know that there are ways around this issue, but in the actual program, all of which came to my mind, would lead to much longer computation time and/or quite wiered code.
Thanks, a lot, in advance!
Best, Peter
From Michael Metcalf,
Pointers are variables with the POINTER attribute; they are not a distinct data type (and so no 'pointer arithmetic' is possible).
They are conceptually a descriptor listing the attributes of the objects (targets) that the pointer may point to, and the address, if any, of a target. They have no associated storage until it is allocated or otherwise associated (by pointer assignment, see below):
So your idea of b=>a*2 doesn't work because b is being assigned to a and not given the value of a.
Expression, in general (there two and a half very significant exceptions), are not valid pointer targets. Evaluation of an expression (in general) yields a value, not an object.
(The exceptions relate to the case where the overall expression results in a reference to a function with a data pointer result - in that case the expression can be used on the right hand side of a pointer assignment statement, or as the actual argument in a procedure reference that correspond to a pointer dummy argument or [perhaps - and F2008 only] in any context where a variable might be required, such as the left hand side of an ordinary assignment statement. But your expressions do not result in such a function reference and I don't think the use cases are relevant to what you wnt to do. )
I think you want the value of b to change as the "underlying" value of a changes, as per the form of the initial expression. Beyond the valid pointer target issue, this requires behaviour contrary to one of the basic principles of the language (most languages really) - evaluation of an expression uses the value of its primaries at the time the expression is evaluation - subsequent changes in those primaries do not result in a change in the historically evaluated value.
Instead, consider writing a function that calculates b based on a.
program pointer
IMPLICIT NONE
real(8) :: a
do i=1,10
a=dble(i)*2.0d0
write(*,*) b(a)
end do
contains
function b(x)
real(kind(a)), intent(in) :: x
real(kind(a)) :: b
b = 2.0d0 * x
end function b
end program
Update: I'm getting closer to what I wanted to have (for those who are interested):
module test
real,target :: a
real, pointer :: c
abstract interface
function func()
real :: func
end function func
end interface
procedure (func), pointer :: f => null ()
contains
function f1()
real,target :: f1
c=>a
f1 = 2.0*c
return
end function f1
end module
program test_func_ptrs
use test
implicit none
integer::i
f=>f1
do i=1,10
a=real(i)*2.0
write(*,*)f()
end do
end program test_func_ptrs
I would be completely satisfied if I could find a way to avoid the dummy arguments (at least in when I'm calling f).
Additional information: The point is that I want to define different functions f1 and deside before starting the loop, what f is going to be inside of the loop (depending on whatever input).
Pointer arithmetic, in the sense of calculating address offsets from a pointer, is not allowed in Fortran. Pointer arithmetic can easily cause memory errors and the authors of Fortran considered it unnecessary. (One could do it via the back door of interoperability with C.)
Pointers in Fortran are useful for passing procedures as arguments, setting up data structures such as linked lists (e.g., How can I implement a linked list in fortran 2003-2008), etc.

Fortran DEALLOCATE

I am currently trying to code a little subroutine in Fortran to deallocate all allocated variables in memory when my program comes to an error, i.e., a failed to load file or an inexistent needed file. At this point, execution must be terminated, but not all allocatables are necessarily allocated (it depends on where on the code the error appeared), so i can't make a cleanup deallocating all of them.
My current approach is the following:
SUBROUTINE Cleanup(A)
REAL(8), ALLOCATABLE, DIMENSION(:) :: A
IF (ALLOCATED(A)) THEN
DEALLOCATE(A)
END IF
END SUBROUTINE
and call "Cleanup" for every allocatable. The problem with this is that not all my variables are dimension-1. I have up to three dimensions in some of them.
I first thought about writing 3 different subroutines for different dimensions and using overloading, but this do not seems to be very elegant.
Then it came to my mind that maybe i could pass a pointer instead the actuall argument A, but i've googled and it seems you can't deallocate a target variable trough a pointer.
Any ideas about how to do this properly?
Thanks.
My approach to this would use a combination of the following:
As of Fortran 95, all local un-saved allocatable variables that are allocated when a procedure finishes are automatically deallocated. Whether this is applicable depends on how your DLL is called, and hence whether you can actually structure things such that all your allocatables are unsaved locals.
As of Fortran 2003 (or Fortran 95 + the allocatable TR - this language level is widely supported amongst maintained Fortran compilers) allocatable actual arguments passed to INTENT(OUT) allocatable dummy arguments will be automatically deallocated before the procedure starts execution. Your Cleanup routine in the question just needs to add the declaration of the dummy argument as INTENT(OUT) and then there's no need for the IF test or DEALLOCATE. You still need to write the routine for each type and rank that you need to clean up.
Similar to the previous, allocatable components of derived type variables passed to an INTENT(OUT) dummy argument will be automatically deallocated. So you may be able to collect all your allocatable variables together as components in an object of derived type. Cleanup then simply involves passing that object to a procedure with an INTENT(OUT) dummy. INTENT(OUT) here also resets components that have default initialization back to their "default" value. Perhaps there's other cleanup that you need to manually do at this point too (close files, etc).
An alternative approach, again using derived types with all your variables as components, is to make the derived type object itself allocatable. When you need to cleanup, simply deallocate that one object - components of it will be automatically deallocated. Fortran 2003 allows for a final procedure to be triggered from this sort of event if you have additional other cleanup to do at this point.
A derived type approach also makes it easy to have multiple instances of whatever your DLL supports independently active at the one time (you just have multiple objects of derived type).
Examples of the derived type approach, given:
TYPE MyType
REAL, ALLOCATABLE :: variable_one(:)
INTEGER, ALLOCATABLE :: variable_two(:)
...
END TYPE MyType
INTENT(OUT) dummy
TYPE(MyType) :: object
ALLOCATE(object%variable_one(xxx))
ALLOCATE(object%variable_two(yyy))
...
IF (things_have_gone_wrong) CALL Cleanup(object)
...
SUBROUTINE Cleanup(arg)
TYPE(MyType), INTENT(OUT) :: arg
END SUBROUTINE Cleanup
ALLOCATABLE object.
TYPE(MyType), ALLOCATABLE :: object
ALLOCATE(object)
ALLOCATE(object%variable_one(...))
ALLOCATE(object%variable_two(...))
...
IF (things_have_gone_wrong) DEALLOCATE(object)

Resources