Fortran Pointer arithmetic - pointers

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.

Related

Reshaping 1d array to 2D pointer array Fortran

I have a pointer uvw(:,:) which is two-dimensional, and I got a 1d buffer array x(:).
Now I need to point uvw(1,:)=>x(1:ncell) and uvw(2,:)=>x(ncell+1:ncell*2) etc.
I made a very simple example. I know that array of pointers does not work, but does anybody have an idea how this can be worked around?
PS: For a pragmatic reason I do not want to wrap my uvw with a declared type. ( i am changing some bit of code, and need uvw as 2D pointer. Currently is an array, and my idea is to avoid changing the way uvw is being used as it being used thousands of times)
program test
real, allocatable,target :: x(:)
real, pointer :: ptr(:,:)
allocate(x(100) )
x = 1.
ptr(1,:) => x(1:10)
end program
The error message says:
`error #8524: The syntax of this data pointer assignment is incorrect:
either 'bound spec' or 'bound remapping' is expected in this context.
[1]
ptr(1,:) => x(1:10)
----^`
You are trying to perform pointer bounds remapping, but you have the incorrect syntax and approach.
Pointer bounds remapping is a way to have the shape of the pointer different from that of the target. In particular, the rank of the pointer and target may differ. However, in such an assignment it is necessary to explicitly specify the lower and upper bounds of the remapping; it isn't sufficient to use : by itself.
Also, you'll need to assign the whole pointer in one go. That is, you can't have "the first ten elements point to this slice, the next ten to this slice" and so on in multiple statements.
The assignment statement would be
ptr(1:10,1:10) => x
Note, that this also means that you can't actually have what you want. You are asking for the elements ptr(1,1:10) to correspond to x(1:10) and ptr(2,2:10) to correspond to x(11:20). That isn't possible: the array elements must match in order: ptr(1:10,1) being the first ten elements of ptr must instead be associated with the first ten elements x(1:10). The corrected pointer assignment above has this.
If you prefer avoiding a pointer, then the UNION/MAP is an option depending on compiler. It was added to gfortran a while ago... then you can think of the array as a rank=2 but also use the vector (Rank=1) for SIMD operations.
All this assumes that one wants to avoid pointers...

In (Free) Pascal, can a function return a value that can be modified without dereference?

In Pascal, I understand that one could create a function returning a pointer which can be dereferenced and then assign a value to that, such as in the following (obnoxiously useless) example:
type ptr = ^integer;
var d: integer;
function f(x: integer): ptr;
begin
f := #x;
end;
begin
f(d)^ := 4;
end.
And now d is 4.
(The actual usage is to access part of a quite complicated array of records data structure. I know that a class would be better than an array of nested records, but it isn't my code (it's TeX: The Program) and was written before Pascal implementations supported object-orientation. The code was written using essentially a language built on top of Pascal that added macros which expand before the compiler sees them. Thus you could define some macro m that takes an argument x and expands into thearray[x + 1].f1.f2 instead of writing that every time; the usage would be m(x) := somevalue. I want to replicate this functionality with a function instead of a macro.)
However, is it possible to achieve this functionality without the ^ operator? Can a function f be written such that f(x) := y (no caret) assigns the value y to x? I know that this is stupid and the answer is probably no, but I just (a) don't really like the look of it and (b) am trying to mimic exactly the form of the macro I mentioned above.
References are not first class objects in Pascal, unlike languages such as C++ or D. So the simple answer is that you cannot directly achieve what you want.
Using a pointer as you illustrated is one way to achieve the same effect although in real code you'd need to return the address of an object whose lifetime extends beyond that of the function. In your code that is not the case because the argument x is only valid until the function returns.
You could use an enhanced record with operator overloading to encapsulate the pointer, and so encapsulate the pointer dereferencing code. That may be a good option, but it very much depends on your overall problem, of which we do not have sight.

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.

pointer as a dummy argument

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.

Resources