F95: Possible to return an allocatable array?
Author 
Message 
Peter C. Chapi #1 / 34

F95: Possible to return an allocatable array?
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

Fri, 17 Jun 2005 10:16:19 GMT 


#2 / 34

F95: Possible to return an allocatable array?

Wed, 18 Jun 1902 08:00:00 GMT 


David Fran #3 / 34

F95: 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 


Alan Mille #4 / 34

F95: 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.
Has a value been determined for count at this stage? It may be that the compiler has set count to zero; if so, the allocated size for your array will be zero. Quote: > 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
 Alan Miller http://users.bigpond.net.au/amiller Retired Statistician

Fri, 17 Jun 2005 18:24:36 GMT 


David Fran #5 / 34

F95: 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 


Peter C. Chapi #6 / 34

F95: Possible to return an allocatable array?
Quote: > > FUNCTION compute_primes(n) > > IMPLICIT NONE > > INTEGER, ALLOCATABLE, DIMENSION(:) :: compute_primes > > INTEGER, INTENT(IN) :: n > > INTEGER :: count > > ! Find the primes and count them. > Has a value been determined for count at this stage? > It may be that the compiler has set count to zero; if so, the allocated size > for your array will be zero. > > ALLOCATE(compute_primes(count))
Yes, definitely. Using the oldest debugging method in the book, I added a print statement just before the ALLOCATE like this PRINT *, count And it prints an appropriate value. Peter Quote: > > ! 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

Fri, 17 Jun 2005 20:24:07 GMT 


Peter C. Chapi #7 / 34

F95: 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 #8 / 34

F95: 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 #9 / 34

F95: 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 


#10 / 34

F95: Possible to return an allocatable array?

Wed, 18 Jun 1902 08:00:00 GMT 


Richard Main #11 / 34

F95: Possible to return an allocatable array?
Quote: > 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?).
It does matter, although you can do it either way. If you put it in a module (which I generally recommend), then you must remove the above interface body. USEing the module is sufficient to provide the explicit interface. Having the interface body in that case would actually be illegal; you are not allowed to redeclare things that you USE from a module  all of their properties come from the USE. If you have it as an external procedure (i.e. not in a module), then the interface body as you wrote it is necessary and lookd correct to my quick glance. Quote: > My program compiles without errors or warnings using Lahey Fortran 95 > v5.70b on Win2k.
I don't recall whether or not that version implements allocatable function results or not. Do be aware that allocatable function results are not part of the base Fortran 95 standard. They are part of a "TR", which is in essence an official extension to the f95 standard and is "promised" to be included in f2k. An increasing number of recent f95 compilers do implement that TR. I assume, since it compiled without complaint, that Lahey 5.7 must be among those. I mention the point just so that you are aware of it. Quote: > 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?
See my above comment about allocatable function results. But I bet that's not directly the issue here. Instead, I focus on the result = .... Your result is an allocatable array, which you never allocate. Note that (it's name notwithstanding), your variable named result is *NOT* itself the function result. The function result is part of the righthand side of the assignment statement. In this case, it happens to be the whole of the righthand side, which can lead to confusions like yours, but it is still important to realize that the righthand side and lefthand side are separate things. This might be more apparent in a (somewhat silly, but I use it to make the point) case like twice_result = 2*compute_primes(n) In this case, I hope it is clear that twice_result isn't the result of the function. The result of the function is to evaluate the expression on the righthand side, which is then assigned to the lefthand side. The principle is the same without the "2*"; the expression is then a trivial case of a single primary, but that is still an expression. So your real problem isn't the function result. It is that you can't assign to an allocatable variable without first allocating it. The allocation isn't automatic. (Some people would like to enhance the language to allow this, but it isn't allowed presently). Your program would probbaly work if you bypassed the variable named result and just wrote PRINT *, SIZE(compute_primes(n)), "primes found." but that wouldn't suffice if you then wanted to do something more with the primes. It would also work (though I wouldn't recommend this approach) if you invoked the function twice as in allocate(result(size(compute_primes(n)))) result = compute_primes(n) Best, in my opinion, would be to make compute_primes into a subroutine with result and n as arguments. With result as an actual argument, the allocation in the subroutine *DOES* allocate result itself. You'll also need an explicit interface for a subroutine that has an allocatable dummy argument; as with the function, either put the procedure in a module or wtite an interface body (but not both). Allocatable arguments are part of the same TR that introduced allocatable function results, so I presume that any compiler that supports one will also support the other. That wouldn't necessarily have to be the case in theory, but it is the way I'd expect things to be.  Richard Maine  Good judgment comes from experience; email: my last name at host.domain  experience comes from bad judgment. host: altair, domain: dfrc.nasa.gov   Mark Twain

Sat, 18 Jun 2005 00:10:00 GMT 


#12 / 34

F95: Possible to return an allocatable array?

Wed, 18 Jun 1902 08:00:00 GMT 


Gerald F. Thoma #13 / 34

F95: Possible to return an allocatable array?
Peter: You might find http://www.utm.edu/research/primes/howmany.shtml helpful. Ciao, Gerry T.
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

Sat, 18 Jun 2005 00:56:09 GMT 


Peter C. Chapi #14 / 34

F95: Possible to return an allocatable array?
Quote: > How about showing your C program that doesnt allocate in program but in its > function, yet can deallocate in its main?
In C I could get the effect I was after like this int *compute_primes(int n, int *count) { int *result; // Compute the primes and store into *count how many there are. I have // to return the count as a separate result since C arrays don't know // their size. // *count = ... // Allocate space. result = malloc(*count * sizeof(int)); // Fill up the array 'result'. return result; Quote: }
int main(void) { int *numbers; int count; numbers = compute_primes(n, &count); // Use the array numbers of size 'count'. // Release the allocation here. free(numbers); return 0; Quote: }
Peter

Sat, 18 Jun 2005 07:12:52 GMT 


Peter C. Chapi #15 / 34

F95: 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 


Page 1 of 3

[ 34 post ] 

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