 |
forums.silverfrost.com Welcome to the Silverfrost forums
|
View previous topic :: View next topic |
Author |
Message |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Thu Jun 12, 2014 4:10 am Post subject: Using un-allocated arrays as subroutine arguments |
|
|
I have been trying to use allocatable variables as subroutine arguments and I am investigating what happens if the arrays have not previously been allocated.
I am not sure if the Fortran 95 standard allows un-allocated arrays as arguments, but FTN95 Ver 7.00 appears to do this.
The following example shows the test code I have written.
Code: | ! Program to test allocate
!
call test_alloc
end
subroutine test_alloc
!
real*8, allocatable, dimension(:,:) :: aa, bb
!
allocate ( aa(4,7) )
!
if (allocated (aa)) then
write (*,*) 'aa is allocated'
else
write (*,*) 'aa is NOT allocated'
end if
!
if (allocated (bb)) then
write (*,*) 'bb is allocated'
else
write (*,*) 'bb is NOT allocated'
end if
!
write (*,*) 'Size test 1'
write (*,*) size (aa)
write (*,*) size (bb) ! this gives a non-zero result with /debug
! but fails with /check
! should it work and return 0 ?
!
! Call routine with un-allocated array bb
call test_call (aa, bb)
!
write (*,*) 'aa=',aa(1,1)
!
write (*,*) 'Size test 2'
write (*,*) size (aa)
write (*,*) size (bb)
!
end subroutine test_alloc
subroutine test_call (aa, bb)
!
real*8 aa(4,*), bb(6,*) ! what declaration should work for Fortran 95 ?
!
aa(1,1) = 1.0
!
! The following will compile and work with FTN95 /debug
if (allocated (aa)) then
write (*,*) 'aa is allocated'
else
write (*,*) 'aa is NOT allocated'
end if
!
if (allocated (bb)) then
write (*,*) 'bb is allocated'
else
write (*,*) 'bb is NOT allocated'
end if
!
end subroutine test_call |
The above program aa.f90:
works for ftn95 aa /lgo
works for ftn95 aa /debug /lgo
fails for ftn95 aa /check /lgo
I think that FTN95 may not conform to the Fortran 95 standard ?
I am trying to avoid making the arrays allocated, so that I can utilise the status of .not. allocated (bb) in the subroutine.
I think F2003 and F2008 have changed the way these arguments may be declared and handled.
Any comments ?
John |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8210 Location: Salford, UK
|
Posted: Thu Jun 12, 2014 8:07 am Post subject: |
|
|
To check for standard conforming code, use /ISO on the command line.
FTN95 gives a warning when /ISO is not used and an error report when it is used.
It looks like /CHECK is not clever enough to handle this code. |
|
Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Thu Jun 12, 2014 10:37 am Post subject: |
|
|
Paul,
Thanks for the suggestion. I used the /ISO which indicated that I had a problem with the ALLOCATED test in the subroutine.
From the Fortran 95 Draft Standard J3/97-007R2:
13.14.9 The ALLOCATED intrinsic can only be applied to an allocatable array.
5.1 The ALLOCATABLE attribute may be used only when declaring an array that is not a dummy argument or a function result.
This implies that I can not test the allocated attribute of an aray in a subroutine.
In the case of the SIZE () intrinsic;
13.14.101 SIZE (ARRAY [, DIM]) Returns the extent of an array along a specified dimension or the total number of elements in the array.
ARRAY may be of any type. It shall not be scalar. It shall not be a pointer that is disassociated or an allocatable array that is not allocated.
This implies that I can not use SIZE on an array that is not allocated.
In the case of an actual argument to a subroutine call being ALLOCATABLE, I can not find any specification in the standard relating to the actual argument must be ALLOCATED.
The basic problem with the code I have is can I use an un-allocated array as the argument in a subroutine call ?
John |
|
Back to top |
|
 |
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Thu Jun 12, 2014 6:48 pm Post subject: |
|
|
Hello John,
I don't think the Fortran standard allows you to use allocated() on assumed size dummy argument arrays (such as aa(4,*)). As your code stands there would be no way for the compiler to know about the allocation status of aa if your test_call was compiled in a separate file.
You would need to use assumed shape (aa(:,:)) and then you would also need an explicit interface to test_call().
Something like this should work:
Code: |
module foo
contains
subroutine process(a)
real, allocatable :: a(:)
if (allocated(a)) then
! ... do something if a is allocated
else
! ... do something if a not allocated
end if
end subroutine process
end module foo
program test
use foo
real, allocatable :: a(:)
call process(a)
end
|
If there is a bug in FTN95 preventing allocated() from working (I don't think there is), you can allocate a zero size array and test this to see if the array is in use. But you would still need to use assumed shape and an explicit interface.
Code: |
allocate(aa(0))
if (size(aa) > 0) then
! ... do something if a is being used
else
! ... do something if a not being used
end if
|
David. _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl
Last edited by davidb on Fri Jun 13, 2014 8:11 am; edited 1 time in total |
|
Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Fri Jun 13, 2014 1:45 am Post subject: |
|
|
David,
Thanks for your comments. The problem I have is that the following program appears to work with /debug, although it gives a warning about the use of ALLOCATED().
Code: | ! Program to test use of allocated intrinsic
!
real*8, allocatable, dimension(:,:) :: aa, bb
!
allocate ( aa(4,7) )
!
call test_call (aa, bb)
!
write (*,*) 'aa=',aa(1,1)
!
end
subroutine test_call (aa, bb)
!
real*8 aa(4,*), bb(6,*) ! what declaration should work for Fortran 95 ?
!
aa(1,1) = 1.0
!
! The following will compile and work with FTN95 /debug
if (allocated (aa)) then
write (*,*) 'aa is allocated'
else
write (*,*) 'aa is NOT allocated'
end if
!
if (allocated (bb)) then
write (*,*) 'bb is allocated'
else
write (*,*) 'bb is NOT allocated'
end if
!
end subroutine test_call |
My problem is:
Can I assume that the "call test_call (aa, bb)" can be expected to work, where bb has not been allocated ? (ie not give an access violation error)
Can I assume that allocated (bb) will give a valid result, although I can use other tests to identify if bb has not been allocated.
The alternative is to provide tests for all allocatable arrays, before the call test_call takes place. For example I could do this for bb in the following example, although I would subsequently need to test and de-allocate bb (and all similar arrays) when it is required to be allocated.
Code: | ! Program to test use of allocated intrinsic
!
real*8, allocatable, dimension(:,:) :: aa, bb
!
allocate ( aa(4,7) )
!
! prepare for test_call
if (.not. allocated (aa)) allocate ( aa(4,0) )
if (.not. allocated (bb)) allocate ( bb(6,0) )
call test_call (aa, bb)
!
write (*,*) 'aa=',aa(1,1)
!
end |
I was trying to avoid the complexity of manageing (and reporting) the testing for allocation of arrays like bb, but it probably looks like the best approach.
I should also look at F2003/2008 and see how the standard has managed this.
John |
|
Back to top |
|
 |
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Fri Jun 13, 2014 8:20 am Post subject: Re: |
|
|
JohnCampbell wrote: |
Can I assume that the "call test_call (aa, bb)" can be expected to work, where bb has not been allocated ? (ie not give an access violation error)
Can I assume that allocated (bb) will give a valid result, although I can use other tests to identify if bb has not been allocated.
|
No to both. It isn't valid Fortran
If the code works with /DEBUG then that is just a quirk of this compiler.
You always need the ALLOCATABLE attribute on the array to use ALLOCATED. To do what you want, the dummy array must have the allocatable attribute like this:
Code: |
subroutine test_call(aa, bb)
real*8, allocatable :: aa(:), bb(:)
if (allocated(aa)) then
write(*,*) 'aa is allocated'
else
write(*,*) 'aa is NOT allocated'
end if
if (allocated(bb)) then
write(*,*) 'bb is allocated'
else
write(*,*) 'bb is NOT allocated'
end if
end subroutine test_call
|
_________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2615 Location: Sydney
|
Posted: Fri Jun 13, 2014 9:36 am Post subject: |
|
|
Quote: | davidb wrote: You always need the ALLOCATABLE attribute on the array to use ALLOCATED. |
Unfortunately, Clause 5.1 of the standard includes : The ALLOCATABLE attribute may be used only when declaring an array that is not a dummy argument or a function result.
This implies that I can not define the dummy argument as allocatable and so can't test the allocated attribute of the array in the subroutine.
I must test it before the routine is called.
I can't see a way around this.
John |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8210 Location: Salford, UK
|
Posted: Fri Jun 13, 2014 3:59 pm Post subject: |
|
|
My understanding is that this is a deliberate FTN95 extension to the standard.
The reason behind the /ISO switch is that FTN95 has some non standard extensions and so one needs to use /ISO to ensure conformance with the Standard.
Naturally for portable code one should use /ISO but if you are locked into FTN95 then the extensions are there to use.
Admittedly there is a problem with /CHECK but this ought to be fixable.
However, I have not followed this thread closely so I may be missing the point. |
|
Back to top |
|
 |
davidb
Joined: 17 Jul 2009 Posts: 560 Location: UK
|
Posted: Fri Jun 13, 2014 5:18 pm Post subject: Re: |
|
|
[quote="JohnCampbell"] Quote: | Unfortunately, Clause 5.1 of the standard includes : The ALLOCATABLE attribute may be used only when declaring an array that is not a dummy argument or a function result.
John |
This is the case for Fortran 95, but the allocatable attribute is allowed in Fortran 2003. You have stumbled across a deficiency in the Fortran 95 language that has been corrected in Fortran 2003.
Paul,
I am not sure that you can implement this as an extension to the standard. It is forbidden to use the allocated() intrinsic on an array which does not have the allocatable attribute. In Fortran 95, only allocatable deferred shape arrays can be used. In Fortan 2003 (and later), allocatable deferred shape and allocatable dummy arrays can be used.
Even if you break the rules as an extension, there is no easy way to get the allocation status of an assumed size array when a subroutine is compiled in a separate file. _________________ Programmer in: Fortran 77/95/2003/2008, C, C++ (& OpenMP), java, Python, Perl |
|
Back to top |
|
 |
PaulLaidler Site Admin
Joined: 21 Feb 2005 Posts: 8210 Location: Salford, UK
|
Posted: Sat Jun 14, 2014 7:33 am Post subject: |
|
|
David
I have not looked at this closely but my comments relate to the current state of FTN95. As I understanding it, FTN95 can provide any extensions that are feasible but I don't know if this is the case here.
John
If this is a significant issue then I can log it for further investigation if you wish. |
|
Back to top |
|
 |
simon
Joined: 05 Jul 2006 Posts: 299
|
Posted: Sat Jun 14, 2014 9:25 am Post subject: |
|
|
If you make aa and bb pointer arrays I think you should be able to pass them as unallocated, and keep them as allocated after return from the subroutine. But you do need to nullify them first, otherwise the results are unexpected. There is some way of avoiding the compilers warning message about the use of allocated on non-allocatable arrays (withohut simply suppressing the message), but I can't remember what that is right now
Code: | ! Program to test use of allocated intrinsic
!
real*8, pointer, dimension(:,:) :: aa, bb
!
nullify (aa)
nullify (bb)
allocate ( aa(4,7) )
!
call test_call (aa, bb)
!
write (*,*) 'aa=',aa(1,1)
!
contains
subroutine test_call (aa, bb)
!
real*8, pointer, dimension(:,:) aa, bb ! what declaration should work for Fortran 95 ?
!
aa(1,1) = 1.0
!
! The following will compile and work with FTN95 /debug
if (allocated (aa)) then
write (*,*) 'aa is allocated'
else
write (*,*) 'aa is NOT allocated'
end if
!
if (allocated (bb)) then
write (*,*) 'bb is allocated'
else
write (*,*) 'bb is NOT allocated'
end if
!
end subroutine test_call
end
|
|
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|