Possible to return an allocatable array? 
Author Message
 Possible to return an allocatable array?



Quote:

> Hello!

> I'm attempting to teach myself some of fortran's newer features. To this
> end I am working on a (trivial) program to compute all prime numbers
> less than or equal to a given integer. I want to write a function that
> will compute the primes and return them in an array. (I'm not concerned
> right now about how good an idea this is... I'm just practicing with
> Fortran language features here). Since I don't know how many primes
> exist less than a given value, my thought was to store them in an
> allocatable array (the size of which I compute) and then return that.
> Here is what my function looks like in part

> FUNCTION compute_primes(n)
>   IMPLICIT NONE
>   INTEGER, ALLOCATABLE, DIMENSION(:) :: compute_primes
>   INTEGER, INTENT(IN)   :: n
>   INTEGER               :: count

>   ! Find the primes and count them.

>    ALLOCATE(compute_primes(count))

>   ! Load up the compute_primes array with the answer.

> END FUNCTION compute_primes

> Apparently in order for me to use this function it needs to have an
> explicit interface in the calling program unit. Accordingly my main
> program unit looks like (this is complete)

> PROGRAM primes
>   IMPLICIT NONE

>   INTEGER :: n
>   INTEGER, ALLOCATABLE, DIMENSION(:) :: result
>   INTERFACE
>      FUNCTION compute_primes(n)
>        IMPLICIT NONE
>        INTEGER, INTENT(IN) :: n
>        INTEGER, ALLOCATABLE, DIMENSION(:) :: compute_primes
>      END FUNCTION compute_primes
>   END INTERFACE

>   PRINT *, "Enter the upper bound"
>   READ *, n

>   result = compute_primes(n)
>   PRINT *, SIZE(result), "primes found."

> END PROGRAM primes

> I do not have the compute_primes function in a module (should that
> matter?).

> My program compiles without errors or warnings using Lahey Fortran 95
> v5.70b on Win2k. However, when it runs it always outputs "0 primes
> found." I'm confident that my compute_primes function is working
> properly. I can print out correct results from inside the function. Is
> it simply impossible to return an allocatable array? If so, why wouldn't
> the compiler have objected to my attempt to do so? What am I missing?

> Thanks!

> Peter

As written above I can confirm that CVF also returns "0 primes found"
Below version cheats in declaring a max size program array to "catch" the
results, (perhaps F2K will automatically allocate the size of the returned
array?) but IMO below re-write returning both count and numbers is best way
to tackle this problem..
note my re-written function STILL allocates the size of its output and using
a module eliminates the explicit interfacing mess..
------------------------------------------------------
module primes_1
contains
function compute_primes(n)  result(numbers)
integer,intent(in)  :: n
integer,allocatable :: numbers(:)
integer :: count
count = 0
if (n == 5) count = 3    ! #primes determined somehow
allocate ( numbers(0:count) )
numbers = [ count, 1,3,5 ]
end function
end module primes_1

program primes
use primes_1
integer :: n, nums(0:1000)  ! declare max returned numbers
nums = compute_primes(5)
n = nums(0)
write (*,'(a,i3)')    '#primes= ', n                     ! outputs  #primes=
3
write (*,'(a,1000i3)') 'numbers= ', nums(1:n)  ! outputs  numbers=  1  3  5
end program
 -------------------------------------------------



Fri, 17 Jun 2005 17:57:42 GMT  
 Possible to return an allocatable array?
IMO, below alternative version without using ALLOCATE is preferable for
speed/clarity/etc.
--------------------------------------------------------
module primes_1
contains
function compute_primes(n,m)  result(numbers)
integer,intent(in) :: n, m
integer ::numbers(0:m)  ! result automatically agrees with callers
expectations of max size
integer :: count
count = 0
if (n == 5) count = 3    ! #primes determined somehow
numbers(0:count) = [ count, 1,3,5 ]
end function
end module primes_1

program primes
use primes_1
integer,parameter :: maxcount = 1000
integer :: count, nums(0:maxcount)

nums = compute_primes(5,maxcount)
count = nums(0)
write (*,'(a,i3)')    '#primes= ', count
write (*,'(a,<maxcount>i3)') 'numbers= ', nums(1:count)
end program



Fri, 17 Jun 2005 19:01:12 GMT  
 Possible to return an allocatable array?
See my previous message..


Fri, 17 Jun 2005 19:13:43 GMT  
 Possible to return an allocatable array?



Quote:
> IMO, below alternative version without using ALLOCATE is preferable for
> speed/clarity/etc.

Yes, I understand this general approach and it makes sense. Still it
seems inelegant in this case. Although the caller can put an upper bound
on the required size of the array, the caller doesn't really know the
right size. It would seem (to me anyway) that allocatable arrays should
be able to address the problem. Of course it could be argued that it
isn't very elegant to allocate an array in one program unit and
deallocate it in another. But I have a C background (does it show?) and
that form of inelegance seems normal to me. :-)

Peter



Fri, 17 Jun 2005 20:24:08 GMT  
 Possible to return an allocatable array?



Quote:



> > IMO, below alternative version without using ALLOCATE is preferable for
> > speed/clarity/etc.

> Yes, I understand this general approach and it makes sense. Still it
> seems inelegant in this case. Although the caller can put an upper bound
> on the required size of the array, the caller doesn't really know the
> right size. It would seem (to me anyway) that allocatable arrays should
> be able to address the problem. Of course it could be argued that it
> isn't very elegant to allocate an array in one program unit and
> deallocate it in another. But I have a C background (does it show?) and
> that form of inelegance seems normal to me. :-)

> Peter

re:  "isn't very elegant to allocte an array in one program unit and
deallocate it in another"

How about showing your C program that doesnt allocate in program but in its
function, yet can deallocate in its main?



Fri, 17 Jun 2005 21:07:40 GMT  
 Possible to return an allocatable array?
Well if returning a subset of a max array gives you heartburn, below
allowing a function to return a "global" result probably will give the
purists in this newsgroup heartburn as well, ha ha..
However, it does allow exact allocation of function determined array size
with the caller program seeing the same exact allocated array,  furthermore
its fast, and presents the most stability of all in regard to memory access
faults..
------------------------------------------------
module primes_1
integer,allocatable :: numbers(:)
end module primes_1
module primes_2
contains
function compute_primes(n)  result(count)
use primes_1
integer,intent(in) :: n
integer :: count
count = 0
if (n == 5) count = 3    ! #primes determined somehow
allocate ( numbers(count) )
numbers = [ 1,3,5 ]
end function
end module primes_2

program primes
use primes_1
use primes_2
integer :: count
count = compute_primes(5)  ! allocates numbers
write (*,*) '#primes= ', size(numbers), ' shud = ',count
write (*,*) 'numbers= ', numbers
end program



Fri, 17 Jun 2005 21:35:20 GMT  
 Possible to return an allocatable array?



Quote:
> Well if returning a subset of a max array gives you heartburn, below
> allowing a function to return a "global" result probably will give the
> purists in this newsgroup heartburn as well, ha ha..

I thought of this myself. In fact, a "clean" way to handle the global
data would be to bury in into an object of some suitable abstract type.
I could imagine a "prime_generator" type that contains private members
(what word does the Fortran community use?) as necessary to hold the
primes. I could then define suitable operations for the type that allow
the caller to find out how many primes there are and then later extract
them without having those primes recomputed. It seems like all of this
could be done quite neatly with a Fortran module. I may investigate that
approach since it will take me into uncharted territory (for me) and
that is, after all, the entire point of this exercise. :-)

Peter



Sat, 18 Jun 2005 07:12:54 GMT  
 Possible to return an allocatable array?
Peter,
You might think that we have exhausted solution possibilities for your
inquiry,  below indicates it aint so,
(in Fortran there are always several ways to "skin a cat")..

Below works with CVF 6.6b , it may not work with other compilers.
BTW, this may be first time anyone has posted such syntax here, (passing
caller's allocatable array to function and allowing it to allocate it) ..
------------------------------------------
module primes_1
contains
function compute_primes(n,numbers)  result(count)
integer,intent(in) :: n
integer,allocatable :: numbers(:)
integer :: count
count = 0
if (n == 5) count = 3    ! #primes determined somehow
allocate ( numbers(count) )
numbers = [ 2,3,5 ]
end function
end module primes_1

program primes
use primes_1
integer,allocatable :: nums(:)
integer :: count

count = compute_primes(5,nums)
write (*,*) '#primes= ', size(nums), ' shud = ',count
write (*,*) 'numbers= ', nums
end program



Sat, 18 Jun 2005 17:38:48 GMT  
 Possible to return an allocatable array?


Quote:
> You might think that we have exhausted solution possibilities for your
> inquiry,  below indicates it aint so,
> (in Fortran there are always several ways to "skin a cat")..

Yes, thanks for the code. I believe Richard Maine also mentioned the
idea of using allocatable arrays as arguments... although he said that
strictly speaking it also involved an extension to the current standard.

I appreciate all the comments I've received on this; they have been most
helpful. I definitely feel like I have a better idea about how
allocatable arrays work, at least, and the whole point of this exercise
was to learn more about that. I'm enjoying my explorations of Fortran
90/95 and look forward to more.

Thanks!

Peter



Sat, 18 Jun 2005 20:56:06 GMT  
 Possible to return an allocatable array?



Quote:



> > IMO, below alternative version without using ALLOCATE is
preferable for
> > speed/clarity/etc.

> Yes, I understand this general approach and it makes sense. Still
it
> seems inelegant in this case. Although the caller can put an
upper bound
> on the required size of the array, the caller doesn't really know
the
> right size. It would seem (to me anyway) that allocatable arrays
should
> be able to address the problem. Of course it could be argued that
it
> isn't very elegant to allocate an array in one program unit and
> deallocate it in another. But I have a C background (does it
show?) and
> that form of inelegance seems normal to me. :-)

I don't know why this is posted to comp.lang.pl1, but in PL/I they
are called CONTROLLED, and it is perfectly reasonable to return
a CONTROLLED array.   At least as reasonable as in C.

Also, this has been a PL/I feature since about 1966.

-- glen



Sun, 26 Jun 2005 17:19:31 GMT  
 Possible to return an allocatable array?

Quote:



> > isn't very elegant to allocate an array in one program unit and
> > deallocate it in another. But I have a C background (does it
> show?) and
> > that form of inelegance seems normal to me. :-)

> I don't know why this is posted to comp.lang.pl1, but in PL/I they
> are called CONTROLLED, and it is perfectly reasonable to return
> a CONTROLLED array.   At least as reasonable as in C.

> Also, this has been a PL/I feature since about 1966.

> -- glen

Prove it by giving fellow pliers an example of this CONTROLLED array,
in a useful routine like below which I provided last week in response to a C++ guy
challenging Fortran'ners to translate his cryptic numFromString C++ routine

---------------------------------------------------------------------------
module test_1
contains
function numFromString (s,nan,proxy, v)  result (count)
character(*) :: s, nan
real(8) :: proxy
real,allocatable :: v(:)
integer :: i, k, n, count
count = 1
n = len_trim(s)
do k = 1,n
   if (s(k:k) == ',') count = count+1
end do
allocate ( v(count) )
i = 1 ; count = 0
do k = 1,n
   if (s(k:k) == ',' .or. k == n) then
      count = count+1
      read (s(i:k),*,err=1) v(count) ; go to 2
    1  v(count) = proxy    ! use proxy if data error
    2  i = k+1             ! next data field start
   end if
end do
end function
end module

program test
use test_1
real,allocatable :: vec(:)
integer :: count
character(3) :: nan = 'nil'
real(8) :: proxy = -1.

count = numFromString("1.223,nil,22.33,0.08,nil", nan, proxy, vec)
write (*,'(a,i0)') '#items in string = ',count
write (*,'(a,<count>f7.3)') 'vector = ',vec
end program

above outputs
1.223  -1.000  22.330   0.080  -1.000



Sun, 26 Jun 2005 20:42:49 GMT  
 Possible to return an allocatable array?

Quote:

> I don't know why this is posted to comp.lang.pl1, but in PL/I they
> are called CONTROLLED, and it is perfectly reasonable to return
> a CONTROLLED array.   At least as reasonable as in C.

> Also, this has been a PL/I feature since about 1966.

In PL/I, user written functions can only return scalars.  The only attributes
allowed in the RETURNS option or attribute are data attributes and alignment
attributes.  In other words those attributes that characterize a value as
distinct from the place where the value is stored.  Storage class attributes
such as CONTROLLED can only apply to named variables.  The storage used to hold
the returned value of a function depends on the implementation and is either a
machine register or a compiler generated anonymous variable which as far as I
know is always of the AUTOMATIC storage class unless you want to consider
compiler generated temporaries as a storage class of their own.


Mon, 27 Jun 2005 03:41:04 GMT  
 Possible to return an allocatable array?



Quote:

> > I don't know why this is posted to comp.lang.pl1, but in PL/I
they
> > are called CONTROLLED, and it is perfectly reasonable to return
> > a CONTROLLED array.   At least as reasonable as in C.

> > Also, this has been a PL/I feature since about 1966.

> In PL/I, user written functions can only return scalars.  The
only attributes
> allowed in the RETURNS option or attribute are data attributes
and alignment
> attributes.  In other words those attributes that characterize a
value as
> distinct from the place where the value is stored.  Storage class
attributes
> such as CONTROLLED can only apply to named variables.  The

storage used to hold

Quote:
> the returned value of a function depends on the implementation
and is either a
> machine register or a compiler generated anonymous variable which
as far as I
> know is always of the AUTOMATIC storage class unless you want to
consider
> compiler generated temporaries as a storage class of their own.

Oops.  I was using returns in the sense of modifying a parameter,
not as a function RETURNS value.

-- glen



Mon, 27 Jun 2005 04:17:21 GMT  
 
 [ 40 post ]  Go to page: [1] [2] [3]

 Relevant Pages 

1. F95: Possible to return an allocatable array?

2. Allocatable array as return value in function

3. How can I return an allocatable array?

4. f90 function returns structure with allocatable arrays

5. return value as an allocatable array

6. allocatable vs non-allocatable arrays

7. Allocatable array of allocatable defined types?

8. allocatable in dll possible?

9. Is it possible to create array of arrays

10. Array#sort! returns nil when array empty

11. java array return value not array in tcl

12. Allocatable Arrays in Fortran 90

 

 
Powered by phpBB® Forum Software