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

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"

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

Wed, 18 Jun 1902 08:00:00 GMT
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))

> 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"

>   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
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.

- Show quoted text -

Quote:
>    ALLOCATE(compute_primes(count))

> 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"

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

> > 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"

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

> > END PROGRAM primes

Fri, 17 Jun 2005 20:24:07 GMT
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
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
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
F95: Possible to return an allocatable array?

Wed, 18 Jun 1902 08:00:00 GMT
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"

>   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 right-hand side of the assignment statement.  In this case, it
happens to be the whole of the right-hand side, which can lead to
confusions like yours, but it is still important to realize that the
right-hand side and left-hand 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 right-hand side, which is then assigned to the
left-hand 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
F95: Possible to return an allocatable array?

Wed, 18 Jun 1902 08:00:00 GMT
F95: Possible to return an allocatable array?
Peter:

You might find

http://www.utm.edu/research/primes/howmany.shtml

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))

> 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"

>   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
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
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]

Relevant Pages