packages feed

language-Modula2-0.1: examples/Modula-2_Libraries/andrea-m2/lib/generic/realarray.mod

IMPLEMENTATION MODULE RealArrays;

(* Operations on a dynamic array of reals *)

(* V1.1, J. Andrea, Jun.22/93 -add Duplicate *)
(* V1.0, J. Andrea, May.18/92 *)
(* This code may be freely used and distributed, it may not be sold *)

FROM SYSTEM  IMPORT ADDRESS, TSIZE;
FROM Storage IMPORT ALLOCATE, DEALLOCATE;

TYPE
  RealArray = POINTER TO RECORD
             min, max :CARDINAL;      (* dimemsions of the matrix *)
             start    :ADDRESS;       (* memory address of the first item *)
             size     :CARDINAL;      (* actual size in bytes *)
           END;


  ArrayType = REAL;

VAR
  type_size  :CARDINAL;             (* #bytes in a single item *)

(* -------------------------------------------------------------- *)
PROCEDURE Build( VAR a :RealArray; min_index, max_index :CARDINAL );
VAR
  i :CARDINAL;
BEGIN
  NEW( a );

  IF min_index > max_index THEN
    i         := min_index;
    min_index := max_index;
    max_index := i;
  END;

  a^.min := min_index;
  a^.max := max_index;

  a^.size := ( max_index - min_index + 1 ) * type_size;

  ALLOCATE( a^.start, a^.size );
END Build;

(* -------------------------------------------------------- *)
PROCEDURE Destroy( VAR a :RealArray );
BEGIN
  DEALLOCATE( a^.start, a^.size );
  DISPOSE( a );
END Destroy;

(* -------------------------------------------------------- *)
PROCEDURE Put( a :RealArray; index :CARDINAL; value :ArrayType );
VAR
  adra :POINTER TO ArrayType;
BEGIN
  IF ( a^.min <= index ) & ( index <= a^.max ) THEN
    adra  := a^.start + ( index - a^.min ) * type_size;
    adra^ := value;
  END;
END Put;

(* -------------------------------------------------------- *)
PROCEDURE Get( a :RealArray; index :CARDINAL ) :ArrayType;
VAR
  adra :POINTER TO ArrayType;
BEGIN
  IF ( a^.min <= index ) & ( index <= a^.max ) THEN
    adra := a^.start + ( index - a^.min ) * type_size;
    RETURN adra^;
  ELSE
    RETURN 0.0;
  END;
END Get;

(* -------------------------------------------------------- *)
PROCEDURE Size( a :RealArray; VAR min_index, max_index :CARDINAL );
BEGIN
  min_index := a^.min;
  max_index := a^.max;
END Size;

(* -------------------------------------------------------- *)
PROCEDURE Min( a :RealArray ) :ArrayType;
VAR
  adra   :POINTER TO ArrayType;
  i, k   :CARDINAL;
  result :ArrayType;
BEGIN

  k := 0;

  adra   := a^.start;
  result := adra^;

  FOR i := a^.min+1 TO a^.max DO
     k     := k + type_size;
     adra  := a^.start + k;
     IF adra^ < result THEN result := adra^ END;
  END;

  RETURN result;
END Min;

(* -------------------------------------------------------- *)
PROCEDURE Max( a :RealArray ) :ArrayType;
VAR
  adra   :POINTER TO ArrayType;
  i, k   :CARDINAL;
  result :ArrayType;
BEGIN

  k := 0;

  adra   := a^.start;
  result := adra^;

  FOR i := a^.min+1 TO a^.max DO
     k     := k + type_size;
     adra  := a^.start + k;
     IF adra^ > result THEN result := adra^ END;
  END;

  RETURN result;
END Max;

(* -------------------------------------------------------- *)
PROCEDURE Compare( a, b :RealArray ) :BOOLEAN;
VAR
  adra, adrb :POINTER TO ArrayType;
  i, k :CARDINAL;
  ok   :BOOLEAN;
BEGIN
  IF ( a^.min = b^.min ) & ( a^.max = b^.max ) THEN

    ok := TRUE;

    k := 0;
    i := a^.min;
    WHILE ok & ( i <= a^.max ) DO
       adra  := a^.start + k;
       adrb  := b^.start + k;
       ok    := adra^ = adrb^;
       k     := k + type_size;
       i     := i + 1;
    END;

  ELSE
    ok := FALSE;
  END;

  RETURN ok;
END Compare;

(* -------------------------------------------------------- *)
PROCEDURE Assign( a :RealArray; x :ArrayType );
VAR
  adra :POINTER TO ArrayType;
  i, k :CARDINAL;
BEGIN
  k := 0;
  FOR i := a^.min TO a^.max DO
     adra  := a^.start + k;
     adra^ := x;
     k     := k + type_size;
  END;
END Assign;

(* -------------------------------------------------------- *)
PROCEDURE Copy( a, b :RealArray );
VAR
  adra, adrb :POINTER TO ArrayType;
  i, k :CARDINAL;
BEGIN
  IF ( a^.min = b^.min ) & ( a^.max = b^.max ) THEN

    k := 0;
    FOR i := a^.min TO a^.max DO
       adra  := a^.start + k;
       adrb  := b^.start + k;
       adrb^ := adra^;
       k     := k + type_size;
    END;

  END;
END Copy;

(* -------------------------------------------------------- *)
PROCEDURE Duplicate( a :RealArray; VAR b :RealArray );
VAR
  adra :POINTER TO ArrayType;
BEGIN
  Build( b, a^.min, a^.max );
  Copy( a, b );
END Duplicate;

(* -------------------------------------------------------- *)
PROCEDURE Add( a :RealArray; x :ArrayType );
VAR
  adra :POINTER TO ArrayType;
  i, k :CARDINAL;
BEGIN
  k := 0;
  FOR i := a^.min TO a^.max DO
     adra  := a^.start + k;
     adra^ := adra^ + x;
     k     := k + type_size;
  END;
END Add;

(* -------------------------------------------------------- *)
PROCEDURE Multiply(  a :RealArray; x :ArrayType );
VAR
  adra :POINTER TO ArrayType;
  i, k :CARDINAL;
BEGIN
  k := 0;
  FOR i := a^.min TO a^.max DO
     adra  := a^.start + k;
     adra^ := adra^ * x;
     k     := k + type_size;
  END;
END Multiply;

BEGIN
  type_size := TSIZE( ArrayType );
END RealArrays.