RESHAPEing with C_F_POINTER and C_LOC

In an effort to RESHAPE some big arrays without the memory cost of, well, RESHAPEing arrays, a colleague pointed me to this posting on Intel’s board that says how to use C_F_POINTER to RESHAPE an array without the cost. Thinking that looked what I want to do (just much, much bigger), I took the example code seen in the second reply and tried it out with PGI. When I did I received:

> pgf90 trial.f90
PGF90-S-0074-Illegal number or type of arguments to c_f_pointer - keyword argument cptr (trial.f90: 10)

So, I thought maybe PGI wasn’t as lax (if that’s right?) as Intel and wanted r3_ to be (as in the first reply):

integer, allocatable, target :: r3_(:,:,:)

but, upon compilation, I get the same severe output.

I’ve checked the FAQ, and it says C_F_POINTER and C_LOC are supported.

Is there some flag I need to pass along to get this to work with PGI? Or is this use of C_F_POINTER in this way an Intel method, and is there a PGI way to code such a task?

Hi Matt,

Can you send ‘trial.f90’ to PGI Customer Service (trs@pgroup.com) and ask them to forward it to me? Unfortunately there were problems with our first implementation of procedure pointers. We have several fixes going into the next build (9.0-4) and I’d like to see if this fixes your issue as well. More importantly, if it doesn’t, then I can get it to our engineers.

Thanks,
Mat

Hi Matt,

I have confirmed that this is a bug and filed TPR#16064.

Note that the issue is that we are not accepting C_LOC() as a valid argument for C_F_POINTER’s cptr. The work around is to create a temporary cptr type variable, store the result of C_LOC() into this temp, and pass the temp to C_F_POINTER.

Thank you for the report,
Mat

Zombie thread…REACTIVATE!

I seem to have re-encountered this bug. To wit, if you make a simple program:

program test

   use, intrinsic :: iso_c_binding

   implicit none

   real, pointer :: ptr(:,:) => NULL()
   real, pointer :: uin(:,:,:) => NULL()

   integer, parameter :: nx = 4
   integer, parameter :: ny = 5

   integer :: i, j

   allocate(ptr(nx,ny))

   forall (i=1:nx,j=1:ny) ptr(i,j) = 10*i+j

   write (*,*) 'shape(ptr): ', shape(ptr)
   write (*,'(a,x,z32)') ' loc(ptr(1,1)): ', loc(ptr(1,1))
   write (*,*) 'ptr: ', ptr

   call c_f_pointer(c_loc(ptr(1,1)),uin,[nx,ny,1])

   write (*,*) 'shape(uin): ', shape(uin)
   write (*,'(a,x,z32)') ' loc(uin(1,1,1)): ', loc(uin(1,1,1))
   write (*,*) 'uin: ', uin

   deallocate(ptr)

end program test

Now we can run in Intel:

(1450) $ ifort -V
Intel(R) Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 16.0.2.181 Build 20160204
Copyright (C) 1985-2016 Intel Corporation.  All rights reserved.

(1451) $ ifort test.F90
(1452) $ ./a.out
 shape(ptr):            4           5
 loc(ptr(1,1)):                   6DE060
 ptr:    11.00000       21.00000       31.00000       41.00000    
   12.00000       22.00000       32.00000       42.00000       13.00000    
   23.00000       33.00000       43.00000       14.00000       24.00000    
   34.00000       44.00000       15.00000       25.00000       35.00000    
   45.00000    
 shape(uin):            4           5           1
 loc(uin(1,1,1)):                   6DE060
 uin:    11.00000       21.00000       31.00000       41.00000    
   12.00000       22.00000       32.00000       42.00000       13.00000    
   23.00000       33.00000       43.00000       14.00000       24.00000    
   34.00000       44.00000       15.00000       25.00000       35.00000    
   45.00000

In gfortran:

(1461) $ gfortran --version
GNU Fortran (GCC) 5.3.0
Copyright (C) 2015 Free Software Foundation, Inc.

GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of GNU Fortran
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING

(1462) $ gfortran test.F90
(1463) $ ./a.out
 shape(ptr):            4           5
 loc(ptr(1,1)):                            605F80
 ptr:    11.0000000       21.0000000       31.0000000       41.0000000       12.0000000       22.0000000       32.0000000       42.0000000       13.0000000       23.0000000       33.0000000       43.0000000       14.0000000       24.0000000       34.0000000       44.0000000       15.0000000       25.0000000       35.0000000       45.0000000    
 shape(uin):            4           5           1
 loc(uin(1,1,1)):                            605F80
 uin:    11.0000000       21.0000000       31.0000000       41.0000000       12.0000000       22.0000000       32.0000000       42.0000000       13.0000000       23.0000000       33.0000000       43.0000000       14.0000000       24.0000000       34.0000000       44.0000000       15.0000000       25.0000000       35.0000000       45.0000000

And in good old nagfor (though I had to comment out the loc print):

(1470) $ nagfor -V
NAG Fortran Compiler Release 6.0(Hibiya) Build 1064
Product NPL6A60NA for x86-64 Linux
Copyright 1990-2015 The Numerical Algorithms Group Ltd., Oxford, U.K.
(1471) $ nagfor test.F90
NAG Fortran Compiler Release 6.0(Hibiya) Build 1064
[NAG Fortran Compiler normal termination]
(1472) $ ./a.out
 shape(ptr):  4 5
 ptr:   11.0000000  21.0000000  31.0000000  41.0000000  12.0000000  22.0000000  32.0000000  42.0000000  13.0000000  23.0000000  33.0000000  43.0000000  14.0000000  24.0000000  34.0000000  44.0000000  15.0000000  25.0000000  35.0000000  45.0000000
 shape(uin):  4 5 1
 uin:   11.0000000  21.0000000  31.0000000  41.0000000  12.0000000  22.0000000  32.0000000  42.0000000  13.0000000  23.0000000  33.0000000  43.0000000  14.0000000  24.0000000  34.0000000  44.0000000  15.0000000  25.0000000  35.0000000  45.0000000

But PGI:

(1480) $ pgfortran -V

pgfortran 16.3-0 64-bit target on x86-64 Linux -tp haswell 
The Portland Group - PGI Compilers and Tools
Copyright (c) 2016, NVIDIA CORPORATION.  All rights reserved.
(1481) $ pgfortran test.F90
(1482) $ ./a.out
 shape(ptr):             4            5
 loc(ptr(1,1)):                            606E60
 ptr:     11.00000        21.00000        31.00000        41.00000     
    12.00000        22.00000        32.00000        42.00000     
    13.00000        23.00000        33.00000        43.00000     
    14.00000        24.00000        34.00000        44.00000     
    15.00000        25.00000        35.00000        45.00000    
 shape(uin):             4            5            1
 loc(uin(1,1,1)):                  41A8000041300000
Segmentation fault (core dumped)

So TPR#16064 has been regressed. I have access to some old compilers and PGI 11.10 likes it, as does 12.10, but PGI 13.10 does not. So somewhen in 2013, it got undone.

Note, that if you do the suggestion of doing:

   cptr = c_loc(ptr(1,1))
   call c_f_pointer(cptr,uin,[nx,ny,1])

then all works as expected. Huzzah!

Matt,

Thanks for that. It appears to have stopped working between the 13.6 and 13.7 release. It has been assigned TPR 22461.

dave

Matt,

This problem was logged as TPR 22461, and has been corrected in the
current 16.9 release.

Let’s hope it does not reactivate.

dave