```From: corbett@lupa.Sun.COM (Robert Corbett)
Newsgroups: comp.lang.fortran
Subject: Re: Questionable optimization
Date: 6 Jun 2000 05:26:40 GMT

In article <8h6itr\$qf8\$3@news.IAEhv.nl>,
Jos Bergervoet  <bergervo@iaehv.iae.nl> wrote:
>
>An interesting puzzle is: How do you write a routine SUB(A,B), that
>transposes the matrix A, returns the result in B, is standard
>conforming fortran, and is also guaranteed to work for A and B at
>
>If you understand the answer (it CANNOT be done in Fortran, whatever
>tricks you try to use) you have really understood the answer to your
>original question.

It can be done.  Section 12.4.1.6 of ISO/IEC 1539-1:1997 makes it
possible.  Among many other things it says

(2)  If the value of any part of the entity is affected
through the dummy argument, then at any time during
the execution of the procedure, either before or
after the definition, it may be referenced only
through that dummy argument unless

(a)  the dummy argument has the POINTER attribute,

(b)  the part is all or part of a pointer subobject,
or

(c)  the dummy argument has the TARGET attribute,
the dummy argument does not have INTENT(IN),
the dummy argument is a scalar object or an
assumed-shape array, and the actual argument
is a target other than an array section with
a vector subscript.

Thus, the program given below is standard conforming.

Sincerely,
Bob Corbett

-----------------------------------------------------------

SUBROUTINE SUB(A, B)
REAL A(:,:)
INTENT(IN) A
REAL B(:,:)
INTENT(OUT) B
TARGET B

B = TRANSPOSE(A)
END

PROGRAM MAIN
INTERFACE
SUBROUTINE SUB(A, B)
REAL A(:,:)
INTENT(IN) A
REAL B(:,:)
INTENT(OUT) B
TARGET B
END SUBROUTINE
END INTERFACE
REAL A(3, 3)

DO J = 1, 3
DO I = 1, 3
A(I, J) = 3*J + I - 3
END DO
END DO

DO J = 1, 3
PRINT *, (A(I, J), I = 1, 3)
END DO
CALL SUB(A, A)
PRINT *
DO J = 1, 3
PRINT *, (A(I, J), I = 1, 3)
END DO
END

```

```From: Richard Maine <maine@altair.dfrc.nasa.gov>
Newsgroups: comp.lang.fortran
Subject: Re: Questionable optimization
Date: 06 Jun 2000 07:43:09 -0700

"James Van Buskirk" <torsop@ix.netcom.com> writes:

> >It can be done.  Section 12.4.1.6 of ISO/IEC 1539-1:1997...

> Did no one on the committee get motion sickness, vertigo, or
> at least amblyopia from reviewing this difficult section?

Well I certainly did.  I'm not going to try to give an interpretation of it
because I never can get it right.  I thought the conditions far too
complicated and esoteric, but apparently there was a desire to specify
pretty specific conditions in order to facilitate some optimizations.
In other places in the standard, restrictions are often phrased more
broadly, giving a simpler restriction, but one that isn't as finely
tuned.

I recall mentioning a position to the effect that I'd never be able to
explain the conditions in this particular section to users (even if I
figured them out myself).  Thus so as far as I was concerned, the
conditions were largely irrelevant.  My advice is "don't do anything
vaguely like that and then you won't have to worry about the precise
interpretation of the conditions."  Presumably those people who feel
the necessity to tread close to the complicated fine line here will
understand it well enough that they won't need me to explain it to
them.  (Or they will be disappointed).

I slightly overstate in that I think I can puzzle out the section if I
keep it in front of me and read very carefully.  What I have no hope of
doing is remembering it and explaining it in a fashion that I could
reasonably expect a user to remember.

--
Richard Maine
maine@altair.dfrc.nasa.gov

```

```From: "James Van Buskirk" <torsop@ix.netcom.com>
Newsgroups: comp.lang.fortran
Subject: Re: Questionable optimization
Date: Tue, 6 Jun 2000 00:48:50 -0600

Robert Corbett wrote in message <8hi22g\$ask\$1@engnews1.eng.sun.com>...

>It can be done.  Section 12.4.1.6 of ISO/IEC 1539-1:1997 makes it
>possible.  Among many other things it says

But it also says
(1)  ... Action that affects the value of the entity or any part
of the it shall be taken through the dummy argument unless

(c) the dummy argument has the TARGET attribute [and] the
dummy argument does not have INTENT(IN) ...

So the given example flunks the requirements of part (1) because
dummy argument A has INTENT(IN) and is does not have the TARGET
attribute.  Also part (c) in both (1) and (2) here require the actual
argument A to be a target.

Did no one on the committee get motion sickness, vertigo, or
at least amblyopia from reviewing this difficult section?

```

```From: corbett@lupa.Sun.COM (Robert Corbett)
Newsgroups: comp.lang.fortran
Subject: Re: Questionable optimization
Date: 7 Jun 2000 02:20:02 GMT

In article <8hi6s3\$mu7\$1@slb0.atl.mindspring.net>,
James Van Buskirk <torsop@ix.netcom.com> wrote:
>
>Robert Corbett wrote in message <8hi22g\$ask\$1@engnews1.eng.sun.com>...
>
>>It can be done.  Section 12.4.1.6 of ISO/IEC 1539-1:1997 makes it
>>possible.  Among many other things it says
>
>
>But it also says
>     (1)  ... Action that affects the value of the entity or any part
>          of the it shall be taken through the dummy argument unless
>
>          (c) the dummy argument has the TARGET attribute [and] the
>              dummy argument does not have INTENT(IN) ...
>
>So the given example flunks the requirements of part (1) because
>dummy argument A has INTENT(IN) and is does not have the TARGET
>attribute.  Also part (c) in both (1) and (2) here require the actual
>argument A to be a target.
>
>Did no one on the committee get motion sickness, vertigo, or
>at least amblyopia from reviewing this difficult section?

You're right.  I have fixed my code.  Please let me know if you see
remaining problems.

Sincerely,
Bob Corbett

------------------------------------------------------------------

SUBROUTINE SUB(A, B)
REAL A(:,:)
REAL B(:,:)
INTENT(OUT) B
TARGET A, B

B = TRANSPOSE(A)
END

PROGRAM MAIN
INTERFACE
SUBROUTINE SUB(A, B)
REAL A(:,:)
REAL B(:,:)
INTENT(OUT) B
TARGET A, B
END SUBROUTINE
END INTERFACE

REAL A(3, 3)
TARGET A

DO J = 1, 3
DO I = 1, 3
A(I, J) = 3*J + I - 3
END DO
END DO

DO J = 1, 3
PRINT *, (A(I, J), I = 1, 3)
END DO
CALL SUB(A, A)
PRINT *
DO J = 1, 3
PRINT *, (A(I, J), I = 1, 3)
END DO
END

```

```From: Jos Bergervoet <bergervo@iaehv.iae.nl>
Newsgroups: comp.lang.fortran
Subject: Re: Questionable optimization
Date: 10 Jun 2000 09:50:37 GMT

Robert Corbett <corbett@lupa.Sun.COM> wrote:

>            ...  I have fixed my code.  Please let me know if you see
> remaining problems.

You have given A the Target attribute in the calling code. That may
indeed allow you (together with your new SUB) to call SUB(A,A),
although I didn't look it up in the standard.

My claim, however, that you cannot do it solely by wrting SUB
in the appropriate way, still stands.

Besides, if it requires special precautions in the calling code,
it isn't guaranteed to work (users may forget those precautions).
And if you want to make requirements on the users, then you could
also require that they don't call SUB with twice the same argument.

So in practice, I would prefer to define a function if I want
this special behavior (well, special for Fortran, that is). Using
A = My_Fun(A) is allowed in any case, without tricks.

But back to your example: you could also consider to make and A and
B both pointer dummies in SUB, and ask the user to make A a pointer
array in the calling program. That would allow SUB(A,A). The
advantage is that if the user forgets to honor your request, the
compiler will complain. In your code, if Target is forgotten in the
calling program, the compiler won't say anything.

-- Jos

> 					Sincerely,
> 					Bob Corbett

> ------------------------------------------------------------------

>       SUBROUTINE SUB(A, B)
>         REAL A(:,:)
>         REAL B(:,:)
>         INTENT(OUT) B
>         TARGET A, B

>         B = TRANSPOSE(A)
>       END

>       PROGRAM MAIN
>         INTERFACE
>           SUBROUTINE SUB(A, B)
>             REAL A(:,:)
>             REAL B(:,:)
>             INTENT(OUT) B
>             TARGET A, B
>           END SUBROUTINE
>         END INTERFACE

>         REAL A(3, 3)
>         TARGET A

>         DO J = 1, 3
>           DO I = 1, 3
>             A(I, J) = 3*J + I - 3
>           END DO
>         END DO

>         DO J = 1, 3
>           PRINT *, (A(I, J), I = 1, 3)
>         END DO
>         CALL SUB(A, A)
>         PRINT *
>         DO J = 1, 3
>           PRINT *, (A(I, J), I = 1, 3)
>         END DO
>       END
```