gm2
[Top][All Lists]

## Re: Dynamic mutidimensional arrays

 From: Michael Riedl Subject: Re: Dynamic mutidimensional arrays Date: Mon, 3 Apr 2023 23:33:23 +0200 User-agent: Mozilla/5.0 (X11; Linux i686; rv:102.0) Gecko/20100101 Thunderbird/102.9.0

Gaius,

in a lot of cases within linear algebra routines one has a need to have intermediate multidimensional arrays (mostly 2-dimensional, but I also had more dimensions) which would only be needed within the scope of the procedure.

A simple sample might be that we need to multiply two matrices and, in the end, one is only interrested in some special aspects of this result (e.g. the lowest eigenvalues).

How would you handle such a case ?

As said, in Oberon it would work as suggested, but also in modern Fortran that is not implement too different (sample code below), gfortran can compile the code without issues.

But I just wanted to see if that would be of principal interrest - if it would reqite too much work, I can live with static allocation for the moment.

Mainly it would be a chance to make code more readable and to avoide wasting too much memory in the case you define the maximun size of a problem the code can handle with static declarations.

Michael

PROGRAM DynArray
USE ISO_FORTRAN_ENV, only : dp => REAL64, stdin => input_unit
!     Next line requires a fortran module "LinAlg.f90" which implement MultMatVec ...
USE LinAlg, only : MultMatVec
IMPLICIT NONE
INTEGER :: M,N
REAL(dp),allocatable :: A(:,:)
REAL(dp),allocatable :: B(:),C(:)
!     ... some more stuff ...

ALLOCATE(A(M,N))
ALLOCATE(B(N))
ALLOCATE(C(M))

!     some code to initialize A,B ...

CALL MultMatVec(M,N,A,B,C)

!     Some code to output the result C ...

DEALLOCATE(A)
DEALLOCATE(B)
DEALLOCATE(C)
END PROGRAM DynArray
~

Am 01.04.23 um 17:53 schrieb Gaius Mulley:
```Michael Riedl <udo-michael.riedl@t-online.de> writes:

```
```Gaius, all,

I have a questions / suggest about a possible extension of GM2.

Would it be possible to have dynamic multidimensional arrays implemented ?

We have multidimensional open array as procedure parameter, but if we
come to the main module we already need to know the (maximal)
dimension of e.g. a matrix - that does not make a lot of sense in my
view. Especially if you have more complex programs where you do not
know upfront the dimensions of the problem you would like to handle.

A small sample code illustrating the approach below - the code should
work with AWD Modula, XDS M2 and the P1 compiler - it's the way Oberon
addresses the issue (without the "DISPOSE").

Thanks for some feedback

Michael

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

MODULE DynArray;

TYPE  tVECTOR    = ARRAY OF REAL;      (* 1-dim open array *)
tMATRIX    = ARRAY OF tVECTOR;   (* 2-dim open array *)

tPtrVECTOR = POINTER TO tVECTOR; (* pointer to open 1-dim array *)
tPtrMATRIX = POINTER TO tMATRIX; (* pointer to open 2-dim array *)

PROCEDURE MultMatVek(    M,N : CARDINAL;
VAR A   : ARRAY OF ARRAY OF REAL;   (* in *)
VAR B   : ARRAY OF REAL;            (* in *)
VAR C   : ARRAY OF REAL);           (* out *)

(* multiply matrix A[M,N] times vector B[N], result is
vector C[M] *)

VAR i,j : CARDINAL;
s   : REAL;
BEGIN
FOR i:=0 TO M-1 DO
s := 0.0;
FOR j:=0 TO N-1 DO s:=s + A[i,j]*B[j]; END;
C[i] := s;
END; (* FOR i *)
END MultMatVek;

VAR   A       : tPtrMATRIX;
B,C     : tPtrVECTOR;
M,N,i,j : CARDINAL;

BEGIN
M := 4;
N := 3; (* suppose M and N are read in from some (external)
source ... *)

NEW(A,M,N);
NEW(B,N);
NEW(C,M);

FOR i:=0 TO M-1 DO (* some code to initialize A,B ... *)
FOR j:=0 TO N-1 DO A^[i,j] := VAL(REAL,i+j); END;
END;
FOR i:=0 TO N-1 DO B^[i] := VAL(REAL,i); END;

MultMatVek(M,N,A^,B^,C^);

(* Some code to output the result C ... *)

DISPOSE(A);
DISPOSE(B);
DISPOSE(C);
END DynArray.
```
```Hello Michael,

interesting - yes I see it would be useful.  I'd like to implement the
ISO generics, ISO OO and M2R10.  But I do see implementing open array
variables could be an easy win (and fit with the current implementation
of open array parameters).

MODULE DynArray ;

PROCEDURE MultMatVek (M, N: CARDINAL;
VAR A: ARRAY OF ARRAY OF REAL ;  (* in *)
VAR B: ARRAY OF REAL;            (* in *)
VAR C: ARRAY OF REAL) ;          (* out *)
(* multiply matrix A[M,N] times vector B[N], result is vector C[M] *)
VAR i, j: CARDINAL;
s   : REAL;
BEGIN
FOR i:=0 TO M-1 DO
s := 0.0;
FOR j:=0 TO N-1 DO s:=s + A[i,j]*B[j]; END;
C[i] := s;
END; (* FOR i *)
END MultMatVek;

PROCEDURE Init (M, N: CARDINAL) ;
VAR
(* A, B and C are created at runtime via alloca and are
internally implemented in the same way as procedure
parameters.  *)
A   : ARRAY <0..M-1> OF ARRAY <0..N-1> OF REAL ;
B, C: ARRAY <0..N-1> OF REAL ;
BEGIN
FOR i:=0 TO M-1 DO (* some code to initialize A,B ... *)
FOR j:=0 TO N-1 DO
A[i,j] := VAL (REAL,i+j)
END;
END;
FOR i:=0 TO N-1 DO B[i] := VAL(REAL,i); END;
MultMatVek (M, N, A, B, C);
(* Some code to output the result C ... *)
END
END Init ;

VAR
M, N: CARDINAL ;
BEGIN
Init (M, N)
END DynArray.

as a suggestion?  Although it requires further thought to re-examine the
ebnf and change it to restrict the use of open array variables to
procedures (although I guess one could provide some form of alloca
(similar to your NEW example)) for the global variables

regards,
Gaius
```