[comp.lang.fortran] matrix multiplication

scavo@cie.uoregon.edu (Tom Scavo) (05/05/91)

As you all know, a classic programming exercise is the matrix 
multiplication problem

     A   =   B   C  .
    mxn     mxp pxn

A robust algorithm will also handle the special case

     X   =   Y   X                                           (1)
    mxn     mxm mxn

where the result is to replace one of the matrices being 
multiplied.  Such a calculation will break a naive algorithm, 
however.  One solution is to pass  B  and  C  by *value* (with 
loss of efficiency in both time and space) but of course Fortran's 
insistence that all parameters be passed by reference precludes 
such an approach.  On the other hand, pass-by-value can be 
simulated using a local array (for the lhs) declared within the 
matrix multiplication routine.  Unfortunately, the dimensions of 
this local array put an operational limit on the size of the input 
matrices.

I already have an inadequate routine that uses such a local array.  
How would I write a *general* matrix multiplication routine that 
handles tricky computations such as those in (1), and accomodates 
matrices of arbitrary size?  Also, does anyone know of a Fortran 
compiler that implements pass-by-value-result, a kind of delayed 
pass-by-reference where the actual parameters are updated at the 
point of return?  Or is this non-standard?

Tom Scavo
scavo@cie.uoregon.edu

pmontgom@euphemia.math.ucla.edu (Peter Montgomery) (05/05/91)

In article <1991May04.170203.22222@ariel.unm.edu> scavo@cie.uoregon.edu (Tom Scavo) writes:
>I already have an inadequate routine that uses such a local array.  
>How would I write a *general* matrix multiplication routine that 
>handles tricky computations such as those in (1), and accommodates 
>matrices of arbitrary size? 

	Convince your vendor to support certain Fortran 90 features.
Matrix multiplication is an F90 intrinsic function.  My nominee
for the more important F90 feature is automatic arrays:
local arrays whose dimensions can depend upon the values of
parameters passed to the subroutine (and upon common variables).  
[Also high on my list are the bit manipulation functions and IMPLICIT NONE.]
With automatic arrays you could allocate a product array of the desired size 
upon entry, build the product there, and copy it before exiting.
--
        Peter L. Montgomery 
        pmontgom@MATH.UCLA.EDU 
        Department of Mathematics, UCLA, Los Angeles, CA 90024-1555
If I spent as much time on my dissertation as I do reading news, I'd graduate.

dik@cwi.nl (Dik T. Winter) (05/05/91)

In article <1991May04.170203.22222@ariel.unm.edu> scavo@cie.uoregon.edu (Tom Scavo) writes:
 > A robust algorithm will also handle the special case
 >      X   =   Y   X                                           (1)
 >     mxn     mxm mxn
 > where the result is to replace one of the matrices being 
 > multiplied.
Not in Fortran.

 >                    On the other hand, pass-by-value can be 
 > simulated using a local array (for the lhs) declared within the 
 > matrix multiplication routine.  Unfortunately, the dimensions of 
 > this local array put an operational limit on the size of the input 
 > matrices.
Still your routine will not be conforming to the Fortran standard.
 > 
 > How would I write a *general* matrix multiplication routine that 
 > handles tricky computations such as those in (1), and accomodates 
 > matrices of arbitrary size?
If you are thinking about portrable Fortran you must forget it.
It is not permitted.  To give an example of the problem, suppose the
following (simple) routine:
	SUBROUTINE ADD(A, B, C)
	A = B + C
	RETURN
	END
The following calls are illegal:
	CALL ADD(P, P, Q)
	CALL ADD(P, Q, P)
The reason is that *if* one of the parameters changes value within the
routine that parameter may not be aliased to another on the call side.
Some compilers allow this, but some choke on a number of cases.

 >                              Also, does anyone know of a Fortran 
 > compiler that implements pass-by-value-result, a kind of delayed 
 > pass-by-reference where the actual parameters are updated at the 
 > point of return?  Or is this non-standard?
This is certainly non-standard in general.  For simple variables it
is implemented on a large number of compilers (IBM amongst them).
--
dik t. winter, cwi, amsterdam, nederland
dik@cwi.nl

mwette@csi.jpl.nasa.gov (Matt Wette) (05/06/91)

In article <1991May04.170203.22222@ariel.unm.edu>, scavo@cie.uoregon.edu (Tom Scavo) writes:
|> As you all know, a classic programming exercise is the matrix 
|> multiplication problem
|> 
|>      A   =   B   C  .
|>     mxn     mxp pxn
|> 
|> A robust algorithm will also handle the special case
|> 
|>      X   =   Y   X                                           (1)
|>     mxn     mxm mxn
|> 
|> where the result is to replace one of the matrices being 
|> multiplied.

Computing "X <- Y * X" is actually quite simple to do as a Fortran 
routine if you're willing to pass a "work vector".  My version is
included below.  In fact, this case is quite efficient.  A nastier one
(in Fortran) is "X <- X * Y".  A "general" routine could branch to 
code which could handle your particular case.  Note that you have to
take care of transposes also (i.e., "X <- Y' * X").  I think the
convenience you want from pass-by-value is not worth the large loss
in efficiecy you'll get from copying (possibly) large arrays.

Matt


      SUBROUTINE MULBRR(L, M, N, A, NA, B, NB, WKV)
C
      INTEGER L, M, N, NA, NB
      DOUBLE PRECISION A(NA,1), B(NB,1), WKV(1)
C
C     B = A * B   A IS (L X M),  B(RHS) IS (M X N),  B(LHS) IS (L X N).
C                 WKV IS A WORK VECTOR OF SIZE  L.
C
C     $Id: mulbrr.f,v 1.1 1991/01/24 00:50:12 mwette Exp $
C
      INTEGER I,J,K
C
      IF (L .LE. 0 .OR. M .LE. 0 .OR. N .LE. 0) RETURN
      DO 50 J = 1,N
         DO 10 I = 1,L
            WKV(I) = 0.0D0
   10    CONTINUE
         DO 30 K = 1,M
            DO 20 I = 1,L
               WKV(I) = WKV(I) + A(I,K)*B(K,J)
   20       CONTINUE
   30    CONTINUE
         DO 40 I = 1,L
            B(I,J) = WKV(I)
   40    CONTINUE
   50 CONTINUE
      RETURN
C
C --- LAST LINE OF MULBRR ---
      END


-- 
 _________________________________________________________________
 Matthew R. Wette           | Jet Propulsion Laboratory, 198-326
 mwette@csi.jpl.nasa.gov    | 4800 Oak Grove Dr, Pasadena,CA 91109
 -----------------------------------------------------------------

jlg@cochiti.lanl.gov (Jim Giles) (05/06/91)

In article <1991May04.170203.22222@ariel.unm.edu>, scavo@cie.uoregon.edu (Tom Scavo) writes:
|> [...]                         Also, does anyone know of a Fortran 
|> compiler that implements pass-by-value-result, a kind of delayed 
|> pass-by-reference where the actual parameters are updated at the 
|> point of return?  Or is this non-standard?

It is quite within the standard to pass procedure arguments by value/result.
It is also standard to pass by reference.  The reason for the Fortran 
prohibition of aliasing parameters through procedure calls is to make
the semantics of both forms of procedure call identical.  That's why
you can't do MATMLT(X,Y,X,M,N,M) - if the procedure assigns to X.  If
you were allowed to do so, the semantics of the two parameter passing
methods would be different.

Yes, you can implement Fortran with value/result parameters.  The bad
news is that it still doesn't do what you want since aliasing IN and
INOUT (or OUT) parameters is illegal.

J. Giles

scavo@cie.uoregon.edu (Tom Scavo) (05/07/91)

In an earlier article, I naively ask:

> >                              Also, does anyone know of a Fortran 
> > compiler that implements pass-by-value-result, a kind of delayed 
> > pass-by-reference where the actual parameters are updated at the 
> > point of return?  Or is this non-standard?

In article <3444@charon.cwi.nl> dik@cwi.nl (Dik T. Winter) writes:

>This is certainly non-standard in general.  For simple variables it
>is implemented on a large number of compilers (IBM amongst them).

In article <23261@lanl.gov> jlg@cochiti.lanl.gov (Jim Giles) writes:
 
>It is quite within the standard to pass procedure arguments by value/result.
>It is also standard to pass by reference.  The reason for the Fortran 
>prohibition of aliasing parameters through procedure calls is to make
>the semantics of both forms of procedure call identical.  That's why
>you can't do MATMLT(X,Y,X,M,N,M) - if the procedure assigns to X.  If
>you were allowed to do so, the semantics of the two parameter passing
>methods would be different.

So what is the concensus on this issue?  Is it within the
standard to implement pass-by-value-result?  If so, what
compilers have gone this route?

As an aside, how did it happen that two competing parameter
passing mechanisms got into the Fortran 77 standard?  (This
question assumes, of course, that this is indeed the case.) 
Was it an error of omission on the part of the standards
committee, or were the insecurities of pass-by-reference
simply not known at the time?  (I'm just interested in a
proper historical perspective.)

Looking to the future, how does Fortran 90 deal with the
parameter passing problem?

Tom Scavo
scavo@cie.uoregon.edu

dik@cwi.nl (Dik T. Winter) (05/08/91)

In article <1991May07.155218.13741@ariel.unm.edu> scavo@cie.uoregon.edu (Tom Scavo) writes:
 > So what is the concensus on this issue?  Is it within the
 > standard to implement pass-by-value-result?  If so, what
 > compilers have gone this route?
I fail to see any difference between what Jim Giles said and what I said.
Pass-by-value-result is allowed, as is pass-by-reference.  The standard
allows both.  As I said, IBM compilers use pass-by-value-result, but CDC
compilers use pass-by-reference.
 > 
 > As an aside, how did it happen that two competing parameter
 > passing mechanisms got into the Fortran 77 standard?  (This
 > question assumes, of course, that this is indeed the case.) 
This is indeed *not* the case.  The standard simply leaves the parameter
passing mechanisms unspecified.  It only specifies the result for
non-aliased parameters.  Any program assuming one way or the other depends
on improper aliasing, and that makes the program illegal.

If you want a detour to Ada:  in Ada it *is* specified that simple parameters
are passed-by-value-return.  Non-simple parameters are to be passed by
either value-return or reference.  The reason is that if the subroutine
you are calling resides on a different processor you really *want*
value-return in most cases.
--
dik t. winter, cwi, amsterdam, nederland
dik@cwi.nl

khb@chiba.Eng.Sun.COM (Keith Bierman fpgroup) (05/09/91)

In article <1991May07.155218.13741@ariel.unm.edu> scavo@cie.uoregon.edu (Tom Scavo) writes:


   As an aside, how did it happen that two competing parameter
   passing mechanisms got into the Fortran 77 standard?  (This

The standard was carefully crafted to allow compilers to do the
highest performing thing on their platform. If you code according to
the standard, you can't tell how parameter passing occurs.

On traditional "scalar" uniprocessors, passing addresses is often the
best way. On machines like the TMC and MASSPAR, copying is often
cheaper. 


   Looking to the future, how does Fortran 90 deal with the
   parameter passing problem?

The same way; the standard doesn't mandate how you do it; just what
the effects are. With interface blocks, the coder can communicate with
the compiler a bit better (parameters passed just as IN, or OUT may
merit special treatment, for example).
--
----------------------------------------------------------------
Keith H. Bierman    keith.bierman@Sun.COM| khb@chiba.Eng.Sun.COM
SMI 2550 Garcia 12-33			 | (415 336 2648)   
    Mountain View, CA 94043