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,
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? ========================================================= If you don't have too many elements of one of the types, you can use the transfer intrinsic:
real, allocatable, dimension(:) :: a integer :: i : i = transfer(a(j))
> 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,
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.
This function seems to translate it from a real to an integer. I actually want to store BOTH integer and REAL values in contiguous memory locations. I want to be able to read an integer variable directly from a "real" array location.
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" <113547.3...@CompuServe.COM> wrote in message
"David Johnson" <d...@crtech.com> writes: > 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
???? 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).
-- 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
> This function seems to translate it from a real to an integer. I actually > want to store BOTH integer and REAL values in contiguous memory locations. I > want to be able to read > an integer variable directly from a "real" array location.
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.
I want to do this because this is a production code that is used by hundreds or thousnads of users, and there can be significant runtime problems of sizing the array for the worst case user. They may need it to be 10's or hundreds of megabytes and other users may only need 20 or 30 bytes. So I don't want to give them an executable that takes 100's of MB of memory to load.
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!).
> > This function seems to translate it from a real to an integer. I actually > > want to store BOTH integer and REAL values in contiguous memory locations. I > > want to be able to read > > an integer variable directly from a "real" array location.
> 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.
> ???? 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).
> -- > 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
"David Johnson" <d...@crtech.com> writes: > 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.
-- 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
David Johnson writes: >>> 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 do file the whole thing out. It is done using generic filers that I can't add a hack too. And it wouldn't be simple to make two arrays since there are many places inside of loops that use both the integer and real values. Meaning I have to do the copy lots of times, which would be slow, not to mention prone to errors when figuring out where to put the copies. Miss one and spend days debugging.
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
> > 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.
> -- > 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
"David Johnson" <d...@crtech.com> wrote in message
news:fHNR6.26$JR3.209738@news.uswest.net... | Hi, | | 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 | | d...@crtech.com
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:
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".
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.
> > 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.
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.
Duane Bozarth writes: >> David Johnson writes: >>>>> 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. > 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.
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.
This is the best solution I have seen so far. It breaks very little code to implement and the only fault seems to be the use of the LOC function, which fortunately seems to be available on all the compilers I use.
Thanks to all for the help!
Dave
"Jugoslav Dujic" <jdu...@yahoo.com> wrote in message
> "David Johnson" <d...@crtech.com> wrote in message > news:fHNR6.26$JR3.209738@news.uswest.net... > | Hi, > | > | 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 > | > | d...@crtech.com
> 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:
> 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".
One way to do this is to allocate the array in another language, meaning most likely C these days, but I did it with Pascal for my Ph.D. thesis work, and pass the array into the Fortran code which is written to treat it as an adjustable sized array.
(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
>.the client has a corporate >policy of only using commercially available tools, and that is enforced >rigorously.
Please, then, be careful not to let slip who it is, as we wouldn't want to be guilty of shorting it's stock based on insider information. -- Kevin G. Rhoads, Ph.D. (The Cheshire Cat for official Internet mascot.) kgrhoads@NO_SPAM.alum.mit.edu
> >>> 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.
> > 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.
> 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.
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.
> >.the client has a corporate > >policy of only using commercially available tools, and that is enforced > >rigorously. > Please, then, be careful not to let slip who it is, as we wouldn't > want to be guilty of shorting it's stock based on insider information. > -- > Kevin G. Rhoads, Ph.D. (The Cheshire Cat for official Internet mascot.) > kgrhoads@NO_SPAM.alum.mit.edu
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. :-)
One trick we used in the past is to declare the equivalenced arrays in the blank common. The blank common size is (was) taken by the linker from the max blank common size of all the routines in Fortran 66 and 77. One major issue is that you must put the two equivalenced arrays at the last position after all variables declared to be in the blank common.
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))
> I want to do this because this is a production code that is used by hundreds > or thousnads of users, and there can be significant runtime problems of > sizing the array for the worst case user. They may need it to be 10's or > hundreds of megabytes and other users may only need 20 or 30 bytes. So I > don't want to give them an executable that takes 100's of MB of memory to > load.
> 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!).
> > > This function seems to translate it from a real to an integer. I > actually > > > want to store BOTH integer and REAL values in contiguous memory > locations. I > > > want to be able to read > > > an integer variable directly from a "real" array location.
> > 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.