Code Comments

Programming Forum and web based access to our favorite programming groups.
For Programmers: Free Programming Magazines | New: Database administration forum
Registration is free! Edit your profileCalendarFind other membersFrequently Asked QuestionsSearch -> 
Post New Thread











Thread
Author

overload array index operator
Is there any way to overload the index operator in fortran? For example
if I want to index an array with a derived type? Or if I want to access
a N-d array with a single subscript (possible of a derived type)?

As a specific example, if I had a 2-d array:

real foo(2,2)
foo(1,1)=10
foo(2,1)=20
foo(1,2)=30
foo(2,2)=40

and if
real bar
bar=[2,4]

then I would like to be able to access:
foo(bar)

and it would be a rank 1 array:
[20,40]

Can this be done in fortran?

Report this thread to moderator Post Follow-up to this message
Old Post
Ben Barrowes
10-15-04 08:58 PM


Re: overload array index operator
Ben Barrowes wrote:
> Is there any way to overload the index operator in fortran? For example
> if I want to index an array with a derived type? Or if I want to access
> a N-d array with a single subscript (possible of a derived type)?
>
> As a specific example, if I had a 2-d array:
>
> real foo(2,2)
> foo(1,1)=10
> foo(2,1)=20
> foo(1,2)=30
> foo(2,2)=40
>
> and if
> real bar
> bar=[2,4]
>
> then I would like to be able to access:
> foo(bar)
>
> and it would be a rank 1 array:
> [20,40]
>
> Can this be done in fortran?

No and yes. Unlike C/C++, where anything goes, there is no concept in
Fortran of an index operator. Hence, you can't index an array with a
derived type.

However, in the example you gave, you are trying to index one array
using another array of indices. This is permitted by Fortran 90/95/03;
but these "vector subscripts" work in a slightly different way than your
example above. In fact, for the desired result, your code would have to
read something like this:

---
real foo(2,2)
foo(1,1)=10.
foo(2,1)=20.
foo(1,2)=30.
foo(2,2)=40.

integer bar_1(2), bar_2(2)
bar_1 = (/2,2/)
bar_2 = (/1,2/)

print *,foo(bar_1,bar_2)
---

This would give the desired output "20. 40.". However, a number of
points to note:

1) You need two separate arrays, bar_1 and bar_2, to index foo, since
foo has two dimensions
2) bar_1 and bar_2 *must* be declared as integers if they are to be used
for indexing
3) Array literals are enclosed inside (/.../) delimiters. The [...]
syntax is introduced in the new Fortran 2003 standard; however, it is
*not* part of the F90/F95 standards, and should be avoided if you wish
to write portable code based on these standards.
4) There are restrictions on the use of vector subscripts on the
left-hand side of assignments -- basically, to prevent the same element
being written to twice.

Should you wish to know more, the book "Fortran 95/2003 Explained",
co-authored by c.l.f regular Mike Metcalf, gives a good discussion of
vector subscripts.

cheers,

Rich

--
Dr Richard H D Townsend
Bartol Research Institute
University of Delaware

[ Delete VOID for valid email address ]

Report this thread to moderator Post Follow-up to this message
Old Post
Rich Townsend
10-15-04 08:58 PM


Re: overload array index operator
Rich,
I appreciate your response. This indexing, however, does not give what
I expected. With your example, I get:
20.0000000000000 20.0000000000000 40.0000000000000 40.0000000000000

In fact, consider:

program zztest1

real foo(3,3)
integer bar_1(3), bar_2(3)
foo(1,1:3)=(/10.,40.,70./)
foo(2,1:3)=(/20.,50.,80./)
foo(3,1:3)=(/30.,60.,90./)
bar_1 = (/2,2,1/)
bar_2 = (/1,3,2/)

print *,foo(bar_1,bar_2)

end program zztest1


Both ifc and g95 yield:
> test1
20.0000000000000        20.0000000000000        10.0000000000000
80.0000000000000        80.0000000000000        70.0000000000000
50.0000000000000        50.0000000000000        40.0000000000000

Where from your post, I expected:
(/20,80,40/)

Ben



Rich Townsend wrote:
> Ben Barrowes wrote:
> 
>
>
> No and yes. Unlike C/C++, where anything goes, there is no concept in
> Fortran of an index operator. Hence, you can't index an array with a
> derived type.
>
> However, in the example you gave, you are trying to index one array
> using another array of indices. This is permitted by Fortran 90/95/03;
> but these "vector subscripts" work in a slightly different way than your
> example above. In fact, for the desired result, your code would have to
> read something like this:
>
> ---
> real foo(2,2)
> foo(1,1)=10.
> foo(2,1)=20.
> foo(1,2)=30.
> foo(2,2)=40.
>
> integer bar_1(2), bar_2(2)
> bar_1 = (/2,2/)
> bar_2 = (/1,2/)
>
> print *,foo(bar_1,bar_2)
> ---
>
> This would give the desired output "20. 40.". However, a number of
> points to note:
>
> 1) You need two separate arrays, bar_1 and bar_2, to index foo, since
> foo has two dimensions
> 2) bar_1 and bar_2 *must* be declared as integers if they are to be used
> for indexing
> 3) Array literals are enclosed inside (/.../) delimiters. The [...]
> syntax is introduced in the new Fortran 2003 standard; however, it is
> *not* part of the F90/F95 standards, and should be avoided if you wish
> to write portable code based on these standards.
> 4) There are restrictions on the use of vector subscripts on the
> left-hand side of assignments -- basically, to prevent the same element
> being written to twice.
>
> Should you wish to know more, the book "Fortran 95/2003 Explained",
> co-authored by c.l.f regular Mike Metcalf, gives a good discussion of
> vector subscripts.
>
> cheers,
>
> Rich
>

Report this thread to moderator Post Follow-up to this message
Old Post
Ben Barrowes
10-15-04 08:58 PM


Re: overload array index operator
Ben Barrowes wrote:
> Rich,
>     I appreciate your response. This indexing, however, does not give
> what I expected. With your example, I get:
>  20.0000000000000 20.0000000000000 40.0000000000000 40.0000000000000
>
> In fact, consider:
>
> program zztest1
>
> real foo(3,3)
> integer bar_1(3), bar_2(3)
> foo(1,1:3)=(/10.,40.,70./)
> foo(2,1:3)=(/20.,50.,80./)
> foo(3,1:3)=(/30.,60.,90./)
> bar_1 = (/2,2,1/)
> bar_2 = (/1,3,2/)
>
> print *,foo(bar_1,bar_2)
>
> end program zztest1
>
>
> Both ifc and g95 yield: 
>    20.0000000000000        20.0000000000000        10.0000000000000
>    80.0000000000000        80.0000000000000        70.0000000000000
>    50.0000000000000        50.0000000000000        40.0000000000000
>
> Where from your post, I expected:
> (/20,80,40/)
>
> Ben

Oh dear, I've had a monster brain fart. I apologize for giving you a
wholly-misleading example -- I appear to have forgotten that vector
subscripts along different dimensions are applied independently of one
another.

A better example would have been something like this:

---
real foo(4)
foo(1)=10.
foo(2)=20.
foo(3)=30.
foo(4)=40.

integer bar(2)
bar = (/2,4/)

print *,foo(bar)
---

This will produce the desired output "20. 40."; but note that foo is now
a one-dimensional array, and I have a single index array bar.

cheers,

Rich

--
Dr Richard H D Townsend
Bartol Research Institute
University of Delaware

[ Delete VOID for valid email address ]

Report this thread to moderator Post Follow-up to this message
Old Post
Rich Townsend
10-15-04 08:58 PM


Re: overload array index operator

Ben Barrowes wrote:
> Rich,
>     I appreciate your response. This indexing, however, does not give
> what I expected. With your example, I get:
>  20.0000000000000 20.0000000000000 40.0000000000000 40.0000000000000
>
Yep, that's what you get.  Vector Valued Subscripts give
the outer product of the subscript ranges.  There is no good
way in Fortran to collapse a 2 dimensional array into one
dimension that way you want to.

In your first example, you seem to be thinking of foo(2,2)
as the 4th element of foo.  It really isn't, it's the (2,2)
element.

The only thing I can think of is to equivalence a
one dimensional array to foo and subsctipr into
that.  Something like
real foo(2,2), big_foo(4)
equivalence (foo, big_foo)
..
the big_foo( (/2,4/) ) will be a rank one array with
values 20 and 40.  Unfortunately, you can only EQUIVALENCE
this way with arrays of known size and that aren't dummy
arguments.  That's often a killer limitation for most
uses.  As Rcih mentioned, you can use a one dimensional
integer scalar array name in place of the array constructor
for the (/ 2,4 /).

You can always copy the 2D array into a 1D array, manipulate
it with vector valued subscripts, and copy it back.
Whether or not that's a good idea depends on how much
you do to what.

Dick Hendrickson

> In fact, consider:
>
> program zztest1
>
> real foo(3,3)
> integer bar_1(3), bar_2(3)
> foo(1,1:3)=(/10.,40.,70./)
> foo(2,1:3)=(/20.,50.,80./)
> foo(3,1:3)=(/30.,60.,90./)
> bar_1 = (/2,2,1/)
> bar_2 = (/1,3,2/)
>
> print *,foo(bar_1,bar_2)
>
> end program zztest1
>
>
> Both ifc and g95 yield: 
>    20.0000000000000        20.0000000000000        10.0000000000000
>    80.0000000000000        80.0000000000000        70.0000000000000
>    50.0000000000000        50.0000000000000        40.0000000000000
>
> Where from your post, I expected:
> (/20,80,40/)
>
> Ben
>
>
>
> Rich Townsend wrote: 


Report this thread to moderator Post Follow-up to this message
Old Post
Dick Hendrickson
10-15-04 08:58 PM


Re: overload array index operator
"Ben Barrowes" <barrowes@alum.mit.edu> wrote in message
news:416ff3b7$1_5@news3.es.net...

> Is there any way to overload the index operator in fortran? For example
> if I want to index an array with a derived type? Or if I want to access
> a N-d array with a single subscript (possible of a derived type)?

> As a specific example, if I had a 2-d array:

> real foo(2,2)
> foo(1,1)=10
> foo(2,1)=20
> foo(1,2)=30
> foo(2,2)=40

> and if
> real bar
> bar=[2,4]

> then I would like to be able to access:
> foo(bar)

> and it would be a rank 1 array:
> [20,40]

> Can this be done in fortran?

Sort of. Try this:

module extra_index
implicit none
contains
subroutine repoint(old,n,new)
integer n
real, target :: old(n)
real, pointer :: new(:)

new => old
end subroutine repoint
end module extra_index

program test
use extra_index
implicit none
real, target :: foo(2,2)
integer, allocatable :: bar(:)
real, pointer :: foo1(:)

foo = reshape((/10,20,30,40/),shape(foo))
call repoint(foo,size(foo),foo1)
allocate(bar(2))
bar = (/2,4/)
write(*,*) foo1(bar)
end program test

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



Report this thread to moderator Post Follow-up to this message
Old Post
James Van Buskirk
10-15-04 08:58 PM


Re: overload array index operator
On Fri, 15 Oct 2004, James Van Buskirk wrote:

>
>
> "Ben Barrowes" <barrowes@alum.mit.edu> wrote in message
> news:416ff3b7$1_5@news3.es.net...
> 
> 
> 
> 
> 
> 
> 
>
> Sort of. Try this:
>
> module extra_index
>   implicit none
>   contains
>      subroutine repoint(old,n,new)
>         integer n
>         real, target :: old(n)
>         real, pointer :: new(:)
>
>         new => old
>      end subroutine repoint
> end module extra_index
>
> program test
>   use extra_index
>   implicit none
>   real, target :: foo(2,2)
>   integer, allocatable :: bar(:)
>   real, pointer :: foo1(:)
>
>   foo = reshape((/10,20,30,40/),shape(foo))
>   call repoint(foo,size(foo),foo1)
>   allocate(bar(2))
>   bar = (/2,4/)
>   write(*,*) foo1(bar)
> end program test
>
> --
> write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
> 6.0134700243160014d-154/),(/'x'/)); end
>

I usually do something along the following:

program zztest1

real foo(3,3)
logical lfoo(3,3)
foo(1,1:3)=(/10.,40.,70./)
foo(2,1:3)=(/20.,50.,80./)
foo(3,1:3)=(/30.,60.,90./)
lfoo=.false.
lfoo(1,2)=.true.
lfoo(2,(/1,3/))=.true.
print *, pack(foo,mask=lfoo)

end program zztest1

of course you won't get the order that you had specified (column-wise as
opposed to row-wise).  Now all you have to do is update lfoo as you
iterate through your program to pull off the elements you want.  Not sure
if this is what you were going for though.

Cheers,
Jason

Report this thread to moderator Post Follow-up to this message
Old Post
Jason Nielsen
10-15-04 08:58 PM


Sponsored Links




Last Thread Next Thread Next
Search this forum -> 
Post New Thread

Fortran archive

Show a Printable Version Send to friend Email This Page to Someone! subscribe to this thread Receive updates to this thread
Computer Consultants
Programming Jobs
Visual Basic Controls
SQL Server Programming
Webservices
Java Security
Visual Studio
C# Programming
Visual J++
Software engineering
Open source Software
Perl Programming
PHP Programming
ASP Programming
ASP .NET Programming
Visual Basic Programming
Windows Scripting Host
Java Programming
Java Help
Java Beans
VBScript
Cobol
MAC Applications
Unix Programming
Forum Jump:
All times are GMT. The time now is 06:00 PM.

 
Free MCSE Braindumps | Real Estate Topics

Programming forum archive

Copyrights CodeComments.com 2004 - 2006

Powered by vBulletin Copyright 2000-2006 Jelsoft Enterprises Limited.