Re: Efficient way to pass different shaped arrays?



Peter wrote:
I'm attempting to use an array argument of a subroutine for two
different purposes. One, which works fine, has the caller declare an
identical explicit shape array. The other, shown below, has the caller
(A) passing a small number of reals in the same memory space.
Subroutine B knows, via other arguments not shown, which kind of array
argument is being received.

In subroutine A:

REAL, DIMENSION(3) :: array
CALL B(array)

SUBROUTINE B(array)
REAL, DIMENSION(28,0:10001), INTENT(INOUT) :: array

Under CVF6, this worked as expected, but using IVF9, the compiler flags
an error because the extent of 'array' as a dummy argument for B
exceeds the size of the real argument 'array' in A; presumably this is
an error because B could write memory beyond the size of 'array'
declared by the caller.

I am pretty sure passing a one dimensional array to a two dimensional
dummy is allowed, definitely the other way around is allowed.

The standard since F66 would be that the dimensions of the dummy
array (in the called routine) should be variables, either passed as arguments or in COMMON. I believe newer standards allow a subset of
expressions in subscripts.

So, my question is, what is a simple and efficient way to pass in the
3-element array? I don't really want to create a huge 28x10002 array in
the caller, and for efficiency it would be better not to add another
argument (subroutine B gets called many times).

You say that other arguments not shown make the distinction.
Standard back to F66, is if those arguments are the actual array
dimensions, where one should be 1 in the one dimensional case.

I believe since F77 the last subscript of the dummy array can be *,
indicating that the actual value isn't given, but the program is
still required to stay within bounds. In your case, (28,0:*)
should allow an array dimensioned (28), not excessively large.

It might be possible to compute the actual array bounds.
Since Fortran doesn't have a conditional operator, it might be that
you could use a trick I saw once in a discussion about how NOT to
write Fortran code. Consider:

DO 1 I=1,100
DO 1 J=1,100
1 A(I,J)=(I/J)*(J/I)

It seems that someone actually used this to initialize an identity
matrix, with much more multiplication and division than needed.

If multiply and divide are allowed in dummy array dimensions, and I
don't actually know that they are, you might be able to use a similar
trick to compute the appropriate dimensions. The rules for specification expression are complicated enough that I won't go into
more detail. If (28,0:*) doesn't work then I or someone else can figure
out what can actually be done.

-- glen

.



Relevant Pages

  • Re: gfortran & adjustable array: most values remain zero
    ... first n-1 dimensions of an n-dimensional array must match between caller ... the ranks don't even have to match, must less the dimensions. ... If the first dimensions of the actual and dummy ... the resulting correspondence of array elements is ...
    (comp.lang.fortran)
  • Re: array verses ArrayList
    ... > I have a class that contains a collection of reference types. ... > needs to have a method that returns the collection to the caller. ... If the size cannot change, then no, an Array of MyObject is preferable. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: About Memory Allocation and function calls
    ... function(because the caller don't know the exact size). ... how should the caller access this array for future use? ... Allocated memory remains allocated until it is explicitly freed. ... the calling function has access to. ...
    (comp.lang.c)
  • About Memory Allocation and function calls
    ... function(because the caller don't know the exact size). ... how should the caller access this array for future use? ... I consider to use mallocto allocate memory for this array, ... return the pointer to this run time allocated memory back to the ...
    (comp.lang.c)
  • Re: out param question
    ... an arbitrary length array of bytes.... ... You allocate a block of memory with CoTaskMemAlloc, ... it in *pData and its length in *pSize. ... The caller eventually frees the ...
    (microsoft.public.win32.programmer.ole)