gm2
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Dynamic mutidimensional arrays


From: Michael Riedl
Subject: Re: Dynamic mutidimensional arrays
Date: Wed, 5 Apr 2023 09:40:28 +0200
User-agent: Mozilla/5.0 (X11; Linux i686; rv:102.0) Gecko/20100101 Thunderbird/102.9.0

Hallo Andreas,


thanks for the feedback, parts of my answer below in your text.

I am fully aware about (most of) the current features of the language (at least I hope so :-)

For me there is a inconsistency in the ISO approach of mutidimensional array ...    

- you can use 1-dimensional open array parameters and you can allocate the space for them in the calling program or procedure

- we have multiply dimensional open array parameters for procedures

- but we can only use fixed sized multiple-dimensional arrays to hand over

- even in case of 1-dimensional arrays we cannot use "HIGH" to check if the dimension of the actual parameter handed over is sufficient (at least if I do not want to make everything based on records having a data field and a size field.

Below a short sample (which, for the reasons give about, is sub-optimal).

With "my" approach one could hand over proper "high" parameters to the procedure called for 1 or multi-dimensional fields - something offering the possibility to procedure code better able to catch failures ...

It might have a reason why Niklaus Wirth introduced that in Oberon and other languages also went that way ...


Gruß / Regads

Michael


MODULE DynArray1D;

FROM Storage IMPORT ALLOCATE,DEALLOCATE;
             IMPORT STextIO;
             IMPORT SWholeIO;

  (* Here I assume that INTEGER and SYSTEM.ADDRESS have the same size, *)
  (* but this is not essential for this sample                         *)

CONST MaxV    = MAX(INTEGER) DIV SIZE(REAL);

TYPE  PVECTOR = POINTER TO ARRAY [0..MaxV-1] OF REAL;

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

          (* add vector A abd B and return the result in vector C *)

          VAR i : CARDINAL;

BEGIN
      IF (HIGH(C) < N-1) THEN
        (* Some error handling code ...                    *)
        (* but : actually HIGH(C) will be MaxV-1 and NOT N *)
        STextIO.WriteLn;
        STextIO.WriteString(" HIGH(C) = "); SWholeIO.WriteCard(HIGH(C),1);
        STextIO.WriteLn;
        STextIO.WriteString(" N       = "); SWholeIO.WriteCard(N,1);
        STextIO.WriteLn;
        STextIO.WriteString(" Error *** HIGH(C) < N-1 (AddVector) ***");
        STextIO.WriteLn;
        HALT;
      END;
      FOR i:=0 TO N-1 DO C[i]:= A[i] + B[i]; END;
END AddVector;

VAR   A,B,C : PVECTOR;
      N,i   : CARDINAL;
BEGIN
      N := 7; (* suppose N is read in from some source ... *)

      ALLOCATE(A,N*SIZE(REAL));
      ALLOCATE(B,N*SIZE(REAL));
      ALLOCATE(C,N*SIZE(REAL));

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

      AddVector(N,A^,B^,C^);

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

      DEALLOCATE(A,N*SIZE(REAL));
      DEALLOCATE(B,N*SIZE(REAL));
      DEALLOCATE(C,N*SIZE(REAL));

END DynArray1D.


Am 04.04.23 um 18:18 schrieb Fischlin Andreas:
Dear Michael,

Whatever the availability of some of the features are that you envisage to need, it struck me that your sample code seems to suffer from the fact that you squeeze everything into the same program module, while the services you seem to look for typically should go into a library module.

[MRi: The sample code is only menat to show how my proposual may work. The libraries and programms I have in mind all have several thouthands lines o code and are spread about dozends of modules - shurely nothing to line out the basics]
By this approach you seem to fully miss out on one of the fundamental features of M2. Notably data abstraction by using e.g. an opaque type exported from a library module. It seems to me before calling for language extensions it would be advisable to first try to fully exploit the features the language already offers. Perhaps I am wrong with this impression, I just wanted to share it with you as it may possibly help.

Now of course, as Benjamin rightly pointed out, one disadvantage of PIM M2 is that you need "procedures like WriteThis, WriteThat, WriteYetAnotherThat.” for the functionality of Write, which is also true of course for any functionality such as matrix algebra.

Yet, I would argue that even classical M2 offers quite attractive solutions. Perhaps not what you would be happy with, but I’d say at least usable. Look e.g. for our modules LgMatricesLgMatCalc, or LgMatInv from our SciLib (home pagequick reference) all from RAMSES.

[MRi If you want to have a look on the libraries I actually have in mind see on my (outdated) repository at https://opensourceprojects.eu/p/modula2 (I need to find a new place to publish the actual versions). ]

Andreas


ETH Zurich
Prof. em. Dr. Andreas Fischlin
IPCC Vice-Chair WGII
Systems Ecology - Institute of Biogeochemistry and Pollutant Dynamics
CHN E 24
Universitaetstrasse 16
8092 Zurich
SWITZERLAND


+41 44 633-6090 phone
+41 44 633-1136 fax
+41 79 595-4050 mobile

             Make it as simple as possible, but distrust it!
________________________________________________________________________









On Tue, 28.03.23, at 00:22, Michael Riedl <udo-michael.riedl@t-online.de> wrote:

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.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]