Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29257 Discussions

Reshape a 1D allocatable array into a 2D array without copying data

OP1
New Contributor III
3,205 Views
Assume I want to convert a 1d allocatable array (with 100 elements) into a 10x10 2d allocatable array, without making a copy of the original data (this solution is too expensive given the actual size of my arrays).
Assuming that my 100 elements are sorted in the correct order (row-major order for the Fortran arrays), it seems I would just need to modify the array descriptor. How can I do this?

For instance, if V is originally[1,2,3,4] and I want to transform it into
V = [1 3
2 4 ],
while retaining the allocatable nature of V.

Thank you!

Olivier

PS: Note that if the arrayis not declared as allocatable and contains contiguous data then this is trivial.
0 Kudos
7 Replies
Steven_L_Intel1
Employee
3,205 Views
You can't change the rank of an existing array. But what you could do is this:
[cpp]USE, INTRINSIC :: ISO_C_BINDING
INTEGER, POINTER :: V2D(:.:)
...
call C_F_POINTER (C_LOC(V), V2D, [2,2])[/cpp]
Now, V2D is a 2D array with the contents of V. However, you cannot deallocate V2D - any deallocation has to be of V.
0 Kudos
OP1
New Contributor III
3,205 Views

Thank you Steve - I guess I need to find another way of programming what I want to do.

Olivier
0 Kudos
eos_pengwern
Beginner
3,205 Views
Quoting - opmkl

Thank you Steve - I guess I need to find another way of programming what I want to do.

Olivier

A possible, though rather abstruse, way of doing this would be to put operations which involve the 2D version of V into separate subroutines in a separate file. The calling routine would pass the 1D version, and the subroutine would declare the incoming variable as 2D. An interface block would be needed in the calling routine to fool it into thinking that the subroutine was expecting a 1D vector to be passed to it.

For example, if the calling routine contained:

[plain]n=size(v1,1)
sqrt_n=int(sqrt(n)) ! Assuming you want a square 2D array
                           ! as per your example.

interface 
	subroutine do_something_to_v1(n, v1)
		integer, value :: n
		real, intent(inout), dimension(n**2) :: v1
	end subroutine do_something_to_v1
end interface

call do_something_to_v1(sqrt_n, v1)
[/plain]

...and the subroutine was declared in a separate file (not a USED module) as:

[plain]subroutine do_something_to_v1(n,v2)

	integer, value :: n
	real, intent(inout), dimension(n,n) :: v2

	...
end subroutine do_something_to_v1
[/plain]

... then v2 would bereceived bythe subroutine as if it were an n-by-n array, without any copying taking place because all that's being put on the stack is the memory address of v1. v2 is kind-of allocatable in that it exists only when being worked on, and the samecode will work regardless of the dimension assigned to v1. Any overhead associated with the calling of the subroutines should be removed by the compiler during optimisation.

I did say it was abstruse, but I've used this approach successfully to pass 2D arrays to VML functions that expect to receive 1D vectors. I expect the same would work in reverse.
0 Kudos
OP1
New Contributor III
3,205 Views
Yes, that's the traditional way of doing it when your dummy arrays are not allocatable. However, in my case, I need to keep the allocatable properties of my arrays in the subsequent subroutines that manipulate them.

Ideally, only the array descriptor would need to be updated. But there are probably some hurdles to do this (it would be implemented otherwise,I reckon) - Steve may be able to shed some light on this.

Thanks!

Olivier
0 Kudos
Steven_L_Intel1
Employee
3,205 Views
Changing the rank of an array means changing the size of the descriptor as you have a new set of bounds to list. There is no support for this at all.

You can, as has been suggested in this thread, manipulate the data in the array using a different shape, but you can't "reshape" the original array.
0 Kudos
OP1
New Contributor III
3,205 Views
I see. I didn't know the descriptors had variable lengths. I thought they were structures of fixed size (since arrays have a rank of 7 at most).

Thanks Steve,

Olivier
0 Kudos
Steven_L_Intel1
Employee
3,205 Views
No, the descriptor varies by rank. Fortran 2008 increases the number of dimensions to 15 - we may support 31 in the future.
0 Kudos
Reply