GENERIC INTERFACE MatrixN (DRep, RRep, MRep); (* In-place ("destructive") linear maps from vectors of type "DRep.T" to vectors of type "RRep.T", represented as "MRep.T"s. It is assumed that each "MRep.T" has finite-dimensional range and domain. Thus, conceptually, an "MRep.T" is a two-dimensional array of floats, but concretely it could be something else --- say, a triangular matrix, a quaternion, a procedure, etc. Created by J. Stolfi, with contributions by Marcos C. Carrard. *) IMPORT Wr, Thread; TYPE T = MRep.T; ElemT = MRep.ElemT; RealT = ARRAY OF ARRAY OF REAL; LongRealT = ARRAY OF ARRAY OF LONGREAL; PROCEDURE NRows(READONLY m: T): CARDINAL; PROCEDURE NCols(READONLY m: T): CARDINAL; (* Number of rows (dimension of domain space) and of columns (dimension of range) of the map "m". *) PROCEDURE Fill(VAR m: T; x: LONGREAL); (* Sets all coefficients of "m" to "x". *) PROCEDURE Identity(VAR m: T); (* Sets "m" to the identity matrix. *) PROCEDURE Diagonal(VAR m: T; READONLY a: ARRAY OF LONGREAL); (* Sets "m" to all zeros, except that "m[i,i]" is set to "a[i]" for each "i". The size of "a" must be "MIN(NRows(m), NCols(m))". *) PROCEDURE Get(READONLY m: T; i, j: CARDINAL): LONGREAL; (* Extracts coefficient "[i,j]" of "m", converting it to LONGREAL *) PROCEDURE Set(VAR a: T; i, j: CARDINAL; x: LONGREAL); (* Sets coefficient "[i,j]" of "m" to "x", rounded if necessary. *) PROCEDURE MapRow(READONLY a: DRep.T; READONLY m: T; VAR r: RRep.T); (* Stores in "r" the product of "a", viewed as a row vector, by the matrix "m". *) PROCEDURE MapCol(READONLY m: T; READONLY a: RRep.T; VAR r: DRep.T); (* Stores in "r" the product of matrix "m" by the vector "a", viewed as a column vector. *) PROCEDURE Mul(READONLY m, n: T; VAR r: T); (* Stores in "r" the product of matrices "m" and "n", in that order. Requires "NRows(r) = NRows(m)", "NCols(r) = NCols(n)", and "NCols(m) = NRows(n)". *) PROCEDURE Triangularize(VAR m: T; total := FALSE); (* Reduces "m" to upper triangular form by elementary row operations. A matrix "m" is {\em upper tr1iangular} if the elements "m[i,j]" with "i > j" are all zero. An {\em elementary row operation} consists of adding a multiple of one row to another row; a {\em row swap} consists of exchanging two rows and negating one of them. Observe that these operations are equivalent to premultiplying the matrix by a square matrix with unit determinant. If "total" is true, the procedure keeps applying elementary row operations until "m" is {\em totally reduced}, that is, each row that is not entirely zero has at least one more leading zero than the preceding row. *) PROCEDURE ToReal(READONLY m: T; VAR c: RealT); PROCEDURE ToLongReal(READONLY m: T; VAR c: LongRealT); (* Convert from "MRep.T" to plain array of "REAL" or "LONGREAL". *) PROCEDURE FromReal(VAR a: T; READONLY c: RealT); PROCEDURE FromLongReal(VAR a: T; READONLY c: LongRealT); (* Convert from plain array of "REAL" or "LONGREAL" to "MRep.T". *) PROCEDURE Print( wr: Wr.T; READONLY m: T; olp := "( "; osep := "\n "; orp := " )"; ilp := "("; isep := " "; irp := ")"; fmt: PROCEDURE(x: ElemT): TEXT := MRep.DefaultElemFmt; align: BOOLEAN := TRUE; ) RAISES {Wr.Failure, Thread.Alerted}; (* Prints the matrix "m" to the given writer, formatting each coefficient with "fmt". The ``inner'' delimiters "ilp", "isep", and "irp" are printed before the first element, between elements, and after the last element in each row. The ``outer'' delimiters "olp", "osep", and "orp" are printed before the first row, between rows, and after the last row. If "align" is true, the entries in each column will be padded with blanks as needed to align them vertically. *) PROCEDURE ToText(READONLY m: T): TEXT; (* Formats "m" in some standard format. *) END MatrixN.