For Programmers: Free Programming Magazines  


Home > Archive > Fortran > April 2007 > Arithmetic operation on derived type









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Arithmetic operation on derived type
reubendb

2007-04-13, 7:04 pm

Hello,

Supposed I have the following module containing derived types
definition:
------------------
module physicalQuantityModule:
type, public :: thermodynamicType
sequence
real &
:: density = 1.0, &
temperature = 1.0, &
pressure = 1.0
real, dimension(3) &
:: velocity = 1.0
end type thermodynamicType

type, public :: nucleiType
sequence
real &
:: mass = 1.0, &
spin = 1.0, &
excess = 1.0
end type nucleiType

type, public :: physicalQuantityType
type(thermodynamicType), pointer &
:: thermoProfile => NULL()
type(nucleiType), pointer &
:: nuclei => NULL()
type(thermodynamicType), pointer &
:: auxiliary => NULL()
end type physicalQuantityType

contains

subroutine addWithNumber(myQuantity, number)
type(physicalQuantityType), intent(inout) &
:: myQuantity
real, intent(in) &
:: number

! Need to be implemented
end subroutine addWithNumber


subroutine multiplyWithNumber(myQuantity, number)
type(physicalQuantityType), intent(inout) &
:: myQuantity
real, intent(in) &
:: number

! Need to be implemented
end subroutine multiplyWithNumber

end module physicalQuantityModule
----------

and a program that uses the module:
-------------
program physicalQuantity
use physicalQuantityModule
implicit none
type(physicalQuantityType) &
:: myQuantity

allocate(myQuantity%thermoProfile)
allocate(myQuantity%nuclei)
allocate(myQuantity%auxiliary)

call addWithNumber(myQuantity, 10.0)
call multiplyWithNumber(myQuantity, 3.0)

print*, myQuantity%thermoProfile%density

deallocate(myQuantity%thermoProfile)
deallocate(myQuantity%nuclei)
deallocate(myQuantity%auxiliary)

end program physicalQuantity
---------

As you can see, the subroutine addWithNumber() and
multiplyWithNumber() are not implemented. My question is how to best
implement this without enumerating the member of the derived type one
by one (ie: doing myQuantity%thermoProfile%density + 1, etc).
I am wondering, since thermodynamicType and nucleiType are defined
with Sequence, if I somehow can do something similar to array
operation to do the arithmetic. At first I tried something like

subroutine addWithNumber(myQuantity, number)
type(physicalQuantityType), intent(inout) &
:: myQuantity
real, intent(in) &
:: number
real, dimension(7)
:: packedThermoProfile
real, dimension(3)
:: packedNucleiType
equivalence(myQuantity%thermoProfile, packedThermoProfile)
equivalence(myQuantity%nucleiType, packedNucleiType)

packedThermoProfile = packedThermoProfile + number
packedNucleiType = packedNucleiType + number

end subroutine addWithNumber

but this obviously doesn't work since the argument of equivalence()
cannot be pointer. So I am not sure if there any other way to do this.
Is there possibly any way to do this without the need to enumerate one
by one the member of the type ?

Thanks in advance for any help.
RDB

Michael Metcalf

2007-04-13, 7:04 pm


"reubendb" <reubendb@gmail.com> wrote in message
news:1176486168.614995.226660@y5g2000hsa.googlegroups.com...
> So I am not sure if there any other way to do this.
> Is there possibly any way to do this without the need to enumerate one
> by one the member of the type ?
>

If you want to add 'derived type' to 'intrinsic type' in many places, you
need to write a function that overloads the + operator for that combination.
For details see, e.g., p. 44 of "Fortran 95/2003 Explained":

function add_interval_real(a,b)

type(interval) :: add_interval_real

type(interval), intent(in) :: a

real, intent(in) :: b

add_interval_real%lower = a%lower + b

add_interval_real%upper = a%upper + b end function add_interval_real



Regards,



Mike Metcalf


reubendb

2007-04-13, 7:04 pm

On Apr 13, 4:34 pm, "Michael Metcalf" <michaelmetc...@compuserve.com>
wrote:
> "reubendb" <reube...@gmail.com> wrote in message
>
> news:1176486168.614995.226660@y5g2000hsa.googlegroups.com...> So I am not sure if there any other way to do this.
>
> If you want to add 'derived type' to 'intrinsic type' in many places, you
> need to write a function that overloads the + operator for that combination.
> For details see, e.g., p. 44 of "Fortran 95/2003 Explained":
>
> function add_interval_real(a,b)
>
> type(interval) :: add_interval_real
>
> type(interval), intent(in) :: a
>
> real, intent(in) :: b
>
> add_interval_real%lower = a%lower + b
>
> add_interval_real%upper = a%upper + b end function add_interval_real
>


Hello,
I understand that I could do that. However that requires me to
enumerate the members of the type and do operation on them on by one.
Using your example, I was hoping I could do something like with
"equivalence(a, packedA)", where packedA is an array with the size =
the number of member of a, then I could do an array operation on
packedA.

But obviously this doesn't work in my case, as I've shown in my
original post, because the member of my derived type is a pointer. I
even tried removing the pointer attribute, but again, equivalence
doesn't work with something like:
equivalence(myQuantity%thermoProfile, packedThermoProfile)
in my example above, although myQuantity%thermoProfile is a sequence
derived type.

RDB

Paul van Delst

2007-04-13, 7:04 pm

reubendb wrote:
> On Apr 13, 4:34 pm, "Michael Metcalf" <michaelmetc...@compuserve.com>
> wrote:
>
> Hello,
> I understand that I could do that. However that requires me to
> enumerate the members of the type and do operation on them on by one.
> Using your example, I was hoping I could do something like with
> "equivalence(a, packedA)", where packedA is an array with the size =
> the number of member of a, then I could do an array operation on
> packedA.
>
> But obviously this doesn't work in my case, as I've shown in my
> original post, because the member of my derived type is a pointer. I
> even tried removing the pointer attribute, but again, equivalence
> doesn't work with something like:
> equivalence(myQuantity%thermoProfile, packedThermoProfile)
> in my example above, although myQuantity%thermoProfile is a sequence
> derived type.


Well, if you want the ability to add the same number to a bunch of fundamentally different
"things" (i.e. thermodynamic temperature vs nuclei spin), don't treat the things as
different. If you want to use array operations, then bung 'em all in an array rather than
in separate structures. Yeah, I know I'm being flippant, but....

....what are you going to do when you want to add one number to just the thermodynamicType
portions of the physicalQuantityType structure, and another number to the nucleiType portion?

I guess I'm having a hard time figuring out why what you want to do would be useful in the
first place (and, in my defense (defence?), it is Friday arvo.... the brain is spinning
down for the w. :o)

cheers,

paulv

--
Paul van Delst Ride lots.
CIMSS @ NOAA/NCEP/EMC Eddy Merckx
Ph: (301)763-8000 x7748
Fax:(301)763-8545
Michael Metcalf

2007-04-13, 7:04 pm


"reubendb" <reubendb@gmail.com> wrote in message
news:1176501311.945996.270750@p77g2000hsh.googlegroups.com...
> On Apr 13, 4:34 pm, "Michael Metcalf" <michaelmetc...@compuserve.com>
> wrote:
>
> But obviously this doesn't work in my case, as I've shown in my
> original post, because the member of my derived type is a pointer. I
> even tried removing the pointer attribute, but again, equivalence
> doesn't work with something like:
> equivalence(myQuantity%thermoProfile, packedThermoProfile)
> in my example above, although myQuantity%thermoProfile is a sequence
> derived type.
>

Right, at some point the nitty-griity has to spelled out.

Apart from that I have 2 questions:

1) Is there any other reason to use SEQUENCE than your attempt to
equivalence? (Note that variables of derived types can be equivalenced only
if they are both of the *same* type as well as of a sequence type.)

2) Many compilers have implemented to TR that allows allocatable components
in derived types. Does yours? IF so, you can replace POINTER by the more
appropriate ALLOCATABLE.

Regards,

Mike Metcalf


reubendb

2007-04-13, 7:04 pm

On Apr 13, 6:11 pm, Paul van Delst <Paul.vanDe...@noaa.gov> wrote:

> Well, if you want the ability to add the same number to a bunch of fundamentally different
> "things" (i.e. thermodynamic temperature vs nuclei spin), don't treat the things as
> different. If you want to use array operations, then bung 'em all in an array rather than
> in separate structures. Yeah, I know I'm being flippant, but....


Hello,
Please let me add to my original post that the example I gave is a
very much stripped down version (and thus rather contrived) of our
code base. The different derived types is essential to our code base
to model physical processes and keep our code modular, but the problem
I'm asking here is strictly computing (Fortran) problem, thus I just
cooked up the simplest example that illustrate it. So no, I can't just
"bung 'em all in an array" :).

> ...what are you going to do when you want to add one number to just the thermodynamicType
> portions of the physicalQuantityType structure, and another number to the nucleiType portion?


Of course in that case I just overload the subroutine addWithNumber().
But this again where I'm stuck, as I am trying to find a way to not
have to enumerate the member of the type to do this. I guess my
biggest gripes right now is why can't "equivalence" do something like:
equivalence(myQuantity%thermoProfile, thermoProfileArray)

or even just
equivalence(thermoProfile, thermoProfileArray)
where thermoProfile is a dummy argument but sequence derived type.

I guess I'm hitting a real wall with no way around it now.

Thanks for the replies.
RDB

glen herrmannsfeldt

2007-04-13, 7:04 pm

reubendb wrote:
(snip)

> As you can see, the subroutine addWithNumber() and
> multiplyWithNumber() are not implemented. My question is how to best
> implement this without enumerating the member of the derived type one
> by one (ie: doing myQuantity%thermoProfile%density + 1, etc).
> I am wondering, since thermodynamicType and nucleiType are defined
> with Sequence, if I somehow can do something similar to array
> operation to do the arithmetic. At first I tried something like


Without saying whether I think it is good or bad, I will note
that PL/I allows structure expressions. An operation
with a scalar applies to each member, with a like structure, member
by member, or with the BY NAME option, between members with the
same name. There doesn't seem to be much interest in adding
this to Fortran.

-- glen

Ken Fairfield

2007-04-13, 7:04 pm

reubendb wrote:
[...]
> Of course in that case I just overload the subroutine addWithNumber().
> But this again where I'm stuck, as I am trying to find a way to not
> have to enumerate the member of the type to do this. I guess my
> biggest gripes right now is why can't "equivalence" do something like:
> equivalence(myQuantity%thermoProfile, thermoProfileArray)
>
> or even just
> equivalence(thermoProfile, thermoProfileArray)
> where thermoProfile is a dummy argument but sequence derived type.
>
> I guess I'm hitting a real wall with no way around it now.


Honestly, I think the only way to achieve what you've outlined
is to make one or more components of the derived types arrays.
Then you can use whole-array arithmetic on those components.

I think a larger question is what are you trying to accomplish?
You've presented the _solution_ you want (which doesn't work) but
not the _problem_ to be solved.

How many individual components are in the actual derived types? If
it's only the half-dozen or so you showed in your example, I can't
understand why you're fighting so hard to save 5 lines of code...
If, on the other hand, there are scores of components, perhaps you
need to replace the numerous individual components with one, or a few
arrays, each indexed by named mnemonic constants.

In any case, your proposed solution is a non-starter.

-Ken
--
Ken & Ann Fairfield
What: Ken dot And dot Ann
Where: Gmail dot Com
reubendb

2007-04-16, 8:05 am

On Apr 13, 6:18 pm, "Michael Metcalf" <michaelmetc...@compuserve.com>
wrote:
> "reubendb" <reube...@gmail.com> wrote in message
>
> news:1176501311.945996.270750@p77g2000hsh.googlegroups.com...> On Apr 13, 4:34 pm, "Michael Metcalf" <michaelmetc...@compuserve.com>
>
>
> Right, at some point the nitty-griity has to spelled out.


OK, a little bit more backgroud to my original question.
Earlier, before my original post here, I had something like this in
the module:

type, public :: hardPhysicalQuantityType
sequence
type(thermodynamicType) &
:: thermoProfile
type(nucleiType) &
:: nuclei
type(thermodynamicType) &
:: auxiliary
end type hardphysicalQuantityType

So here I defined a similar but separate type with sequence qualifier.
Now in the subroutine to do the arithmetic, we can do something like:

subroutine addWithNumber(myQuantity, number)
type(physicalQuantityType), intent(inout) &
:: myQuantity
real, intent(in) &
:: number
type(hardPhysicalQuantityType) &
:: myHardQuantity
real, dimension(15)
:: packedPQ

equivalence(myHardQuantity, packedPQ)

! Copy from myQuantity to myHardQuantity
myHardQuantity%thermoProfile = myQuantity%thermoProfile
myHardQuantity%nuclei = myQuantity%nuclei
myHardQuantity%auxiliary = myQuantity%auxiliary

! Do arithmetic
packedPQ = packedPQ + number

! copy back to myQuantity
myQuantity%thermoProfile = myHardQuantity%thermoProfile
myQuantity%nuclei = myHardQuantity%nuclei
myQuantity%auxiliary = myHardQuantity%auxiliary
end subroutine addWithNumber

This accomplishes what I wanted. The nice thing about this is I don't
have to drill down to the member of my derived type (which itself
could be a derived type); I just need to do this for the top most
level of my derived type, in this case "physicalQuantityType". It
turns out, however, during profiling of our code that the copying is
too expensive. Hence the reason of my original post; I am trying to
get away to do this without copying.

> Apart from that I have 2 questions:
>
> 1) Is there any other reason to use SEQUENCE than your attempt to
> equivalence?

No, not really

Thus the reason of "frustration" with the fact that equivalence
doesn't work with pointer like I mentioned. I mean, the compiler has
all the information that the object being pointed to is a sequence
derived type, so why can't it make an equivalence of the object
pointed by the pointer, with an array.
If this can be done, I imagine it's also nice to have if for code run
on a vector machine, since the SEQUENCE ensures that the member of the
derived type is in contiguous, thus an operation on a sequence derived
type would be just like a vector operation.

BTW, Is there any divantageous to use SEQUENCE ?

> 2) Many compilers have implemented to TR that allows allocatable components
> in derived types. Does yours?

Yes, mine implement that.

>IF so, you can replace POINTER by the more
> appropriate ALLOCATABLE.

In this example, yes you're right. I'm not sure with the original code
(I have to check if it's only for deferred allocation of if the
pointer is actually use as an alias also). But how does using
ALLOCATABLE help me in this problem ?

Thanks for your responds. I appreciate the discussion.
RDB


reubendb

2007-04-16, 8:05 am

On Apr 13, 6:54 pm, Ken Fairfield <K...@Napili.Fairfield.Home> wrote:
<snip>
> I think a larger question is what are you trying to accomplish?
> You've presented the _solution_ you want (which doesn't work) but
> not the _problem_ to be solved.
>
> How many individual components are in the actual derived types? If
> it's only the half-dozen or so you showed in your example, I can't
> understand why you're fighting so hard to save 5 lines of code...


Well, in my code it's really much more that 5 lines :) (the member of
derived types could be another derived types with 2-3 level deep).
Plus it seems more elegant if this can be done. As in my previous
reply, I just don't understand why equivalence can't work / very
restrictive since the compiler has the information to determine that
the derived type is of sequence type. I can't see why EQUIVALENCE with
an array can't just work with any contiguous memory location. Sometime
I wish Fortran had a pointer with more flexibility that we can do
pointer arithmetic like in C.

So what I am trying to accomplish is exactly that, I'm trying to avoid
doing arithmetic for my derived type by having to drill down in each
member, enumerate them for each operation, and write reams of code. I
supposed I could have that done already if I had spent the time
writing the code rather than fighting this here, but curiosity got the
better of me :).


> If, on the other hand, there are scores of components, perhaps you
> need to replace the numerous individual components with one, or a few
> arrays, each indexed by named mnemonic constants.
>
> In any case, your proposed solution is a non-starter.


In my reply to Mike Metcalf that I just sent, I showed what I did
originaly, and the problem with it.

Thanks for the discussion.
RDB

Michael Metcalf

2007-04-16, 10:04 pm


"reubendb" <reubendb@gmail.com> wrote in message
news:1176725311.615011.184320@l77g2000hsb.googlegroups.com...
>
> BTW, Is there any divantageous to use SEQUENCE ?


When derived types were introduced into the language, it was intended that
the layout of data be left to the compiler as it knows how do do this most
efficiently in any given situation. However, in order to provide some
integration between old and new features, the SEQUENCE statement was added
to allow objects of derived type to participate in storage association.
Purists would regard the use of this feature as a desperate last measure to
be avoided at all costs in new programs.

>
> Yes, mine implement that.
>
> In this example, yes you're right. I'm not sure with the original code
> (I have to check if it's only for deferred allocation of if the
> pointer is actually use as an alias also). But how does using
> ALLOCATABLE help me in this problem ?
>

It doesn't. It's simply that you're not using pointers to point, merely to
provide access to dynamic storage. F95 does not allow allocatable arrays to
be used as components or as dummy arguments, but the TR does.

Regards,

Mike Metcalf


Paul van Delst

2007-04-16, 10:04 pm

reubendb wrote:
> On Apr 13, 6:54 pm, Ken Fairfield <K...@Napili.Fairfield.Home> wrote:
> <snip>
>
> Well, in my code it's really much more that 5 lines :) (the member of
> derived types could be another derived types with 2-3 level deep).
> Plus it seems more elegant if this can be done. As in my previous
> reply, I just don't understand why equivalence can't work / very
> restrictive since the compiler has the information to determine that
> the derived type is of sequence type. I can't see why EQUIVALENCE with
> an array can't just work with any contiguous memory location. Sometime
> I wish Fortran had a pointer with more flexibility that we can do
> pointer arithmetic like in C.


From the f95 standard, section 5.5.1, the first constraint:

"An equivalence-object shall not be a dummy argument, a pointer, an allocatable array,
an object of a nonsequence derived type, an object of a sequence derived type
containing a pointer at any level of component selection, an automatic object, a
function name, an entry name, a result name, a named constant, a structure
component, or a subobject of any of the preceding objects."

> So what I am trying to accomplish is exactly that, I'm trying to avoid
> doing arithmetic for my derived type by having to drill down in each
> member, enumerate them for each operation, and write reams of code. I
> supposed I could have that done already if I had spent the time
> writing the code rather than fighting this here, but curiosity got the
> better of me :).


My personal approach is if I'm going to need a structure, then I will probably need
various operations to be performed on that structure. Thus for every structure you create,
there should exist the functions to perform what you want to do (definitely without
needing to copy it). Trying to equivalence a whole mess of structures to an array simply
so you can add a number to all of them at once is, well, a bit of a cheat (not meant as a
personal slight!). In Fortran95 sometimes there is not much more to do that to simply
write the boilerplate code that adds a number to all the structure components. For example:

(the following code assumes you also have the necessary routines to allocate the structure
pointer heirarchies, check them for pointer association etc..)

! Submodule 1
module s1_define
type :: s1_type
real :: x, y
real :: z(3)
end type s1
contains
subroutine addnumber(s1,a)
type(s1_type), intent(in out) :: s1
real, intent(in) :: a
s1%x = s1%x + a
s1%y = s1%y + a
s1%z = s1%z + a
end subroutine addnumber
end module s1_define

! Submodule 2
module s2_define
type :: s2_type
real :: x
real :: z(10)
end type s1
contains
subroutine addnumber(s2,a)
type(s2_type), intent(in out) :: s2
real, intent(in) :: a
s2%x = s2%x + a
s2%z = s2%z + a
end subroutine addnumber
end module s2_define

! Main module
module s_define
use s1_define, s1_addnumber=>addnumber
use s2_define, s2_addnumber=>addnumber
private
public :: s_type
public :: addnumber
type :: s_type
type(s1_type), pointer :: s1(:) => NULL()
type(s2_type), pointer :: s2(:) => NULL()
end type
contains
subroutine addnumber(s,a)
type(s_type), intent(in out) :: s
real, intent(in) :: a
call s1_addnumber(s%s1,a)
call s2_addnumber(s%s2,a)
end subroutine addnumber
end module s_define


! Main program
program test_s
use s_define
type(s_type) :: s

....allocate the various components and subcomponents...
.... stick data into the various components....

a = 10.0
call addnumber(s, a)

... do other stuff...

end program test_s


So what you end up with are a bunch of completely self-contained submodules. The main
module then simply "ties" them all together. Note that the only public entities in the
main module, s_define, are those defined in s_define, NOT s1_define, s2_define, etc.

I do this sort of thing all the time, and apply the same prinicple to the allocation
routines, destruction routines, assignment routines, equal_test routines, etc... At the
very top level you simply calling a bunch of routines to do all the work for the sub
components of your structure.

It is a fair bit more code writing but since it's (mostly) boilerplate you can generate a
lot of it automatically. I use ruby scripts to do it for my code, but you could also use
f95 itself. It really depends on how often you use a particular code design (i.e. is it
worth it to spend the time writing the code that writes your code?). For me, the above
sort of setup has become almost idiomatic -- I generate an f95 structure definition, run
it through my ruby interpreter and out pops several hundred lines of f95 code to
manipulate said structure. It's not perfect (I'm still learning ruby :o) and sometimes I
still need to hand-edit certain sections for particular situations, but the drudgery of
generating lots of boilerplate code has gone.

Anyway...


cheers,

paulv

--
Paul van Delst Ride lots.
CIMSS @ NOAA/NCEP/EMC Eddy Merckx
Beliavsky

2007-04-16, 10:04 pm

On Apr 16, 10:25 am, Paul van Delst <Paul.vanDe...@noaa.gov> wrote:

<snip>

> It is a fair bit more code writing but since it's (mostly) boilerplate you can generate a
> lot of it automatically. I use ruby scripts to do it for my code, but you could also use
> f95 itself. It really depends on how often you use a particular code design (i.e. is it
> worth it to spend the time writing the code that writes your code?). For me, the above
> sort of setup has become almost idiomatic -- I generate an f95 structure definition, run
> it through my ruby interpreter and out pops several hundred lines of f95 code to
> manipulate said structure. It's not perfect (I'm still learning ruby :o) and sometimes I
> still need to hand-edit certain sections for particular situations, but the drudgery of
> generating lots of boilerplate code has gone.


This sounds useful. If you and when you are willing to "publish" this
tool, please let us know.

jamesgiles@att.net

2007-04-16, 10:04 pm

On Apr 16, 7:55 am, "Michael Metcalf" <michaelmetc...@compuserve.com>
wrote:
> "reubendb" <reube...@gmail.com> wrote in message
> news:1176725311.615011.184320@l77g2000hsb.googlegroups.com...

....
....[color=darkred]
> Purists would regard the use of this feature as a desperate
> last measure to be avoided at all costs in new programs.


On the other hand, the committee removed the EXTENSIBLE keyword
before F2003 was approved. Fortunately, SEQUENCE makes a type
non-extensible. And, as far as I can tell, few if any compilers
actually rearrange components anyway - so SEQUENCE is probably
not a big killer of optimization.

--
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

Michael Metcalf

2007-04-16, 10:04 pm


<jamesgiles@att.net> wrote in message
news:1176736652.654284.34810@n59g2000hsh.googlegroups.com...
> And, as far as I can tell, few if any compilers
> actually rearrange components anyway - so SEQUENCE is probably
> not a big killer of optimization.
>

If I run the following with CVF, it prints 2001 2002:

type t1
sequence
integer i
double precision d(1000)
end type t1

type t2
integer i
double precision d(1000)
end type t2

type(t1) a
type(t2) b

inquire(iolength=l1) a
inquire(iolength=l2) b

print *, l1, l2
end

It kindly issues a warning for t1 but does do padding for t2 in this classic
case (not, I admit, rearrangement).

Regards,

Mike Metcalf


Paul van Delst

2007-04-16, 10:04 pm

Beliavsky wrote:
> On Apr 16, 10:25 am, Paul van Delst <Paul.vanDe...@noaa.gov> wrote:
>
> <snip>
>
>
> This sounds useful. If you and when you are willing to "publish" this
> tool, please let us know.


I'm in the midst of rewriting portions of it (again! Like I said, I'm still learning ruby
:o), but after that, sure.

BTW, for those amongst us who are object-oriented-challenged, I've found ruby to be a
great learning tool for understanding all that stuff. I started learning ruby in
preparation for F2003 and, although I'm still in the "consciously incompetent" stage, it's
made OOP principles a lot more meaningful to me in that I can easily apply them to an
interesting (to me) project. And, ruby is just plain old fun. :o)

cheers,

paulv

--
Paul van Delst Ride lots.
CIMSS @ NOAA/NCEP/EMC Eddy Merckx
jamesgiles@att.net

2007-04-16, 10:04 pm

On Apr 16, 9:40 am, "Michael Metcalf" <michaelmetc...@compuserve.com>
wrote:
> <jamesgi...@att.net> wrote in message
>
> news:1176736652.654284.34810@n59g2000hsh.googlegroups.com...
> And, as far as I can tell, few if any compilers
>
> If I run the following with CVF, it prints 2001 2002:


[... example of padding ...

> It kindly issues a warning for t1 but does do padding for t2
> in this classic case (not, I admit, rearrangement).


Implementations can add padding to sequence types - though
maybe not in this case due to the requirement that sequence
types whose components are all numeric-storage-unit multiples
be allowed to storage associate with, say, common blocks.
Most programmers would probably put the components with the
largest boundary requirements first in thier type declarations
to avoid this anyway (even for the non-sequence type). In any
event, it still doesn't eliminate the value of SEQUENCE for
new code development.

(Admittedly, I'd seldom use SEQUENCE if the committee hadn't
removed the EXTENSIBLE keyword. As it is, I've just made an
automatic habit of using SEQUENCE unless I have some compelling
reason not to.)

--
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


John Harper

2007-04-16, 10:04 pm

In article <YNMUh.4242$0S1.950@trnddc01>,
Michael Metcalf <michaelmetcalf@compuserve.com> wrote:
>
><jamesgiles@att.net> wrote in message
>news:1176736652.654284.34810@n59g2000hsh.googlegroups.com...
>If I run the following with CVF, it prints 2001 2002:
>
>type t1
>sequence
>integer i
>double precision d(1000)
>end type t1
>
>type t2
>integer i
>double precision d(1000)
>end type t2
>
>type(t1) a
>type(t2) b
>
>inquire(iolength=l1) a
>inquire(iolength=l2) b
>
>print *, l1, l2
>end


With g95 -Wall -Wextra it prints 8004 8004 and issues no warning.
With Sun f95 -w4 it prints 8004 8008 having warned at compile time
as follows: 'CAUTION: Alignment of the component "D" of the Derived
Type "T1" may cause performance degradation.'

I can see why the first number printed is exactly 4 times CVF's,
as the length is in processor-dependent units, but not why the
second varies.

Are CVF and Sun including some unnecessary length or is g95 omitting
something it shoudn't?

-- John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington 6140, New Zealand
e-mail john.harper@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045
Ken Fairfield

2007-04-16, 10:04 pm

John Harper wrote:
[...]

> I can see why the first number printed is exactly 4 times CVF's,
> as the length is in processor-dependent units, but not why the
> second varies.
>
> Are CVF and Sun including some unnecessary length or is g95 omitting
> something it shoudn't?


The Sun compiler is, apparently, adding 4 "anonymous" bytes of
storage after the first 4-byte integer to assure access to the
8-byte double precision array is optimally aligned. g95 omits
that alignment padding. That is the whole point of Mike's
example, that the SEQUENCE keyword may (or may not?) suppress
padding, and therefore, affect performance due to misaligned
access (per the OP's question).

-Ken
--
Ken & Ann Fairfield
What: Ken dot And dot Ann
Where: Gmail dot Com
glen herrmannsfeldt

2007-04-16, 10:04 pm

Ken Fairfield wrote:

(snip)

> The Sun compiler is, apparently, adding 4 "anonymous" bytes of
> storage after the first 4-byte integer to assure access to the
> 8-byte double precision array is optimally aligned. g95 omits
> that alignment padding. That is the whole point of Mike's
> example, that the SEQUENCE keyword may (or may not?) suppress
> padding, and therefore, affect performance due to misaligned
> access (per the OP's question).


If I understand SEQUENCE, not using it would allow the rearrangement
of data items for optimal packing and alignment. With SEQUENCE only
padding can be used for alignment.

There is a long history of not providing optimal (eight byte)
alignment for double precision data on x86, as it wasn't
required or useful on the 32 bit (data bus) 80486.

The sizeof a C struct includes any padding needed to make a
properly aligned array. Do either gfortran or g95 allow
for a type to match a C struct?

-- glen

Richard Maine

2007-04-16, 10:04 pm

glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:

> If I understand SEQUENCE, not using it would allow the rearrangement
> of data items for optimal packing and alignment. With SEQUENCE only
> padding can be used for alignment.


Then you misunderstand SEQUENCE. There are no such conditions. The
compiler may rearrange items quite freely, even with SEQUENCE. Except
for the special cases of numeric and character sequence (which are very
restrictive - more so than the terms might imply), there are no
restrictions at all on rearrangement, padding, or anything.

As to what compilers are likely to do, that's another matter. But the
standard has no restrictions at all outside of the two special cases.

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







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com