replica nfl jerseysreplica nfl jerseyssoccer jerseyreplica nfl jerseys forums.silverfrost.com :: View topic - Using un-allocated arrays as subroutine arguments
forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Using un-allocated arrays as subroutine arguments

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Thu Jun 12, 2014 4:10 am    Post subject: Using un-allocated arrays as subroutine arguments Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8210
Location: Salford, UK

PostPosted: Thu Jun 12, 2014 8:07 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Thu Jun 12, 2014 10:37 am    Post subject: Reply with quote

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
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Thu Jun 12, 2014 6:48 pm    Post subject: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Fri Jun 13, 2014 1:45 am    Post subject: Reply with quote

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
View user's profile Send private message
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Fri Jun 13, 2014 8:20 am    Post subject: Re: Reply with quote

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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2615
Location: Sydney

PostPosted: Fri Jun 13, 2014 9:36 am    Post subject: Reply with quote

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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8210
Location: Salford, UK

PostPosted: Fri Jun 13, 2014 3:59 pm    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
davidb



Joined: 17 Jul 2009
Posts: 560
Location: UK

PostPosted: Fri Jun 13, 2014 5:18 pm    Post subject: Re: Reply with quote

[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
View user's profile Send private message
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 8210
Location: Salford, UK

PostPosted: Sat Jun 14, 2014 7:33 am    Post subject: Reply with quote

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
View user's profile Send private message AIM Address
simon



Joined: 05 Jul 2006
Posts: 299

PostPosted: Sat Jun 14, 2014 9:25 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
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