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

Reference to derived type element by index?
I have a derived type, e.g.

type circle_datatype
real             :: radius
real             :: x
real             :: y
real             :: z
character(len=*) :: circle_label
endtype circle_datatype
type(circle_datatype) :: circle


and want to refer to the individual elements via some indexing scheme,
say in this example I want to change the value of circle%radius I would
use index #1, or the z-coordinate I would use #4. Is there some method
by which this is possible?

I think IDL has a system for this, such that circle.radius can be
referenced by circle.(0), but I really need Fortran's horsepower for
this code!

Report this thread to moderator Post Follow-up to this message
Old Post
Rob Crain
03-30-08 12:24 AM


Re: Reference to derived type element by index?
Rob Crain wrote:

> I have a derived type, e.g.
>
> type circle_datatype
>    real             :: radius
>    real             :: x
>    real             :: y
>    real             :: z
>    character(len=*) :: circle_label
> endtype circle_datatype
> type(circle_datatype) :: circle
>
>
> and want to refer to the individual elements via some indexing scheme,
> say in this example I want to change the value of circle%radius I would
> use index #1, or the z-coordinate I would use #4. Is there some method
> by which this is possible?
>
> I think IDL has a system for this, such that circle.radius can be
> referenced by circle.(0), but I really need Fortran's horsepower for
> this code!
type circle_datatype
real             :: radius(100)
real             :: x(100)
real             :: y(100)
real             :: z(100)
character(len=256) :: circle_label(100)
endtype circle_datatype
type(circle_datatype) :: circle

circle%radius(1) = <something>


--

Gary Scott
mailto:garylscott@sbcglobal dot net

Fortran Library:  http://www.fortranlib.com

Support the Original G95 Project:  http://www.g95.org
-OR-
Support the GNU GFortran Project:  http://gcc.gnu.org/fortran/index.html

If you want to do the impossible, don't hire an expert because he knows
it can't be done.

-- Henry Ford

Report this thread to moderator Post Follow-up to this message
Old Post
Gary Scott
03-30-08 03:35 AM


Re: Reference to derived type element by index?
Gary Scott wrote:

> Rob Crain wrote:
> 
>
>  type circle_datatype
>     real             :: radius(100)
>     real             :: x(100)
>     real             :: y(100)
>     real             :: z(100)
>     character(len=256) :: circle_label(100)
>  endtype circle_datatype
>  type(circle_datatype) :: circle
>
> circle%radius(1) = <something>
>
>
Oops or using your original type declaration, another possibility:

type(circle_datatype) :: circle(100)

circle(1)%radius = something

--

Gary Scott
mailto:garylscott@sbcglobal dot net

Fortran Library:  http://www.fortranlib.com

Support the Original G95 Project:  http://www.g95.org
-OR-
Support the GNU GFortran Project:  http://gcc.gnu.org/fortran/index.html

If you want to do the impossible, don't hire an expert because he knows
it can't be done.

-- Henry Ford

Report this thread to moderator Post Follow-up to this message
Old Post
Gary Scott
03-30-08 03:35 AM


Re: Reference to derived type element by index?
Hi Gary - thanks for your reply. I think my initial explanation may have
been unclear, as this is not the solution to my problem. The problem
reduces to the following: I don't know explicitly which variable (I
incorrectly referred to this variable as an element previously, hence
the confusion) I want to update, so I can't say

circle%radius = <something>

All I have is an index that tells me I need to update the i^th variable
within the derived type. So say I need to update circle%z, the index
would have value 4. But I know that I can't do

circle%(4) = <something>

but hoped there was some syntax that might allow this procedure? Any
help appreciated --Rob

Gary Scott wrote:
> Rob Crain wrote:
> 
>  type circle_datatype
>     real             :: radius(100)
>     real             :: x(100)
>     real             :: y(100)
>     real             :: z(100)
>     character(len=256) :: circle_label(100)
>  endtype circle_datatype
>  type(circle_datatype) :: circle
>
> circle%radius(1) = <something>
>
>

Report this thread to moderator Post Follow-up to this message
Old Post
Rob Crain
03-30-08 03:35 AM


Re: Reference to derived type element by index?
Rob Crain wrote:

> Hi Gary - thanks for your reply. I think my initial explanation may have
> been unclear, as this is not the solution to my problem. The problem
> reduces to the following: I don't know explicitly which variable (I
> incorrectly referred to this variable as an element previously, hence
> the confusion) I want to update, so I can't say
>
> circle%radius = <something>
>
> All I have is an index that tells me I need to update the i^th variable
> within the derived type. So say I need to update circle%z, the index
> would have value 4. But I know that I can't do

By i'th variable, are you saying the i'th component?  No you can't alias
an index with the formally defined components and have value 1 refer to
radius and value 2 refer to x.  You could use select case to make that
choice based upon the index.  Still not sure I understand fully tho.

> <snip>
--

Gary Scott
mailto:garylscott@sbcglobal dot net

Fortran Library:  http://www.fortranlib.com

Support the Original G95 Project:  http://www.g95.org
-OR-
Support the GNU GFortran Project:  http://gcc.gnu.org/fortran/index.html

If you want to do the impossible, don't hire an expert because he knows
it can't be done.

-- Henry Ford

Report this thread to moderator Post Follow-up to this message
Old Post
Gary Scott
03-30-08 03:35 AM


Re: Reference to derived type element by index?
Rob Crain <r.a.crain@durham.ac.uk> wrote:

> I have a derived type, e.g.
>
> type circle_datatype
>     real             :: radius
>     real             :: x
>     real             :: y
>     real             :: z
>     character(len=*) :: circle_label
> endtype circle_datatype
> type(circle_datatype) :: circle

You have a compiler that let you get by with that? It shouldn't.
Unrelated to your question, but the len=* is invalid Fortran.

> and want to refer to the individual elements via some indexing scheme,
> say in this example I want to change the value of circle%radius I would
> use index #1, or the z-coordinate I would use #4. Is there some method
> by which this is possible?

Not directly, no. You can sometimes play games with equivalence, but
that has a lot of "issues" and is very limitting. For example, the
simplest games aren't standard conforming or portable unless the derived
type meets the stringent conditions for being a numeric sequence type
(the conditions are considerably more stringent than you'd guess from
the term).

In some cases you might be able to get by with an accessor function,
with a select case construct buried in the function. Thus you could have
a notation like

component(circle,3)

where component is the function. That will only work well when al the
components you want to access have the same type.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain

Report this thread to moderator Post Follow-up to this message
Old Post
Richard Maine
03-30-08 03:35 AM


Re: Reference to derived type element by index?
Hi - yes, that's what I want to do. If, as you say, this can't be done
then a case statement might be the way to go - it's not as elegant as
I'd hoped, but this is just a simple routine to parse a parameter file,
so it's not mission-critical. Thanks for your help!

Gary Scott wrote:
> Rob Crain wrote:
> 
>
> By i'th variable, are you saying the i'th component?  No you can't alias
> an index with the formally defined components and have value 1 refer to
> radius and value 2 refer to x.  You could use select case to make that
> choice based upon the index.  Still not sure I understand fully tho.
> 

Report this thread to moderator Post Follow-up to this message
Old Post
Rob Crain
03-30-08 03:35 AM


Re: Reference to derived type element by index?
On Mar 29, 6:11=A0pm, Rob Crain <r.a.cr...@durham.ac.uk> wrote:
> I have a derived type, e.g.
>
> type circle_datatype
> =A0 =A0 real =A0 =A0 =A0 =A0 =A0 =A0 :: radius
> =A0 =A0 real =A0 =A0 =A0 =A0 =A0 =A0 :: x
> =A0 =A0 real =A0 =A0 =A0 =A0 =A0 =A0 :: y
> =A0 =A0 real =A0 =A0 =A0 =A0 =A0 =A0 :: z
> =A0 =A0 character(len=3D*) :: circle_label
> endtype circle_datatype
> type(circle_datatype) :: circle
>
> and want to refer to the individual elements via some indexing scheme,
> say in this example I want to change the value of circle%radius I would
> use index #1, or the z-coordinate I would use #4. Is there some method
> by which this is possible?
>
> I think IDL has a system for this, such that circle.radius can be
> referenced by circle.(0), but I really need Fortran's horsepower for
> this code!

The following might help:

!---------------------------------------------------------------------------
=
---
module circle_mod

implicit none

integer, parameter :: MAX_CIRCLE_LABEL =3D 64

type circle_datatype
real, pointer :: radius =3D> null()
real, pointer :: x      =3D> null()
real, pointer :: y      =3D> null()
real, pointer :: z      =3D> null()
real :: set(4) =3D 0.
character(MAX_CIRCLE_LABEL) :: label
end type circle_datatype

contains
subroutine create_circle(this, label)
type(circle_datatype), target, intent(INOUT) :: this
character(*), intent(IN) :: label
this%radius =3D> this%set(1)
this%x      =3D> this%set(2)
this%y      =3D> this%set(3)
this%z      =3D> this%set(4)
this%label =3D ADJUSTL(label)
end subroutine

subroutine destroy_circle(this)
type(circle_datatype), intent(INOUT) :: this
nullify(this%radius, this%x, this%y, this%z)
this%set =3D 0.
this%label =3D ''
end subroutine

end module circle_mod

program circle_test

use circle_mod

implicit none

type(circle_datatype), target :: circle

call create_circle(circle, 'unit_xy1')

circle%set =3D REAL([1, 1, 1, 0])
write (*, '((A,G13.6))') "circle's label =3D ", circle%label, &
"radius =3D ", circle%radius, 'x =3D ', circle%x, 'y =3D ', &
circle%y, 'z =3D ', circle%z

call destroy_circle(circle)

stop

end program circle_test
!---------------------------------------------------------------------------
=
---

Report this thread to moderator Post Follow-up to this message
Old Post
jwm
03-30-08 10:01 AM


Re: Reference to derived type element by index?
Rob Crain wrote:
> I have a derived type, e.g.
>
> type circle_datatype
>    real             :: radius
>    real             :: x
>    real             :: y
>    real             :: z
>    character(len=*) :: circle_label
> endtype circle_datatype
> type(circle_datatype) :: circle
>
>
> and want to refer to the individual elements via some indexing scheme,
> say in this example I want to change the value of circle%radius I would
> use index #1, or the z-coordinate I would use #4. Is there some method
> by which this is possible?
>
> I think IDL has a system for this, such that circle.radius can be
> referenced by circle.(0), but I really need Fortran's horsepower for
> this code!

If you don't mind making the code clumsy, error-prone, and difficult
to read, it's trivial ;).

Create a hidden helper type, something like
type helper
integer  ::  index
real     ::  x
character(len=whatever)  ::  c
! any other types that are in circle_datatype
endtype helper

Next create some generic operators or functions that return type
helper results.
i .func. value
or maybe
func(i,value)
returns a type helper result with the index set to i, and the
appropriate x or c set to value.  You'll, obviously, need one
function for each type of element in circle_datatype.  The
character one is trivial, the real one needs a select case.

You can then also provide overloads to do arithmetic between
type helper and the intrinsic types, helper types, and
circle_datatype and return type helper.

(i .func. circle) * 3.14 * (j .func. other_circle)**2

Then create an assignment operator that assigns type helper to
type circle by using an internal select case to assign to the
INDEXth element.

The result is that
circle = i .func. value

is ultimately equivalent to
call assigner(circle, i, value)

I'm not real happy with putting the circle subscript on the right,
it's ugly and error-prone.  But I think it'll work.

After thinking about this, why not just create a few generic
subroutines that implement the above call if you only want to
do assignments that update (but not use) elements?

If you're not in a big hurry and can wait until 2008, the new
Fortran allows pointer functions on the left hand side.
You could probably make
circle.element.i = whatever
do what you want.  But that won't be standard until later this
year.  It might take even longer to get a F2008 compiler :(.

Dick Hendrickson

Report this thread to moderator Post Follow-up to this message
Old Post
Dick Hendrickson
03-31-08 02:15 AM


Re: Reference to derived type element by index?
Since it's not mission critical and I'm pushed for time I opted for an
inelegant select case statement; it does the job. Thanks to all for your
responses though - when I get time to tune the code I'll revisit Dick's
suggestion, it looks like it might be the answer.

Report this thread to moderator Post Follow-up to this message
Old Post
Rob Crain
03-31-08 02:16 AM


Sponsored Links




Last Thread Next Thread Next
Pages (2): [1] 2 »
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 02:10 PM.

 
Free MCSE Braindumps | Real Estate Topics

Programming forum archive

Copyrights CodeComments.com 2004 - 2006

Powered by vBulletin Copyright 2000-2006 Jelsoft Enterprises Limited.