Is passing a RESHAPEd array to an intent(out) arg legal?

  • Follow


  Hello.

  Say I have

subroutine cache_add(data_to_add, n_data) 
  integer, intent(in) :: n_data
  integer, intent(in) :: data_to_add

  ! ... store data_to_add(1:n_data) somewhere
end subroutine

subroutine cache_retrieve(retrieve_buffer, n_data) 
  integer, intent(in)  :: n_data
  integer, intent(out) :: retrieve_buffer

  ! ... fill retrieve_buffer(1:n_data) with data from somewhere
end subroutine

  I am in a situation where I'd like to use these subroutines to store data contained in a 2-dimensional allocatable array, data2D(:,:), allocated to the size of n x n. The value of n is not known at compile time. I imagine the following is safe:

call cache_add(reshape(data2D, (/n*n/)), n*n)

and I hope this will create a temporary 1D array that will be filled with data from data2D, then get passed to cache_add(), copied from and finally destroyed.

  How do I accomplish the reverse with cache_retrieve()? I have a feeling that

call cache_retrieve(reshape(data2D, (/n*n/)), n*n)

is going to create a temporary 1D array that will perhaps be filled by cache_retrieve() but will then be destroyed without the data being ever copied to data2D. Am I right?

  If so, is there a way of accomplishing what I need without creating an allocatable 1D array, filling this with cache_retrieve(), assigning a reshaped version to data2D and deleting the allocatable 1D array?

thanks in advance,
- J.
0
Reply jack.erede (27) 5/31/2012 1:44:35 PM

Op donderdag 31 mei 2012 15:44:35 UTC+2 schreef jack....@gmail.com het volgende:
> Hello.
> 
>   Say I have
> 
> subroutine cache_add(data_to_add, n_data) 
>   integer, intent(in) :: n_data
>   integer, intent(in) :: data_to_add
> 
>   ! ... store data_to_add(1:n_data) somewhere
> end subroutine
> 
> subroutine cache_retrieve(retrieve_buffer, n_data) 
>   integer, intent(in)  :: n_data
>   integer, intent(out) :: retrieve_buffer
> 
>   ! ... fill retrieve_buffer(1:n_data) with data from somewhere
> end subroutine
> 
>   I am in a situation where I'd like to use these subroutines to store data contained in a 2-dimensional allocatable array, data2D(:,:), allocated to the size of n x n. The value of n is not known at compile time. I imagine the following is safe:
> 
> call cache_add(reshape(data2D, (/n*n/)), n*n)
> 
> and I hope this will create a temporary 1D array that will be filled with data from data2D, then get passed to cache_add(), copied from and finally destroyed.
> 
>   How do I accomplish the reverse with cache_retrieve()? I have a feeling that
> 
> call cache_retrieve(reshape(data2D, (/n*n/)), n*n)
> 
> is going to create a temporary 1D array that will perhaps be filled by cache_retrieve() but will then be destroyed without the data being ever copied to data2D. Am I right?
> 
>   If so, is there a way of accomplishing what I need without creating an allocatable 1D array, filling this with cache_retrieve(), assigning a reshaped version to data2D and deleting the allocatable 1D array?
> 
> thanks in advance,
> - J.

The compiler will most probably complain that the actual argument is 
not suitable. 

What you could do instead is turn cache_retrieve into a function:

data2D = reshape( cache_retrieve(), (/n, n/) )

(That will still create the 1D array as an intermediate result, but 
that should be not your concern - modulo the way you can implement the
cache_retrieve() function)

Regards,

Arjen
0
Reply arjen.markus895 (657) 5/31/2012 1:55:29 PM


On May 31, 11:44=A0pm, jack.er...@gmail.com wrote:
> =A0 Hello.
>
> =A0 Say I have
>
> subroutine cache_add(data_to_add, n_data)
> =A0 integer, intent(in) :: n_data
> =A0 integer, intent(in) :: data_to_add
>
> =A0 ! ... store data_to_add(1:n_data) somewhere
> end subroutine
>
> subroutine cache_retrieve(retrieve_buffer, n_data)
> =A0 integer, intent(in) =A0:: n_data
> =A0 integer, intent(out) :: retrieve_buffer
>
> =A0 ! ... fill retrieve_buffer(1:n_data) with data from somewhere
> end subroutine

Because you want to pass data to the subroutine,
the sensible thing to do is to make the dummy argument--
   intent (in out)
0
Reply louisa.hutch (142) 5/31/2012 2:47:23 PM

<jack.erede@gmail.com> wrote:

> subroutine cache_add(data_to_add, n_data) 
>   integer, intent(in) :: n_data
>   integer, intent(in) :: data_to_add
> 
>   ! ... store data_to_add(1:n_data) somewhere
> end subroutine
> 
> subroutine cache_retrieve(retrieve_buffer, n_data) 
>   integer, intent(in)  :: n_data
>   integer, intent(out) :: retrieve_buffer
> 
>   ! ... fill retrieve_buffer(1:n_data) with data from somewhere
> end subroutine
> 
>   I am in a situation where I'd like to use these subroutines to store
> data contained in a 2-dimensional allocatable array, data2D(:,:),
> allocated to the size of n x n. The value of n is not known at compile
> time. I imagine the following is safe:
> 
> call cache_add(reshape(data2D, (/n*n/)), n*n)
> 
> and I hope this will create a temporary 1D array that will be filled with
> data from data2D, then get passed to cache_add(), copied from and
> finally destroyed.

Yes, that's the most likely implementation.

>   How do I accomplish the reverse with cache_retrieve()? I have a feeling that
> 
> call cache_retrieve(reshape(data2D, (/n*n/)), n*n)
> 
> is going to create a temporary 1D array that will perhaps be filled by
> cache_retrieve() but will then be destroyed without the data being ever
> copied to data2D. Am I right?

Not really. The code is illegal because you are passing an expression
instead of a variable to an intent(out) argument. The compiler may do
anything, but one likely result is a compilation error message.

> If so, is there a way of accomplishing what I need without creating an
> allocatable 1D array, filling this with cache_retrieve(), assigning a
> reshaped version to data2D and deleting the allocatable 1D array?

That, of course, would work. A simpler way would be to take advantage of
storage association. Just do

  call cache_retrieve(data2D, n*n)

For the particular code you show, agreement of rank for the actual and
dummy arguments is *NOT* required. You basically get the effect of
reshape for "free". Storage association is a bit "old style" and it has
a bunch of caveats. While it is ok for the exact code you show, it would
not take much change to make it invalid. For example, it won't work if
the dummy argument is assumed shape or with generic procedures.

A newer way to accomplish a simillar end would be using pointers. F2003
allows a 2-D pointer to have a 1-D target (but not the other way around
because of potential problems with non-contiguous targets). So you could
make the actual array be 1-D and just use the pointer to it where you
want to treat it as 2-D. I think (but have not checked) F2008 allows the
other way around in conjunction with the CONTIGUOUS attribute. But f2003
compilers are scarce (none exist on any platforms I have access to),
much less f2008. You might find compilers that implement some features
of f2003, or even of f2008, but that gets into a morass I have regularly
complained about.

-- 
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
0
Reply nospam47 (9742) 5/31/2012 3:32:33 PM

Hello,

On 2012-05-31 15:32:33 +0000, Richard Maine said:
> 
> A newer way to accomplish a simillar end would be using pointers. F2003
> allows a 2-D pointer to have a 1-D target (but not the other way around
> because of potential problems with non-contiguous targets). So you could
> make the actual array be 1-D and just use the pointer to it where you
> want to treat it as 2-D. I think (but have not checked) F2008 allows the
> other way around in conjunction with the CONTIGUOUS attribute. But f2003
> compilers are scarce (none exist on any platforms I have access to),
> much less f2008. You might find compilers that implement some features
> of f2003, or even of f2008, but that gets into a morass I have regularly
> complained about.

gfortran supports pointer rank remapping.

I'd check the usual feature lists for others.
It's a useful feature that isn't all that hard to implement.

-- 
Cheers!

Dan Nagle

0
Reply danlnagle (25) 5/31/2012 11:23:15 PM

  Thanks.
0
Reply jack.erede (27) 6/1/2012 1:41:49 PM

  Thank you. I actually forgot the (:) in the declaration of "data_to_add" and "retrieve_buffer" that I posted here.

  Unfortunately, I am not allowed to use features that are not in Fortran-95 in the project.

thanks for the pointers,
- J.
0
Reply jack.erede (27) 6/1/2012 1:44:00 PM

6 Replies
49 Views

(page loaded in 0.11 seconds)


Reply: