Possible to return an allocatable array?
Author 
Message 
David Fran #1 / 40

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 rewrite returning both count and numbers is best way to tackle this problem.. note my rewritten 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 


David Fran #2 / 40

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 


David Fran #3 / 40

Possible to return an allocatable array?
See my previous message..

Fri, 17 Jun 2005 19:13:43 GMT 


Peter C. Chapi #4 / 40

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 


David Fran #5 / 40

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 


David Fran #6 / 40

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 


Peter C. Chapi #7 / 40

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 


David Fran #8 / 40

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 


Peter C. Chapi #9 / 40

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 


glen herrmannsfeld #10 / 40

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 


David Fran #11 / 40

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 


James J. Weinka #12 / 40

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 


glen herrmannsfeld #13 / 40

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 


Page 1 of 3

[ 40 post ] 

Go to page:
[1]
[2] [3] 
