Is there a good mechanism to get around the restriction that you can't
EQUIVALENCE an array that has been dynamically allocated? I have a REAL and
AN INTEGER array that are equivalenced so that some elements are real and
some are integer, but I now want to dynamically allocate the array. Any
thoughts?
Please reply by both email and in the newsgroup.
Thanks,
Dave
--
--
Easy: ALLOCATE (NEW*SIZE,LOCATION=LOC(OLD))
Just a word of warning: DEALLOCATing any of these arrays will "drop"
*all* of them.
Also, please note that dynamic arrays cannot be passed in COMMON or in
arguments (either direction).
Instead, pass a pointer to the array and re-allocate it (a new name
can be used if one wants).
Oh. I forgot. the C/C++ guys say FORTRAN ain't gotz no pointers, not
even Irish Setters.
Just chuckle and ignore their nonesense; it was easy to do when
FORTRAN first came out, and is still easy.
ie
integer N(10)
real A(10)
equivalence(N,A)
a(5)=1.5
N(6)=1.
write(*,*)N(5),A(6) // would look like garbage
write(*,*)A(5),N(6) // would look like what I set them too.
But How can I do this with a allocatable array?
"Michael Metcalf" <11354...@CompuServe.COM> wrote in message
news:9f8cdp$akh$2...@sshuraaa-i-1.production.compuserve.com...
> This function [transfer] seems to translate it from a real to an integer....
No, transfer does no translation. It just copies the bits. It is a
direct analogue to what EQUIVALENCE does, expect that TRANSFER always
involves copying because it is a function (possibly subject to
compiler optimization, but in concept it is a copy). There may be
performance issues with TRANSFER if you are using it a lot.
And if you want to modify something, you may need to transfer out
and then transfer back in, but you will get the same numbers with
transfer as you would have with equivalence.
As you have noted, you can't directly do equivalence with allocatable
arrays. Although equivalence is widely used to do "type cheating",
it's basic definition has more to do with sharing storage.
There are ways that you may be able to "cheat" and confuse the
compiler into the effect of an equivalence to an allocated array,
but I can't recommend them. The most "obvious" one is illegal for
multiple reasons and is likely to cause undetected wrong answers
if the compiler does some kinds of optimization based on it's
understanding (which you have managed to fool). I'm referring to
the possibility of passing the array as an actual argument to multiple
dummies of different types. If you manage to hide the illegal type
mismatch from the compiler, this might happen to work for some
cases. But I'm not going to show sample code. (If you can't
figure it out from the description, then you probably don't know
enough to keep "out of trouble" with it, and I don't want you
tracing future subtle bugs back to me. Even if you can figure it
out from the description, you may not be able to avoid it's potential
bugs. You have been warned.)
One other possibility, although you can't directly equivalence the
the dynamically array itself, is to copy elements or portions of
the array to something that is in an equivalence class. Something
like
real, allocatable :: a(:)
real :: b
real :: n
equivalence(b,n)
....
(presumably allocate and define A)
...
b = a(42)
write (*,*) n
n = something_else
a(42) = b
Like the TRANSFER approach, this involves copying.
--
Richard Maine | Good judgment comes from experience;
email: my last name at host.domain | experience comes from bad judgment.
host: altair, domain: dfrc.nasa.gov | -- Mark Twain
> ALLOCATE (NEW*SIZE,LOCATION=LOC(OLD))
???? I've never seen whatever construct this is. Or anything close
enough for this to be a plausible minor syntax error of. If this is
some extension, it isn't a widespread one (and thus the odds of it
working with the unspecified compiler of the original poster seem
questionable).
Can I ask, in the context of your actual problem, why you want to do this? Maybe with more
background info, a solution/equivalent method (no pun intended) can be found. The facile
solution to declare your arrays as big as you'll ever need them to be (avoiding the
inability of equivalencing allocatable or adjustable arrays) might be thought of as
inelegant in some circles but if it works.....
cheers,
paulv
--
Paul van Delst A little learning is a dangerous thing;
CIMSS @ NOAA/NCEP Drink deep, or taste not the Pierian spring;
Ph: (301)763-8000 x7274 There shallow draughts intoxicate the brain,
Fax:(301)763-8545 And drinking largely sobers us again.
Alexander Pope.
The code uses the array to keep track of the number of elements (integer)
that follow (real values), and maintains multiple tables within the same
array. And I don't want to rewrite
the code to use a differnent structure. Probably weeks of work if I didn't
introduce any
bugs (like that EVER happens!).
So I'm still looking for a solution
Dave
"Paul van Delst" <paul.v...@noaa.gov> wrote in message
news:3B17D9D1...@noaa.gov...
"Richard Maine" <nos...@see.signature> wrote in message
news:ued78op...@altair.dfrc.nasa.gov...
> The code uses the array to keep track of the number of elements
> (integer) that follow (real values), and maintains multiple tables
> within the same array. And I don't want to rewrite the code to use a
> differnent structure. Probably weeks of work if I didn't introduce
> any bugs (like that EVER happens!).
>
> So I'm still looking for a solution
Well, I'll skip all the "here's some other way I might have done that"
stuff as not being particularly useful. (They all fall at least
broadly into the "rewrite the code to use a different structure"
class).
From your description, I can think of one fairly simple approach that
might work. Just use two separate arrays - one integer and one real.
For any particular element, only one of the two arrays is actually
used - the other has wasted space there. It does cost you a factor of
2 in space, but it's only a factor of 2 (unlike the orders of
magnitude of some of your examples of why static sizing wasn't
acceptable). As long as you alwasy access the integers via the
integer name and the reals via the real name, it seems like it ought
to work. What wouldn't work is if you extracted an element via the
"wrong" name and then used a separate equivalence to get the value.
I.E. just take out all the equivalence statements. Wherever you
allocate the array, allocate both of the separate ones.
If you ever do anything like write the whole thing to a file, you'd
need to do something about merging the two pieces. (Or conversely,
separating them after reads).
Dunno whether it would work for you or not. It's definitely a hack,
but it might be a viable one for some situations.
>>> ALLOCATE (NEW*SIZE,LOCATION=LOC(OLD))
> Yes it is a WATCOM extension. I do have that compiler but can't use
> it for this project. Plus the compiler is non-supported anymore.
That's a bit too strong. Although Sybase decided to discontinue
development, the OpenWatcom project has resumed development and
support, though at a level consistent with the amount of time they
can devote to the effort.
I'm trying to use the transfer function, It isn't elegant, but makes it
should
be foolproof to implement, or at least the least error prone method I have
found.
"Richard Maine" <nos...@see.signature> wrote in message
news:ue8zjco...@altair.dfrc.nasa.gov...
Well, this discussion has given a lot of answers, and it seems that it can't
be done with standard f90 (except using argument cheating as Richard
described). However, non-standard Cray pointers are far
more widespread extension than Watcom's ALLOCATE(...LOCATION=).
If your compiler supports them, and you can live without portability,
that could be the answer:
REAL, ALLOCATABLE:: fArray
INTEGER:: iArray(100000); POINTER(piArray, iArray)
ALLOCATE(fArray(nSomething))
piArray=LOC(fArray)
The above code effectively EQUIVALENCEs fArray and iArray (oh, yes,
it also invokes LOC extension). Note that 100000 in the example does
_not_ actually allocate any storage (it's kinda dummy number -- I think
I saw using * instead, but I'm not sure if it works). Look at your manual
on "Integer pointers" or "Cray pointers".
Jugoslav
A real hack I have done in the past is to pass the same array as two
separate arguments... the receiving subroutine declares one argument as real
and the other as integer. This of course implies that the compiler not
enforce type checking between modules. It also requires some code change
which may negate its usefulness to you.
John Keenan
While I admire the effort of the individuals in the OpenWatom project
(and wish I had something to contribute), unfortunately for many that
translates to "unsupported" by our employers/clients...whether that is
justified is, in these situations, simply not an issue for discussion.
I'm in the same boat with a port from an OS/2 app to NT where I was
forced to leave Watcom for the same reason...the client has a corporate
policy of only using commercially available tools, and that is enforced
rigorously.
>> David Johnson writes:
Honestly, I find the support to better now than it was when it was a
"commercially available tool". However, if the kind of support you
need is a code fix, and you need it now, and you are willing to pay
for immediate attention, then you might be better off with a product
that has a staff of paid people that you could threaten with breach
of contract. But if you only need the answer to a question, you're
far better off now.
I take it your client wouldn't touch Linux with a ten-foot pole.
Thanks to all for the help!
Dave
"Jugoslav Dujic" <jdu...@yahoo.com> wrote in message
news:9fa908$k0r$1...@zmaj.etf.bg.ac.yu...
(Homebrew data acquisition and analysis program for
collecting data about the initiation of electrical breakdown
in ultrapure water, 70 kloc: 66% Fortran, 31% 68k asm
and 2% Pascal -- it worked, I got my data. In 18 Megohm-cm
water initiation of electrical breakdown is mediated by processes
on the electrode surfaces, and less (by a factor of 1.4) by
peak electrical field in the bulk.)
To get the effect of EQUIVALENCE you would pass the
array in twice, which is a violation of recent Fortran standards
(as has been pointed out elsewhere) and will probably
require optimization to be disabled in order to have any
reasonable chance of generating correct code.
--
Kevin G. Rhoads, Ph.D. (The Cheshire Cat for official Internet mascot.)
kgrhoads@NO_SPAM.alum.mit.edu
You take it correctly... :-)
There are, however, many Sun workstations with the Sun-supplied
versions, some directly from Sun, others as "embedded" workstations in
other vendor-supplied DCSes (distributed control systems from, say,
Foxboro, et al.)....
As far as support for the compilers, as the developer/maintainer I never
had a problem (with Watcom on this set of applications) that was not
easily solvable w/o a code patch for both the OS/2 and the NT platform.
(It was somewhat of a pain going to NT as the API header files were not
provided as with OS/2, but that was a one-time straightforward effort to
integrate the MS tool set albeit it was a pain in the proverbial
appendage I'd not want to do again as MS has no existing support for
Fortran any more that I could find. Consequently, I only did the
minimum subset I needed and additional reliance on the Win32 API would
require more of that effort.) However, the problem is it doesn't matter
to the client what (or whether) the previous support was
good/bad/required, the <policy> is the driver. And, while it is fun to
rail at the Dilbert mentality, it is also futile.
I have found the CVF support from Steve L. and his "back room" buddies
to be both timely and excellent. I have, however, found one particular
shortcoming in CVF (relative to Watcom) in error handling at run time
that I have yet to find a good workaround for. That is in the exception
handling for FPU fixup/correction at run time for a real-time app.
Watcom implemented the C library setjmp/longjmp feature integrally with
F77. Compaq has chosen not to do this (and after discussion internally,
informed me they don't foresee doing so in the future). I've not yet
gotten to the point of seriously looking at alternatives, but it will
have to be addressed prior to deployment of the application on NT.
It's not just one...I've got a list (currently counted on two hands, but
then, I'm only a one-person (and trying to retire) person working in a
narrow market niche so my horizon is admittedly limited...I suspect,
however, if you have <any> bond funds in your portfolio, you're already
invested. :-)
This way you can put the real size in the main blank common. Only the main
routine must be recompiled when you change the size.
example :
program Main
integer Size
parameter (Size = 50000000)
integer A (Size)
real B (10)
common A
equivalence (A (1), B (1))
call SP (Size)
end
subroutine SP (Size)
integer Size
integer A (10)
real B (10)
common A
equivalence (A (1), B (1))
do I = 1, Size
A (1) = B(1)
end do
end
David Johnson a écrit :