From: Nathan on
Is it possible for arrays to share memory space such that assigning
one value to an element in array A will also assign that same value to
a different element in array B?...

I have some data that is passed into a subroutine from the main
function, as well as some data that is generated within this
subroutine.

Experimental data is as follows:
ncompg 2
gconc(1) 0.790000000000000
gconc(2) 0.210000000000000
gconc(3) 0.000000000000000E+000
gconc(4) 0.000000000000000E+000
gconc(5) 0.000000000000000E+000
gconc(6) 493.140000000000
gconc(7) 731.440000000000
gconc(8) 0.000000000000000E+000
gconc(9) 0.000000000000000E+000
gconc(10) 0.000000000000000E+000
tcfg(1) -232.510000000000
tcfg(2) -181.430000000000
tcfg(3) 0.000000000000000E+000
tcfg(4) 0.000000000000000E+000
tcfg(5) 0.000000000000000E+000
tcfg(6) -146.950000000000
tcfg(7) -118.572222222222
tcfg(8) 0.000000000000000E+000
tcfg(9) 0.000000000000000E+000
tcfg(10) 0.000000000000000E+000
pcg(1) 493.140000000000 !note: same as GCONC(6).. why?
pcg(2) 731.440000000000 !note: same as GCONC(7).. why?
pcg(3) 0.000000000000000E+000
pcg(4) 0.000000000000000E+000
pcg(5) 0.000000000000000E+000
pcg(6) -232.510000000000
pcg(7) -181.430000000000
pcg(8) 0.000000000000000E+000
pcg(9) 0.000000000000000E+000
pcg(10) 0.000000000000000E+000
aceng(1) 3.770000000000000E-002
aceng(2) 2.220000000000000E-002
aceng(3) 0.000000000000000E+000
aceng(4) 0.000000000000000E+000
aceng(5) 0.000000000000000E+000
aceng(6) 3.451213951350862E-085
aceng(7) 6.013470022929141E-154
aceng(8) 6.013470016999068E-154
aceng(9) 6.013470016999068E-154
aceng(10) 6.013470016999068E-154
TCFF(0) 947.929986572266
TCFF(1) 947.929986572266
TCFF(2) 947.929986572266
TCFF(3) 947.929986572266
PCF(0) 180.717024624348
PCF(1) 180.717024624348
PCF(2) 180.717024624348
PCF(3) 180.717024624348
ACENF(0) 0.910000000000000
ACENF(1) 0.910000000000000
ACENF(2) 0.910000000000000
ACENF(3) 0.910000000000000
FCONC(0) 0.250000000000000
FCONC(1) 0.250000000000000
FCONC(2) 0.250000000000000
FCONC(3) 0.250000000000000
nfsteps 4 !was 3 in main function, changed to 4 in subroutine

This data is defined as such:
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
DIMENSION ACENG(10),TCFG(10),PCG(10),GCONC(10)
DIMENSION
TCFF(0:nfsteps),PCF(0:nfsteps),ACENF(0:nfsteps),FCONC(0:nfsteps)

Where nfsteps (was 3, changed to 4 within subroutine) and ncompg are
passed into this subroutine from the main function.


I understand that it is good practice to keep arrays based on the same
index (EITHER 0 or 1), but this code was passed onto me from someone
who thought it would be nice to mix it up (I guess).

Within the following loop, elements of PCG change as elements of TCFG
change, which is not what is written:

DO I=0,nfsteps-1
TCFG(I+1+NCOMPG) = TCFF(I) !RHS arrays are 0 based
PCG(I+1+NCOMPG) = PCF(I)
ACENG(I+1+NCOMPG) = ACENF(I)
GCONC(I+1+NCOMPG) = FCONC(I)
ENDDO

After this loop, the data is as follows:
ncompg 2
gconc(1) 296.487940000000 !no idea where this one came from
gconc(2) 0.210000000000000
gconc(3) 0.250000000000000
gconc(4) 0.250000000000000
gconc(5) 0.250000000000000
gconc(6) 0.250000000000000
gconc(7) 731.440000000000
gconc(8) 180.717024624348
gconc(9) 180.717024624348
gconc(10) 180.717024624348
tcfg(1) 180.717024624348 !from pcg?
tcfg(2) -181.430000000000
tcfg(3) 947.929986572266
tcfg(4) 947.929986572266
tcfg(5) 947.929986572266
tcfg(6) 947.929986572266
tcfg(7) -118.572222222222
tcfg(8) 0.000000000000000E+000
tcfg(9) 0.000000000000000E+000
tcfg(10) 0.000000000000000E+000
pcg(1) 0.250000000000000 !from gconc?
pcg(2) 731.440000000000
pcg(3) 180.717024624348
pcg(4) 180.717024624348
pcg(5) 180.717024624348
pcg(6) 180.717024624348
pcg(7) -181.430000000000
pcg(8) 947.929986572266 !from tcfg?
pcg(9) 947.929986572266 !from tcfg?
pcg(10) 947.929986572266 !from tcfg?
aceng(1) 3.770000000000000E-002
aceng(2) 2.220000000000000E-002
aceng(3) 0.910000000000000
aceng(4) 0.910000000000000
aceng(5) 0.910000000000000
aceng(6) 0.910000000000000
aceng(7) 6.013470022929141E-154
aceng(8) 6.013470016999068E-154
aceng(9) 6.013470016999068E-154
aceng(10) 6.013470016999068E-154


It appears to me that the array ACENG is the only one that correctly
added the values of ACENF to it without changing other elements in the
array.

It is beyond me as to why this is happening, and I am hoping that
someone else has seen this before and can clue me in.

What is very curious to me is why the data from element 6 and on are
sometimes changed regardless of whether I tell them to be or not...

If I am too vague or you need more information than this, please tell
me and I'll do what I can to provide more information.


I tried running the loop in a separate "testing" function, and this
problem did not occur. (All the data appeared as it should be after
the end of the loop...)

So, back to my original question, I guess:
Can arrays in Fortran share memory locations such that assigning one
value to one element of one array will also be assigned to a different
element of a different array, regardless of whether you told it to do
so?

-Nathan
From: Gib Bogle on
Nathan wrote:
> Is it possible for arrays to share memory space such that assigning
> one value to an element in array A will also assign that same value to
> a different element in array B?...
>
> I have some data that is passed into a subroutine from the main
> function, as well as some data that is generated within this
> subroutine.

<snip>

> This data is defined as such:
> IMPLICIT DOUBLE PRECISION (A-H,O-Z)
> DIMENSION ACENG(10),TCFG(10),PCG(10),GCONC(10)
> DIMENSION
> TCFF(0:nfsteps),PCF(0:nfsteps),ACENF(0:nfsteps),FCONC(0:nfsteps)
>
Take care when passing arrays that have 0-based subscripting. You need to tell
the subroutine about the 0-base.
From: Nathan on
On Mar 3, 3:36 pm, Gib Bogle <g.bo...(a)auckland.no.spam.ac.nz> wrote:
> Nathan wrote:
> > Is it possible for arrays to share memory space such that assigning
> > one value to an element in array A will also assign that same value to
> > a different element in array B?...
>
> > I have some data that is passed into a subroutine from the main
> > function, as well as some data that is generated within this
> > subroutine.
>
> <snip>
>
> > This data is defined as such:
> > IMPLICIT DOUBLE PRECISION (A-H,O-Z)
> > DIMENSION ACENG(10),TCFG(10),PCG(10),GCONC(10)
> > DIMENSION
> > TCFF(0:nfsteps),PCF(0:nfsteps),ACENF(0:nfsteps),FCONC(0:nfsteps)
>
> Take care when passing arrays that have 0-based subscripting.  You need to tell
> the subroutine about the 0-base.

That is the declaration of those variables from within the subroutine,
therefore it has been told about the 0 base, right?

ACENG(10) tells the program that ACENG ranges from 1-10
ACENF(0:nfsteps) tells the program that ACENF ranges from 0-nfsteps


Ah, I left out a piece of information that is probably important.
From the main function:
DIMENSION ACENG(5),TCGF(5),PCG(5),GCONC(5)
(the 0-based ones are the same as in the subroutine)

That appears to be the problem.

Note that if I only pass in 3 values for each of TCFF,PCF,ACENF,FCONC
and 2 values for each of the others, the program works (probably
because the total number of components is 5), while when passing in 4
values the program crashes (probably due to there being 6 components
when the arrays in the main function only have space for 5)...


Thanks for taking a look anyway... It's always these careless mistakes
that cause the biggest headaches.

-Nathan
From: dpb on
Nathan wrote:
> Is it possible for arrays to share memory space such that assigning
> one value to an element in array A will also assign that same value to
> a different element in array B?...

Certainly, that is the definition of EQUIVALENCE (altho dummy arguments
cannot be).

....

> nfsteps 4 !was 3 in main function, changed to 4 in subroutine

Need to see declarations in _BOTH_ main and subroutine--if they're
different you have issues...

> This data is defined as such:
> IMPLICIT DOUBLE PRECISION (A-H,O-Z)
> DIMENSION ACENG(10),TCFG(10),PCG(10),GCONC(10)
> DIMENSION
> TCFF(0:nfsteps),PCF(0:nfsteps),ACENF(0:nfsteps),FCONC(0:nfsteps)
>
> Where nfsteps (was 3, changed to 4 within subroutine) and ncompg are
> passed into this subroutine from the main function.

Are these declarations in calling program or subroutine? Are they the
same both places? Oh, so many questions, so little actual information...

>
> I understand that it is good practice to keep arrays based on the same
> index (EITHER 0 or 1), but this code was passed onto me from someone
> who thought it would be nice to mix it up (I guess).

Well, it requires consistency in usage in a given array or confusion
likely reigns; there's no fundamental reason not to use appropriate
bounds for any particular array.

> Within the following loop, elements of PCG change as elements of TCFG
> change, which is not what is written:
>
> DO I=0,nfsteps-1
> TCFG(I+1+NCOMPG) = TCFF(I) !RHS arrays are 0 based
> PCG(I+1+NCOMPG) = PCF(I)
> ACENG(I+1+NCOMPG) = ACENF(I)
> GCONC(I+1+NCOMPG) = FCONC(I)
> ENDDO
....

> It is beyond me as to why this is happening, and I am hoping that
> someone else has seen this before and can clue me in.

Well, the thing about nfsteps be 3 or 4 certainly could be an issue in
computing the values of the indices. Also, again, the needed
declarations in both routines are necessary to really tell what is going on.

In general, w/o trying to delve into it in much depth w/o the missing
information, undoubtedly the various arrays are stored in proximity to
each other and the indices of one are tromping on another's space.
This, as noted above, is undoubtedly owing to a mismatch in declarations
and the changing sizes assumed on loop bounds.

Unless the bounds are set properly in the subroutine, even setting the
bounds-checking compilation flag won't help necessarily, but if you're
not using it, find what it is for your compiler and do so. It could be
informative.

> What is very curious to me is why the data from element 6 and on are
> sometimes changed regardless of whether I tell them to be or not...
>
> If I am too vague or you need more information than this, please tell
> me and I'll do what I can to provide more information.
>
>
> I tried running the loop in a separate "testing" function, and this
> problem did not occur. (All the data appeared as it should be after
> the end of the loop...)
>
> So, back to my original question, I guess:
> Can arrays in Fortran share memory locations such that assigning one
> value to one element of one array will also be assigned to a different
> element of a different array, regardless of whether you told it to do
> so?

The answer is, "if it did, you _DID_ tell it to". :)

You did that by making a reference outside the bounds of one and that
just happened to be where the other resides. Again, bounds checking
will tell you where a computed index is outside the bounds of the
defined array; problem is you may not be setting them right so that the
subroutine thinks they're bigger than the space allocated in the main
for them.

Supply enough context to actually be able to follow from the main to the
subroutine and it'll be clear.

In actuality, you probably could cut this down to a working example
program of only 15-20 lines that would suffice to be complete.

--


> -Nathan
From: Richard Maine on
Nathan <ngreco32(a)gmail.com> wrote:

> Is it possible for arrays to share memory space such that assigning
> one value to an element in array A will also assign that same value to
> a different element in array B?...

Yes. There are ways to do that intentionally. That's pretty much what
the equivalence statement does, in particular. These days it is usually
considered questionable coding style (for a start, because it does cause
confusion). But yes, it can be done.

There are also many ways that can happen by accident. If we actually saw
the relevant code (is this beginning to sound familliar?), we might
better be able to say more.

Probably the most common are from exceeding array bounds and having
mismatched actual and dummy arguments. But there are others.

The code you did show used implicit double precision. As someone noted
in the other thread, it is easy to go wrong with that. In particular, it
is easy to get argument mismatches by getting the type wrong because of
confusions caused by implicit double precision.

Also, if you are mixing arrays with lower bounds of 0 and 1, it is easy
to get confused and exceed the bounds (in either direction; for current
purposes, referencing an element 0 when the lower bound is 1 also counts
as "exceeding" a bound, even though the lower one). A particular point
that is easy to get confused on is in argument passing with different
lower bounds. Lower bounds are *NOT* passed automatically. If you have
an actual argument with a lower bound of 0 and pass it to a dummy
argument with a lower bound of 1 (or an uspecified lower bound, which
implies 1), it will not do what you might think. The elements will all
be numbered off by 1 in the subroutine. That is perfectly legal, but can
be confusing and can easily result in you referencing beyond the valid
bounds.

But that's a lot of guessing based on no data. Showing a bunch of values
doesn't help without the code - all of the revant code. And that
definitely includes the calling routine; if anything, the problem is
more likely to be in the calling routine, or at least partly so (such as
in the case of argument mismatches).

> DIMENSION
> TCFF(0:nfsteps),PCF(0:nfsteps),ACENF(0:nfsteps),FCONC(0:nfsteps)
>
> Where nfsteps (was 3, changed to 4 within subroutine) and ncompg are
> passed into this subroutine from the main function.

Changing the value nfsteps within the subroutine is very likely to cause
confusions. I strongly recommend against it. While it can be legal
(depending on other things), the odds of confusing you are very high. If
I am reading correctly, the above arrays are all automatic arrays
(slightly odd to have an f90 feature like automatic arrays mixed with
70's style sequence numbers that Glenn commented on, though I can see
how it could happen). You would need to know that the automatic arrays
are sized based on the value of nfsteps when the subroutine was entered
- not on any subsequent change). Also realize that any change to nfsteps
in the subroutine will propogate back to the calling routine.

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