how to use 1D array as a multidimensional array
Author Message
how to use 1D array as a multidimensional array

I am not sure what the technical term for this is. But i guess it could
be called array aliasing.

I have a 1D array declared by

real, dimension(100) :: A

Now I want to access this array as a "2D equivalent"

like B(i,j) where B is a 10x10 array and
B(i,j) = A(i*10+j)

required functionalities
1) As soon as one element of A changes, B should automatically get the
new value.
2) Should be able to access the array by both A, B.
3) If possible there should not be two instances of A, B.

What is most easy way to achieve the above functionality? Does fortran
90 have some nice subroutines which does this?

If is of any help, I will be using debian unstable, ifc 7.1 or absoft
8.0, Fortran 90/95

raju

Fri, 15 Dec 2006 23:50:58 GMT
how to use 1D array as a multidimensional array
| I am not sure what the technical term for this is. But i guess it could
| be called array aliasing.
|
| I have a 1D array declared by
|
| real, dimension(100) :: A
|
| Now I want to access this array as a "2D equivalent"
|
| like B(i,j) where B is a 10x10 array and
| B(i,j) = A(i*10+j)
|
|
| required functionalities
| 1) As soon as one element of A changes, B should automatically get the
| new value.
| 2) Should be able to access the array by both A, B.
| 3) If possible there should not be two instances of A, B.
|
| What is most easy way to achieve the above functionality? Does fortran
| 90 have some nice subroutines which does this?
|
| If is of any help, I will be using debian unstable, ifc 7.1 or absoft
| 8.0, Fortran 90/95

Here you are:

program Foo

implicit none

real, pointer:: b(:,:)
real::          a(100)
integer::       i

a = (/(i, i=1,100)/)
call EqReshape(a, b, 10, 10)

contains

subroutine EqReshape(x, p, n1, n2)

integer::         n1, n2
real, target::    x(n1, n2)
real, pointer::   p(:,:)

b => x

end subroutine EqReshape

end program Foo

"Storage association" is the term for two entities sharing the same
storage. In this case, a and x are storage-associated, and "reshaping"
is legal for dummy arguments. Then, pointer P (i.e. B) is additionally
storage-associated with X, i.e. A, via association-operator. Note
that it will work only for explicit-size dummies (if I replace
declaration of x as x(n1, *) I will deservedly get a compiler error).

I'm not sure about the legality of the above sample, but it happens
to compile & work on CVF so you can try your luck. There's only one
storage -- the one of A. EqReshape needs explicit interface
of course.

--
Jugoslav
___________
www.geocities.com/jdujic

You can find my real e-mail on my home page above.

Sat, 16 Dec 2006 00:06:02 GMT
how to use 1D array as a multidimensional array

Quote:

> I am not sure what the technical term for this is.

> But i guess it could  be called array aliasing.

Quote:
> I have a 1D array declared by
> real, dimension(100) :: A
> Now I want to access this array as a "2D equivalent"
> like B(i,j) where B is a 10x10 array and
> B(i,j) = A(i*10+j)

A Fortran 2D array would have B(i,j) = A(i+10*j)

Traditionally EQUIVALENCE was the way to do this,
which you should be able to look up in your Fortran
book, so I won't describe it here.  Newer Fortran
versions have other ways it can be done.

Do remember, though, for larger arrays, memory access
patterns can be important as cache and paging effects
come into play, so you should try to access arrays in
the order they are in storage.   For Fortran that is
with the first subscript changing fastest, the opposite
of many languages.

-- glen

Sat, 16 Dec 2006 00:07:19 GMT
how to use 1D array as a multidimensional array

Quote:

>> I am not sure what the technical term for this is.
> > But i guess it could  be called array aliasing.

>> I have a 1D array declared by

>> real, dimension(100) :: A

>> Now I want to access this array as a "2D equivalent"

>> like B(i,j) where B is a 10x10 array and
>> B(i,j) = A(i*10+j)

>A Fortran 2D array would have B(i,j) = A(i+10*j)

>Traditionally EQUIVALENCE was the way to do this,
>which you should be able to look up in your Fortran
>book, so I won't describe it here.  Newer Fortran
>versions have other ways it can be done.

Here is an example of EQUIVALENCE , which produces output

1 1 1 1 1 1
2 2 2 2 2 2
2 2

program xequiv
implicit none
integer, parameter :: n1 = 3, n2 = 2, n = n1*n2
integer            :: ix(n),iy(n1,n2)
equivalence (ix,iy)
ix = 1
print*,ix
iy = 2
print*,ix
print*,ix(1),iy(1,1)
end program xequiv

I wonder what the advantages and disadvantages are of EQUIVALENCE vs. POINTERs.

It is also possible to pass a 1-D array to a procedure expecting a multidimensional
array, as shown by the code below, which produces output

1           5
2           6
3           7
4           8

1           3
2           4

5           7
6           8

module mat_mod
contains
subroutine print_mat(imat,nr,nc)
implicit none
integer, intent(in) :: nr,nc
integer, intent(in) :: imat(nr,nc)
integer             :: i
do i=1,nr
print*,imat(i,:)
end do
end subroutine print_mat
!
subroutine print_tensor(iarr,n1,n2,n3)
implicit none
integer, intent(in) :: n1,n2,n3
integer, intent(in) :: iarr(n1,n2,n3)
integer             :: i,j
do i=1,n3
write (*,*)
do j=1,n1
print*,iarr(j,:,i)
end do
end do
end subroutine print_tensor
!
end module mat_mod
!
program xvec_mat
use mat_mod, only: print_mat,print_tensor
implicit none
integer, parameter :: nr = 4, nc = 2, n1 = 2, n2 = 2, n3 = 2, n = nr*nc
integer            :: i,ivec(n)
forall (i=1:n) ivec(i) = i
call    print_mat(ivec,nr,nc)
call print_tensor(ivec,n1,n2,n3)
end program xvec_mat

----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---

Sat, 16 Dec 2006 00:28:09 GMT
how to use 1D array as a multidimensional array

Quote:
> I'm not sure about the legality of the above sample, but it happens
> to compile & work on CVF so you can try your luck.

Make sure to give array a the target attribute.  The legality
is processor-dependent.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end

Sat, 16 Dec 2006 00:36:21 GMT
how to use 1D array as a multidimensional array

Quote:

> real, dimension(100) :: A
> Now I want to access this array as a "2D equivalent"
> like B(i,j) where B is a 10x10 array...

Do you mean those declarations literally?  Or were you
just trying to simplify the explanation?  It matters.
In particular, what matters is whether the array in question
is declared with fixed dimensions.

If the array size is actually fixed, as it is in your example,
then *BY FAR* the easiest way is to use equivalence, as in

real, dimension(100) :: A
real, dimension(10,10) :: B
equivalence (a,b)

This is basically f77 (well, for that matter, earlier, as this
predates even f66), other than the trivia that your example
happens to use f90 declaration syntax.  Nothing of substance
new here.

Now if your array is dynamically sized, then things are much
more complicated.  Equivalence is fundamentaly about static
memory layout; you can't use it with dynamically sized things
(no matter what dynamic sizing mechanism you use - equivalence
won't work with any of them).

For dynamically-sized things, see the trick that Jugoslav
mentioned.  I *THINK* that is standard-conforming (but some
of the details of pointers and dummy arguments are quite tricky,
so I'm not sure at all. I'd ask James Buskirk, who seems far
more up on such things than I am.  I always did have trouble
reading that particular part of the standard; takes me hours
to pour over it...and then I still discover that I missed some
detail that makes my answer wrong.)  But if the size is static,
you don't need the complications and side issues of this method.

Note that f2003 provides a simpler way to achieve this for
dynamically-sized arrays.  You can allocate a 1-D array and
then point at it with a pointer of different rank; there is
new syntax in the pointer assignment statement to allow this.
It is only allowed if the allocation is 1-D; you can't do it the
other way around because of possible complications with the
stride.  (I'm mildly advocating for a concept of sequence pointers
in f2003+; it would, as a side effect, allow you to do things the
other way around also.)  But these things are for the future,
f2003 not yet being here in actual compilers.

--
Richard Maine                       |  Good judgment comes from experience;
email: my first.last at org.domain  |  experience comes from bad judgment.
org: nasa, domain: gov              |        -- Mark Twain

Sat, 16 Dec 2006 00:35:53 GMT
how to use 1D array as a multidimensional array

Quote:

>>real, dimension(100) :: A
>>Now I want to access this array as a "2D equivalent"
>>like B(i,j) where B is a 10x10 array...

> Do you mean those declarations literally?  Or were you
> just trying to simplify the explanation?  It matters.
> In particular, what matters is whether the array in question
> is declared with fixed dimensions.

My arrays are allocated dynamically using allocate statement. I was just
trying to present a basic case. Actually my arrays are 3d. Instead of
writing statements like array(i+10j+20k) each and everytime, I thought
the code looks 'nice'  if I access it by array(i,j,k).

If it can not be done, I guess I have to live with the ugly code.

Quote:

> If the array size is actually fixed, as it is in your example,
> then *BY FAR* the easiest way is to use equivalence, as in

>   real, dimension(100) :: A
>   real, dimension(10,10) :: B
>   equivalence (a,b)

My fortran book says equivalence is deprecated. So I never bothered to
read that section. It looks like a nice feature! But anyway, if it is
not good for dynamic sizes, then it is no good.

thanks very much for all the replies
raju

Sat, 16 Dec 2006 02:00:54 GMT
how to use 1D array as a multidimensional array

Quote:

> My fortran book says equivalence is deprecated.

As I have had to comment several times, any such statement is
solely a judgement made by the authors of the book.

There is *NOTHING* in the standard that deprecates equivalence.
Any such judgement is solely one of individuals - nothing official.

I happen to agree with the author's judgement about deprecating
equivalence, but I find it important to distinguish my opinions
from the dictates of the standard.

In particular, I'd argue with the implied meaning of the word "is"
in the claim that "equivalence is deprecated".  :-)

If one just says "equivalence is deprecated" with no other
qualification, then that implies to me that it is deprecated
by the standard.  That is quite different from a statement like
"I consider equivalence to be deprecated".

Quote:
> But anyway, if it is
> not good for dynamic sizes, then it is no good.

Indeed.  it is pretty limited.  And this is an area where compilers
don't tend to extend the standard either.

--
Richard Maine                       |  Good judgment comes from experience;
email: my first.last at org.domain  |  experience comes from bad judgment.
org: nasa, domain: gov              |        -- Mark Twain

Sat, 16 Dec 2006 02:30:28 GMT
how to use 1D array as a multidimensional array
...

Quote:
> program Foo

> implicit none

> real, pointer:: b(:,:)
> real::          a(100)
> integer::       i

> a = (/(i, i=1,100)/)
> call EqReshape(a, b, 10, 10)

> contains

> subroutine EqReshape(x, p, n1, n2)

> integer::         n1, n2
> real, target::    x(n1, n2)
> real, pointer::   p(:,:)

> b => x

> end subroutine EqReshape

> end program Foo

I assume you mean p => x here.  Though, because you've
made it an internal procedure, the variable b is visible
inside EqReshape.

However, the program violates the standard in that you
are associating B with variable A, yet A has no TARGET
attribute.  Without the TARGET attribute, the compiler
is free to assume that A is not associated with pointers and
optimize accordingly.

Even if A is given the TARGET attribute, I'm not sure the
program is conforming.  It contradicts the apparent intent of
the standard that the rank of a TARGET must be the same as
that of any associated pointers.

Note that the F2003 proposed standard allows remapping
of pointer assignments explicitly.  The above situation could
be handled (in an implementation of 2003) as:

real, allocatable, target :: a(100)
real, pointer :: b(:,:)
...
b(1:10,1:10) => a

This associates B with A.

--
J. Giles

"I conclude that there are two ways of constructing a software
design: One way is to make it so simple that there are obviously
no deficiencies and the other way is to make it so complicated
that there are no obvious deficiencies."  -- C. A. R. Hoare

Sat, 16 Dec 2006 03:49:21 GMT
how to use 1D array as a multidimensional array
| ...
|| program Foo
||
|| implicit none
||
|| real, pointer:: b(:,:)
|| real::          a(100)
|| integer::       i
||
|| a = (/(i, i=1,100)/)
|| call EqReshape(a, b, 10, 10)
||
|| contains
||
|| subroutine EqReshape(x, p, n1, n2)
||
|| integer::         n1, n2
|| real, target::    x(n1, n2)
|| real, pointer::   p(:,:)
||
|| b => x
||
|| end subroutine EqReshape
||
|| end program Foo
|
| I assume you mean p => x here.  Though, because you've
| made it an internal procedure, the variable b is visible
| inside EqReshape.

Yes, I meant p=>x, it was a last minute change...

| However, the program violates the standard in that you
| are associating B with variable A, yet A has no TARGET
| attribute.  Without the TARGET attribute, the compiler
| is free to assume that A is not associated with pointers and
| optimize accordingly.

Mea culpa, I forgot about it.

| Even if A is given the TARGET attribute, I'm not sure the
| program is conforming.  It contradicts the apparent intent of
| the standard that the rank of a TARGET must be the same as
| that of any associated pointers.

I've been wondering about it too. I had a feeling that I abused
what is basically a F77-compatibility feature (storage association
of dummy argument arrays) in order to achieve pointer association,
which is IMHO contrary to the "spirit" of the standard language.

Yet, I'd bet that the sample would pass through most compilers
around.

--
Jugoslav
___________
www.geocities.com/jdujic

You can find my real e-mail on my home page above.

Sat, 16 Dec 2006 04:01:56 GMT
how to use 1D array as a multidimensional array

Quote:

>>> real, dimension(100) :: A
>>> Now I want to access this array as a "2D equivalent"
>>> like B(i,j) where B is a 10x10 array...

>> Do you mean those declarations literally?  Or were you
>> just trying to simplify the explanation?  It matters.
>> In particular, what matters is whether the array in question
>> is declared with fixed dimensions.

> My arrays are allocated dynamically using allocate statement. I was just
> trying to present a basic case. Actually my arrays are 3d. Instead of
> writing statements like array(i+10j+20k) each and everytime, I thought
> the code looks 'nice'  if I access it by array(i,j,k).

Forgive me if this is a stupid question, but why not allocate them as n-dimensional rather
than 1-D? If you're worried about the code looking "nice", address it at the source.

cheers,

paulv

- Show quoted text -

Quote:

> If it can not be done, I guess I have to live with the ugly code.

>> If the array size is actually fixed, as it is in your example,
>> then *BY FAR* the easiest way is to use equivalence, as in

>>   real, dimension(100) :: A
>>   real, dimension(10,10) :: B
>>   equivalence (a,b)

> My fortran book says equivalence is deprecated. So I never bothered to
> read that section. It looks like a nice feature! But anyway, if it is
> not good for dynamic sizes, then it is no good.

> thanks very much for all the replies
> raju

Sat, 16 Dec 2006 04:02:48 GMT
how to use 1D array as a multidimensional array

Quote:
> I've been wondering about it too. I had a feeling that I abused
> what is basically a F77-compatibility feature (storage association
> of dummy argument arrays) in order to achieve pointer association,
> which is IMHO contrary to the "spirit" of the standard language.
> Yet, I'd bet that the sample would pass through most compilers
> around.

The relevant passage of ISO/IEC 1539-1:1997(E) is in section 12.4.1.1, pp.
200-201:

"If the dummy argument has the TARGET attribute and is an explicit-shape
array or is
an assumed-size array, and the corresponding actual argument has the TARGET
attribute but is not an array section with a vector subscript
...
(2) When execution of the procedure completes, the pointer association
status of any
pointer that is pointer associated with the dummy argument is processor
dependent."

The way I think about it is that there are two "approved" methods for
passing
arrays in the standard:
1) The f77 method of passing a reference to the first element (Section
12.4.1.4)
of a contiguous array when the dummy argument is an explicit shape or
assumed
size array.
2) Passing a reference to an array descriptor (the reference part becomes
evident when the dummy argument is a POINTER of has the ALLOCATABLE
attribute (f03)).

Given the above assumptions (which are nowhere explicitly stated in the
standard; I just made them up) we see that when the dummy argument is an
f77 style array we have three possibilities for the pointer association
status
on return (assuming the processor isn't smart enough to mark them as
disassociated on return, and further assuming the actual argument and
dummy argument have the TARGET attribute:)
1) The actual argument is itself a guaranteed contiguous array (allocatable,
explicit shape, or assumed size, or an element of one of the above) in which
case the pointer to the dummy will remain associated with the actual
argument
on return
2) The actual argument is discontiguous, in which case the dummy argument
will have been associated with a temporary copy and the and on return will
necessarily have the unpleasant "undefined" association status.
3) The actual argument is contiguous but is created in a way that can also
make discontiguous arrays (POINTER actual argument, assumed shape
dummy that is itself passed as an actual argument to the next level, or an
array section with a vector subscript.)  In these cases, whether a reference
to the original array or section or a reference to a copy is passed has been
seen repeatedly in this group to be compiler-dependent and in fact most
compilers have moved from an original policy of making copies in most or
all cases to a current policy of passing a reference to the original in most
or all cases.  If a reference to the original is passed, of course the
pointer
will remain associated with it on return, and if a reference to a copy is
passed the pointer's association status will then be undefined.  We can see
from this last paragraph why the standard left the association status
processor-
dependent for all three cases.

Of course, if the actual argument was an expression (and an array section
with a vector subscript counts as an expression in this and almost all other
contexts, except for elemental intrinsic assignment that I can think of)
then
there is nothing for the pointer to be associated with on return so that its
association status will then be undefined.

The reader is cautioned that only the passage I quoted has anything to do
with the standard; the rest would be almost certain to be disavowed by any
member of the committee individually or by the entire committee
collectively.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end

Sat, 16 Dec 2006 04:51:52 GMT
how to use 1D array as a multidimensional array

Quote:

>> My arrays are allocated dynamically using allocate statement. I was
>> just trying to present a basic case. Actually my arrays are 3d.
>> Instead of writing statements like array(i+10j+20k) each and
>> everytime, I thought the code looks 'nice'  if I access it by
>> array(i,j,k).

> Forgive me if this is a stupid question, but why not allocate them as
> n-dimensional rather than 1-D? If you're worried about the code looking
> "nice", address it at the source.

In my case, the code is given to me. The original author used the one-d
array formulation. Though I do not understand all the intricate
arguments, the reasoning goes like this.

Say I have a 3D array Array(N,N,M) where N is not same as M. In the
algorithm, say you need to work with the 'local transpose' of the last
two dimensions. Taking the transpose of last two dimensions will result
in an array whose shape is Array2(N,M,N).

The fact that Array & Array2 have different shapes prevents one to use
the same memory location. So using the above method, requires to create
2 arrays.

But if we are using Array(N*N*M), then the array needs to be created
only once. The program takes care of which elemets it needs to access as
and when it wants.

raju

Sat, 16 Dec 2006 05:15:49 GMT
how to use 1D array as a multidimensional array

Quote:
> My arrays are allocated dynamically using allocate statement. I was just
> trying to present a basic case. Actually my arrays are 3d. Instead of
> writing statements like array(i+10j+20k) each and everytime, I thought
> the code looks 'nice'  if I access it by array(i,j,k).

That puts me in mind of a statement function, if "10" and "20" are
fixed at compile time (Heck, for not much overhead, a real integer
function [:-)] might even be inlined at the right optimisation, and you
could pass dynamic dimension values via, e.g. a common block).
Although, your textbook might also deprecate statement functions.

myadd(i,j,k)=i+10(j+20*k) !I presume this is closer to your idea...
(or     integer function myadd(i,j,k)
integer i,j,k
return
end
)
...

Now add in the error handling...

--
Ivan Reid, Electronic & Computer Engineering,     ___     CMS  Collaboration,

Sat, 16 Dec 2006 05:17:48 GMT
how to use 1D array as a multidimensional array

Quote:
> Say I have a 3D array Array(N,N,M) where N is not same as M. In the
> algorithm, say you need to work with the 'local transpose' of the last
> two dimensions. Taking the transpose of last two dimensions will result
> in an array whose shape is Array2(N,M,N).

I would say that argument is bogus. You are allowed to "reshape" an array when
you pass it as an actual argument, as long as the whole size remains the same
(or smaller, obviously) and the original array is contiguous (which it will be

The interesting question is how one wants to access such an array. You have
two choices:

- Explicitly perform the transpose, i.e., make a copy in which the array
elements are re-arranged in memory.
- Change the index computations such that you implicitly access the elements
in transposed order, without actually moving them.

Your code seems to be doing the latter. Whether this is the right choice
depends very much how much work is being done in the "transposed" state: the
more, the higher the likelihood that the first choice is the right one - even
if you need to reverse the transpose again. The reason for this is that all
processors (ha!) have caches that are optimized for "linear" access to data,
and that always access memory in "lines" which are larger than a single array
element. Of course, the details strongly depend on the details of the hardware
_and_ the algorithm - and a choice that was "optimal" yesterday may be far
from it today.

To give you a historical example: Imagine doing a 2D FFT by first doing a
loop of 1D FFTs on the rows and then on the columns. On one particular system
(based on the T800 8-)), it was significantly faster to first gather a column
from external memory in internal memory (which nowadays would be cache),
perform the 1D FFT on it (a lot of operations on non-adjacent data items), and
last scatter it back into the column of the original array.

There is also a paper out there describing loop optimization on an Athlon,
IIRC. It discusses how a compiler (hopefully) can schedule the memory
operations such that overall throughput is optimized, even if more work is
actually performed. Sorry, no quote handy.

Jan

Sat, 16 Dec 2006 15:10:07 GMT

 Page 1 of 2 [ 22 post ] Go to page: [1] [2]

Relevant Pages