GENERIC INTERFACE VectorN (VRep); (* In-place ("destructive") vector space operations on objects of some type "VRep.T". Assumes a "VRep.T" object "v" has "Dim(v)" numeric coordinates, numbered from 0 to "Dim(v)-1". Operations taking two or more "VRep.T" arguments usually expect that all have the same number of coordinates. *) IMPORT Random, Wr, Thread; TYPE T = VRep.T; ElemT = VRep.ElemT; RealT = ARRAY OF REAL; LongRealT = ARRAY OF LONGREAL; PROCEDURE Dim(READONLY a: T): CARDINAL; (* Number of coordinates in "a". *) PROCEDURE Fill(VAR a: T; x: LONGREAL); (* Sets all coordinates of "a" to "x". *) PROCEDURE Axis(VAR a: T; i: CARDINAL); (* Set "a" to the "i"-th canonical vector, i.e. all zeros, except for a "1" in the "i"-th coordinate. Requires "i" in the range "[0..Dim(a)-1]" *) PROCEDURE Get(READONLY a: T; i: CARDINAL): LONGREAL; (* Extracts coordinate "i" of "a", converting it to LONGREAL *) PROCEDURE Set(VAR a: T; i: CARDINAL; x: LONGREAL); (* Sets coordinate "i" of "a" to "x", rounded if necessary. *) PROCEDURE Add(VAR a: T; READONLY b: T); (* Sets "a := a + b" *) PROCEDURE Sub(VAR a: T; READONLY b: T); (* Sets "a := a + b" *) PROCEDURE Neg(VAR a: T); (* Sets "a := -a" *) PROCEDURE Scale(s: LONGREAL; VAR a: T); (* Sets "a := s*a"; *) PROCEDURE Weigh(READONLY w: LongRealT; VAR a: T); (* Sets "a[i] := w[i] * a[i]" for all "i". *) PROCEDURE Mix(s: LONGREAL; VAR a: T; t: LONGREAL; READONLY b: T); (* Sets "a := s*a + t*b". *) PROCEDURE Modify(VAR a: T; s: LONGREAL; READONLY b: T): BOOLEAN; (* Sets "a := a + s*b"; returns TRUE iff "a" changed. *) PROCEDURE Norm(READONLY a: T): LONGREAL; (* Returns the Euclidean length (norm) of vector "a". *) PROCEDURE NormSqr(READONLY a: T): LONGREAL; (* The Euclidean norm of "a", squared. *) PROCEDURE Dir(VAR a: T): LONGREAL; (* Scales "a" by "1/Norm(a)". Returns the old norm as a result. *) PROCEDURE Dist(READONLY a, b: T): LONGREAL; (* The Euclidean distance betwen a and b *) PROCEDURE DistSqr(READONLY a, b: T): LONGREAL; (* The Euclidean distance betwen a and b, squared *) PROCEDURE LInfNorm(READONLY a: T): LONGREAL; (* Returns the $L_\infinity$ norm (max absolute coordinate) of "a" *) PROCEDURE LInfDist(READONLY a, b: T): LONGREAL; (* The $L_\infinity$ distance betwen a and b *) PROCEDURE LInfDir(VAR s: T): LONGREAL; (* Scales "a" by "1/LInfNorm(a)". Returns the old norm as a result. *) PROCEDURE Dot(READONLY a, b: T): LONGREAL; (* Returns the dot product of vectors "a" and "b". *) PROCEDURE Cos(READONLY a, b: T): LONGREAL; (* Returns the cosine of the angle between "a" and "b". *) PROCEDURE Sin(READONLY a, b: T): LONGREAL; (* Returns the (non-negative) sine of the angle between "a" and "b". *) PROCEDURE Decompose(VAR a, b: T); (* Decomposes "a" into components "ao" and "ap" that are respectively orthogonal and parallel to "b"; then sets "a := ao", "b := ap". *) PROCEDURE Triangularize(VAR m: ARRAY OF T; total := FALSE); (* Views the vectors "m[i]" as the rows of a rectangular matrix, and reduces "m" to upper triangular form by elementary row operations. A matrix "m" is {\em upper triangular} if "m[i,j]" is zero whenever "i>j". 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 a: T; VAR c: RealT); PROCEDURE ToLongReal(READONLY a: T; VAR c: LongRealT); (* Convert from "VRep.T" to plain array of "REAL" or "LONGREAL". Require "NUMBER(c) = Dim(a)". *) 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 "VRep.T". Require "NUMBER(c) = Dim(a)". *) PROCEDURE URandom(VAR a: T; rnd: Random.T; min, max: LONGREAL); (* Set the coordinates of "a" to independent random numbers, uniformly distributed in "[min __ max)". *) PROCEDURE NRandom(VAR a: T; rnd: Random.T; avg, dev: LONGREAL); (* Set the coordinates of "a" to independent Gaussian random numbers with mean "avg" and standard deviation "dev". *) PROCEDURE Print( wr: Wr.T; READONLY a: T; lp := "("; sep := " "; rp := ")"; fmt: PROCEDURE(x: ElemT): TEXT := VRep.DefaultElemFmt; ) RAISES {Wr.Failure, Thread.Alerted}; (* Prints "a" on the given writer, formatting each coordinate with "fmt". The parameters "style", "prec", and "pad" govern the printing of each coordinate. The strings "lp", "sep", and "rp" are printed respectively before, between, and after all the coordinates of "a". *) PROCEDURE ToText(READONLY m: T): TEXT; (* Formats "m" in some standard format. *) END VectorN.