C576 (R556) An equivalence-object shall not be a designator with a base
object that is a dummy argument, a pointer, an allocatable variable,
a derived-type object that has an allocatable ultimate component, an
object of a nonsequence derived type, an object of a derived type
that has a pointer at any level of component selection, an automatic
object, a function name, an entry name, a result name, a variable with
the BIND attribute, a variable in a common block that has the BIND
attribute, or a named constant.
> Is it legal to equivalence allocatable arrays?
No.
As a general rule, equivalence is fundamentally static. In any case, as
a specific rule, it is not allowed with allocatable.
--
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
I (and Steven) already answered the question in the first sentence,
making the second one moot. But an unrelated comment on the second
occurs to me.
Even if equivalence was allowed with allocatable, the second question
wouldn't "make sense" because it assume an incorrect model for
equivalence. Equivalence is based on storage sequences - not on
variables. There thus isn't a "second array" to talk about. There can be
multiple variables, some arrays and some not, with various offsets into
the storage sequence. The question implicitly assumes that equivalence
looks like
equivalence (x,y)
but that isn't necesssarily the case.
I think if you look at the full form of equivalence, you'll pretty
quickly figure out that it can't plausibly work with allocatables. What
would happen if you equivalenced something to x(10) and then x got
allocated to only size 5? Or for a simple one - x allocatable and y not,
but y(2) equivalenced to x(3). Etc.
Sure, one could disallow 90% of the syntax of equivalence if
allocatables were involved, but then it would have so little of the
original feature left that it might as well be called something else.
> I think if you look at the full form of equivalence, you'll pretty
> quickly figure out that it can't plausibly work with allocatables. What
> would happen if you equivalenced something to x(10) and then x got
> allocated to only size 5?
If those five elements were x(8), x(9), x(10), x(11), x(12), then no
problem. But your point is well taken.
I'm just trying to determine the optimum way to deal with a particular
situation. Consider a data file, such as an image in FITS format. The
information on size and data type is stored in the header. After
reading
the number of rows and columns, as well as whether the values are
16-bit
integers, 32-bit integers, or 32-bit reals, one can compute how much
memory is needed to hold the image. But then you need a decision tree
for the numeric type to allocate and read. I was wondering if one
could
simply allocate a block of memory of the proper size and then
equivalence
the byte stream with the appropriate numeric type. But it looks like
I'll need to use a more tedious decision tree for each supported
numeric
type and repeat the ALLOCATE and READ statements for every one of them.
What's equally annoying is that the file reading process can occur
multiple times in the program, so the code needs to be repeated. That
is why subroutines were invented, so that the code could be reused,
but one can't declare the allocatable array in the main program and
then have the actual allocation take place in the subroutine. After
all, if it hasn't been allocated yet, then there is not yet any address
to pass to the subroutine. So my program is getting cluttered with a
lot of repeated code that deals with reading the header and data. Is
there a better way?
Yes, you can. If you use an F95 compiler that supports TR 15581 (which most of
them do, nowadays), then you can have subroutine dummy arguments that are
ALLOCATABLE -- that is, you can do the allocation in the subroutine.
After
> all, if it hasn't been allocated yet, then there is not yet any address
> to pass to the subroutine.
Not relevant, there's a lot more to an allocatable array than just its address.
cheers,
Rich
>> What's equally annoying is that the file reading process can occur
>> multiple times in the program, so the code needs to be repeated. That
>> is why subroutines were invented, so that the code could be reused,
>> but one can't declare the allocatable array in the main program and
>> then have the actual allocation take place in the subroutine.
> Yes, you can. If you use an F95 compiler that supports TR 15581 (which most of
> them do, nowadays), then you can have subroutine dummy arguments that are
> ALLOCATABLE -- that is, you can do the allocation in the subroutine.
Unfortunately, I'm using a FORTRAN77 compiler with some Fortran 90
extensions, such as allocatable arrays.
Why not 'upgrade' to Fortran 95? Your code should run in just the same way, and
you can start taking advantage of the other F9X features not present in your
compiler.
cheers,
Rich
> tho...@antispam.ham wrote:
> > Unfortunately, I'm using a FORTRAN77 compiler with some Fortran 90
> > extensions, such as allocatable arrays.
>
> Why not 'upgrade' to Fortran 95? Your code should run in just the same
> way, and you can start taking advantage of the other F9X features not
> present in your compiler.
That's my usual advice to people in situations like that. Assuming a
professional rather than a hobbiest situation, the cost of even the
relatively expensive compilers is negligable. If I billed for my time at
appropriate professional rates, it would cost more than a compiler for
one fairly short consulting session. That's not even counting the cost
of your time. I've had people seriously intending to invest multiple
man-weeks of full-time work rather than pay a few hundred dollars for a
newer compiler. I suppose that's their call. But I've also had people
surprised that I wasn't willing to spend multiple full-time days of my
own to help them avoid having to buy a compiler. (No, you aren't doing
that, but I have had other people do it).
There are even decent free f95 compilers available today. That's
relatively recent; I date it to roughly a year ago that I started
considering g95 viable for real work.
I consider using f77 today to be a voluntary choice. It is still a
viable choice for some people/applications. I don't tend to go on
crusades to convince people to convert for no particular reason. But
when I hear of people fighting with problems that have already been
solved, it does make me wonder why not use the solution that already
exists? Sometimes there are good answers to that question, but it is
just about the first question that springs to mind.
Hacking dynamic allocation support into f77, or even earlier, codes can
be done. Heck, it used to be done all the time. But it was sometimes a
*LOT* of overhead (in manpower - not computer resources). I've seen
codes where it was lesss work to completely rewrite the code than to
continue to maintain such old hacks. I've done such complete code
rewrites myself when faced with the need to port old programs that had
more code involved in memory managment than in the whole rest of the
program, including user interface and the real work.
And back to the imediate point, I can tell you what the standards allow,
but I'm not likely to be a very good resource for information about what
can be done with the particular extensions of some compiler. Though I
suppose you might quite plausibly be looking for the intersection of
what can be done with those f77 extensions while staying within the
bounds of the f90/f95/f2003 standards; that would be a sensible
question, I'd agree.
Attempting to be slightly more constructive (luckily I'm not billing for
my time :-)), yours sounds like a situation where I have been known to
use a simple storage buffer for the bits and then use transfer or
equivalence to convert the bits to appropriate types. You can use
transfer on allocatable arrays (or on darn near anything, though you
have to be careful to understanhd what you are getting in some cases, as
when pointers are involved). And although you can't equivalence an
allocatable array, you *CAN* (and I have) copy an individual element of
such an allocatable array to a scalar (or appropriately sized static
array) that is part of a "type-cheating" equivalence, and then copy out
the "other" type. Add the usual caveat about type cheating violating the
standard, but it will work anyway in most cases, and that's what the
situation specifically needs here. There is overhead involved in the
copying, but that overhead is small compared to I/O costs. I wouldn't
advise it in the middle of a time-critical computation loop, but it
should be ok as part of the I/O process.
<snip>
Aaaaargh! *HOBBYIST*! *HOBBYIST*! Ya spend years convincing me you know more
about Fortran than just about anyone, and then you come out with the Slashdotism
'hobbiest'. Once more, AAAARGH!
:)
cheers,
Rich
> Aaaaargh!...
You thought I could spell? :-)
Hey, although it is not one of my many particular spelling foibles, I
objected to the f2003 intrinsic function name get_environment_variable
on the basis that too many people would have trouble spelling it.
"Envoirment" is one that makes me cringe, but I see it enough to
recognize it as an issue. I lost that vote - and I do like the
functionality of the intrinsic, just not the name.
Double letters are one of my bigger weak spots. If it weren't for all
the times I've used it in OPEN statements, I still wouldn't be able to
spell "formatted" correctly.
I think the long name fits Fortran's preference for verbosity, and it's
easy to read. Compile errors will help with spelling.
But, it does bring up the usefulness of allowing the use of MODULE-style
procedure renaming for intrinsics, or even user non-module procedures.
Has that been discussed/proposed?
Joe
> But, it does bring up the usefulness of allowing the use of MODULE-style
> procedure renaming for intrinsics, or even user non-module procedures.
> Has that been discussed/proposed?
Well, I proposed putting that (and other) new intrinsic procedures into
an intrinsic module, but I just didn't get measurable support for that.
I even brought it up multiple times. It didn't even generate a lot of
debate, in that there wasn't enough support to make it worth debating. I
still think it would have been a good idea. There just seems to be a lot
of resistance to putting standard intrinsics into modules. I'm not
entirely sure why. I heard some explanations, but I didn't find them
convincing. But in the end, people didn't have to convince me - they
just had to vote for the proposals that did it the other way.
You might not be aware of a trick you can use even in f90. You *CAN* use
module-style renaming for intrinsic and external procedures. That can
allow you to avoid local name conflicts or just to add a synonym that
you find preferable for any reason. This doesn't change the global name,
so you still can't have something like two externals of the same name,
but you can do local renaming. You do it by using what I might call a
wrapper module. Example follows.
Suppose that your program involves cataloging the evils of the world and
you make extensive use of
type (transgression) :: sin(7)
Now you discover that you need to use trig functions. You write a module
module trig
intrinsic sin
end module trig
That's all you need in the module (unless you want to add other trig
functions or whatever). Now you can do
use trig, sine=>sin
to get sine as a local rename for the sin intrinsic function. If you
didn't want to have to write out all the renames in each of many places,
you could even wrap that, but it needs a second_level wrapper.
module trig_renamed
use trig, sine=>sin
end module trig_renamed
Then you can do just
use trig_renamed
in your multitude of places.
The same kind of tricks work for external functions.
Wouldn't it be better to do
use trig, original_sin => sin
Dick Hendrickson
So, you could in fact make your own module of all intrinsic functions. I
can see some merit in supplying intrinsics as a module, but I can also
think of some compatibility issues. Intrinsics have a special property
of being auto-magically implicitly declared once they are referenced.
For non-intrinsic procedures, only external subroutines are implicitly
declared. Only an intrinsic can supply a subroutine and function of the
same name, although I think the standard intrinsics avoid this.
Accessing these via a module means being explicit, which in most cases
is a good thing. In fact, it is a way to access both subroutine and
function forms for one of the shared-name intrinsics.
If you can make your own interface wrapper module, the only thing that
Fortran needs is some form of INTRINSIC-NONE statement, so you can
access everything explicitly through your own intrinsics module. Maybe
"INTRINSIC, ONLY :: ..." and/or "INTRINSIC, NONE".
Good Thing?
Sort of fits with my idea of an implicit-none statement for subroutines
as well. Why should implicit-none for variables be so popular, yet not
have the same option for intrinsics and external subroutines?
Joe
> If you can make your own interface wrapper module, the only thing that
> Fortran needs is some form of INTRINSIC-NONE statement...
> Good Thing?
I don't recall hearing that one suggested before, but I agree that it
sounds reasonable enough, and...
> Sort of fits with my idea of an implicit-none statement for subroutines
> as well. Why should implicit-none for variables be so popular, yet not
> have the same option for intrinsics and external subroutines?
That one I have heard before and definitely like. I don't know why it
isn't in. Maybe just that nobody pushed hard enough?
Thinking a little more, I don't see that you need two separate
statements at all. Whatever the spelling of the statement was (and I'd
go for simplicity there), it would just mean that all procedures needed
to be declared explicitly. That would include both external and
intrinsic ones. Anyway, that's the way I would do it, though I suppose
you could separate those two parts.
We already have ways to do the explicit declaration. No need to fancy up
the new feature with something like an "only" list. Even without the
trick I just showed of accessing intrisics through a module, there is
always the good old
intrinsic :: sin, cos
I would not view your intrinsic-none, under whatever spelling as meaning
that intrinsics could not be used at all - just that you have to declare
them, using the intrinsic statement, intrinsic attribute, or the module
wrapper trick.
> Why not 'upgrade' to Fortran 95? Your code should run in just the same way, and
> you can start taking advantage of the other F9X features not present in your
> compiler.
I'd do it in a heartbeat, as soon as someone has one for OS/2.
Does gcc work on OS/2? If so, you should automatically get gfortran when you use
gcc >= 4.0, if I understand thhings correctly.
cheers,
Rich
> Does gcc work on OS/2?
Yes, but I'm aware of only version 3.2.2 being available.
Don't know if gfortran will build under 3.2.2.
Ah. Ok. I forgot you were an OS/2 user. That sounds like a good reason
(not that you need justify yourself to me anyway, but if you were
trying, that justification would work well.)
> Ah. Ok. I forgot you were an OS/2 user. That sounds like a good reason
> (not that you need justify yourself to me anyway, but if you were
> trying, that justification would work well.)
Actually, I'm an OS/2 user, a Windows XP user, a Solaris user, a Linux
user, among other less frequently used systems. However, the program
in question uses some OS/2 system features, therefore for the case at
hand, I'm using Open Watcom and OS/2.
The fun part is that the implicit declaration overrides an explicit
declaration. Consider the program
PROGRAM MAIN
IMPLICIT NONE
INTRINSIC ATAN
INTEGER ATAN
PRINT *, ATAN(1.0)
END
When run, this program prints
0.7853982
Bob Corbett
I have found that "equivalencing" with allocatable arrays is simple;
just ALLOCATE another array of the alternate type and use LOCATION =
LOC(<firstarray>); Deallocate of the first one automatically dumps both.
> I have found that "equivalencing" with allocatable arrays is simple;
> just ALLOCATE another array of the alternate type and use LOCATION =
> LOC(<firstarray>); Deallocate of the first one automatically dumps both.
Thanks! I'll give that a try. I've got a fair bit of experience
using that form of the Watcom ALLOCATE statement now.
Just be aware that whatever this is, it doesn't bear much relation to
standard Fortran. If it meets your need, fine, but just be sure you
know.
From the description, it sounds to me closer to an f90 pointer than an
allocatable. These are two of the most fundamental differences between
pointers and allocatables in f90 - that multiple pointers can have the
same target, and a pointer can point to an existing target instead of
necessarily allocating a new one, while an allocatable always has its
own allocation.
The only one I remember is EQUIVALENCE, which I believe I got
right the first time but I wasn't so sure about it. After
that I remembered it, but I wouldn't be surprised if some
people got it wrong. (It mighe be that I remember it from
valence, as in chemical bonding.)
I have seen INTERGER before, and people who couldn't figure out
what was wrong. I believe there are some compilers with spell
checking and correcting built in, but that is rare.
I wouldn't have minded getenv(), though. Unix has a history
of short names. There is a story about asking the unix creators
some years later what they would do differently, and the only
one was to spell creat() with an e. (The system call to create
a new file, as in OPEN with STATUS='NEW'.
-- glen
>> Robert Baer wrote:
>>> I have found that "equivalencing" with allocatable arrays is simple;
>>> just ALLOCATE another array of the alternate type and use LOCATION =
>>> LOC(<firstarray>); Deallocate of the first one automatically dumps both.
>> Thanks! I'll give that a try. I've got a fair bit of experience
>> using that form of the Watcom ALLOCATE statement now.
> Just be aware that whatever this is,
It associates a variable name with a memory address given by the
value of the LOCATION= option.
> it doesn't bear much relation tostandard Fortran.
There was a time when I eschewed extensions. But nowadays, when
I'm using an older compiler, I don't mind using extensions to it that
are
supported in newer compilers, such as DO ENDDO EXIT and CYCLE,
because the code is still fairly portable. With the particular case at
hand, however, the program relies on some operating system calls, so
it's inherently non-portable, so there's really no reason to avoid
using
extensions.
By the way, there was something I forgot to mention in my earlier
reply, where you mentioned that you forgot I use OS/2. I said that
I use a variety of operating systems. Perhaps you recall an earlier
question of mine about the editor in CVF, whose "save as" annoys
me because it insists on taking my "sample" filename and changing
it into "sample.txt" when using the editor to write something other
than source code. I had asked whether there was some way to
tell CVF that I really mean "sample" without any extension.
Somebody suggested that the way to override the addition of
the .txt extension was to put the filename in quotation marks.
Tried that, doesn't work.
Hmmm...If quotes work, how about trying "sample. " ?