language-Modula2-0.1: examples/Modula-2_Libraries/andrea-m2/lib/generic/packmatri.mod
IMPLEMENTATION MODULE PackMatrix;
(* Matrix of small cardinal values packed into bit items,
see the corresponding definition *)
(* V1.1, J. Andrea, Jun.22/93 -add Duplictate, fix bug in Offset *)
(* V1.0, J. Andrea, Jun.15/93 *)
(* This code may be freely used and distributed, it may not be sold. *)
IMPORT PackArray;
FROM Storage IMPORT ALLOCATE, DEALLOCATE;
TYPE
DataType = CARDINAL;
Matrix = POINTER TO RECORD
rows, cols :CARDINAL;
min, max :DataType;
data :PackArray.Array;
END;
(* -------------------------------------------------------- *)
PROCEDURE InRange( a :Matrix; row, col :CARDINAL ) :BOOLEAN;
(* Is the specified row/col item in this matrix ? *)
BEGIN
RETURN ( row >= 1 ) & ( row <= a^.rows ) & ( col >= 1 ) & ( col <= a^.cols );
END InRange;
(* -------------------------------------------------------- *)
PROCEDURE Offset( a :Matrix; row, col :CARDINAL ) :CARDINAL;
(* Calculate the memory offset to the row/col item from the first item *)
(* This is not zero based, so no "-1" *)
BEGIN
RETURN ( row - 1 ) * a^.cols + col;
END Offset;
(* -------------------------------------------------------- *)
PROCEDURE Build( VAR a :Matrix; minimum, maximum, rows, cols :CARDINAL );
VAR
temp :DataType;
BEGIN
NEW( a );
IF rows = 0 THEN rows := 1 END;
IF cols = 0 THEN cols := 1 END;
a^.rows := rows;
a^.cols := cols;
IF minimum > maximum THEN
temp := maximum;
maximum := minimum;
minimum := temp;
END;
a^.min := minimum;
a^.max := maximum;
PackArray.Build( a^.data, minimum, maximum, rows * cols );
END Build;
(* -------------------------------------------------------- *)
PROCEDURE Destroy( VAR a :Matrix );
BEGIN
PackArray.Destroy( a^.data );
DISPOSE( a );
END Destroy;
(* -------------------------------------------------------- *)
PROCEDURE Put( a :Matrix; row, col :CARDINAL; x :DataType );
BEGIN
IF InRange( a, row, col ) THEN
PackArray.Put( a^.data, Offset( a, row, col ), x );
END;
END Put;
(* -------------------------------------------------------- *)
PROCEDURE Get( a :Matrix; row, col :CARDINAL ) :DataType;
BEGIN
IF NOT InRange( a, row, col ) THEN
RETURN 0;
ELSE
RETURN PackArray.Get( a^.data, Offset( a, row, col ) );
END;
END Get;
(* -------------------------------------------------------- *)
PROCEDURE Size( a :Matrix; VAR bits, bytes, rows, cols :CARDINAL );
VAR
length :CARDINAL;
BEGIN
rows := a^.rows;
cols := a^.cols;
PackArray.Size( a^.data, bits, bytes, length );
END Size;
(* -------------------------------------------------------- *)
PROCEDURE Min( a :Matrix ) :DataType;
BEGIN
RETURN PackArray.Min( a^.data );
END Min;
(* -------------------------------------------------------- *)
PROCEDURE Max( a :Matrix ) :DataType;
BEGIN
RETURN PackArray.Max( a^.data );
END Max;
(* -------------------------------------------------------- *)
PROCEDURE Compare( a, b :Matrix ) :BOOLEAN;
BEGIN
IF ( a^.rows # b^.rows ) OR ( a^.cols # b^.cols ) THEN
RETURN FALSE;
ELSE
RETURN PackArray.Compare( a^.data, b^.data );
END;
END Compare;
(* -------------------------------------------------------- *)
PROCEDURE Assign( a :Matrix; x :DataType );
BEGIN
PackArray.Assign( a^.data, x );
END Assign;
(* -------------------------------------------------------- *)
PROCEDURE Copy( a, b :Matrix );
BEGIN
IF ( a^.min = b^.min ) & ( a^.max = b^.max ) &
( a^.rows = b^.rows ) & ( a^.cols = b^.cols ) THEN
PackArray.Copy( a^.data, b^.data );
END;
END Copy;
(* -------------------------------------------------------- *)
PROCEDURE Duplicate( a :Matrix; VAR b :Matrix );
BEGIN
Build( b, a^.min, a^.max, a^.rows, a^.cols );
Copy( a, b );
END Duplicate;
BEGIN
END PackMatrix.