MODULE; IMPORT Axis, Point; PROCEDURE RealPoint FromCoords (h, v: REAL): T RAISES {} = VAR p: T; BEGIN p.h := h; p.v := v; RETURN p; END FromCoords; PROCEDUREFromAxes (axis: Axis.T; n, m: REAL): T RAISES {} = VAR p: T; BEGIN CASE axis OF | Axis.T.Hor => p.h := n; p.v := m; | Axis.T.Ver => p.h := m; p.v := n; END; RETURN p; END FromAxes; PROCEDUREFloat (p: Point.T): T = VAR q: T; BEGIN q.h := FLOAT(p.h); q.v := FLOAT(p.v); RETURN q END Float; PROCEDURETrunc (p: T): Point.T = VAR q: Point.T; BEGIN q.h := TRUNC(p.h); q.v := TRUNC(p.v); RETURN q END Trunc; PROCEDUREFloor (p: T): Point.T = VAR q: Point.T; BEGIN q.h := TRUNC(p.h); IF FLOAT(q.h) > p.h THEN DEC(q.h) END; q.v := TRUNC(p.v); IF FLOAT(q.v) > p.v THEN DEC(q.v) END; RETURN q END Floor; PROCEDURERound (p: T): Point.T = VAR q: Point.T; BEGIN IF p.h < 0.0 THEN q.h := TRUNC(p.h - 0.5) ELSE q.h := TRUNC(p.h + 0.5) END; IF p.v < 0.0 THEN q.v := TRUNC(p.v - 0.5) ELSE q.v := TRUNC(p.v + 0.5) END; RETURN q END Round; PROCEDUREDistSquare (READONLY p, q: T): REAL RAISES {} = VAR dh, dv: REAL; BEGIN dh := p.h - q.h; dv := p.v - q.v; RETURN dh * dh + dv * dv; END DistSquare; PROCEDUREMinus (READONLY p: T): T RAISES {} = VAR q: T; BEGIN q.h := -p.h; q.v := -p.v; RETURN q; END Minus; PROCEDUREAdd (READONLY p, q: T): T RAISES {} = VAR r: T; BEGIN r.h := p.h + q.h; r.v := p.v + q.v; RETURN r; END Add; PROCEDURESub (READONLY p, q: T): T RAISES {} = VAR r: T; BEGIN r.h := p.h - q.h; r.v := p.v - q.v; RETURN r; END Sub; PROCEDUREMul (READONLY p: T; n: REAL): T RAISES {} = VAR q: T; BEGIN q.h := p.h * n; q.v := p.v * n; RETURN q; END Mul; PROCEDUREDiv (READONLY p: T; n: REAL): T RAISES {} = VAR q: T; BEGIN q.h := p.h / n; q.v := p.v / n; RETURN q; END Div; PROCEDUREMod (READONLY p: T; n: REAL): T RAISES {} = VAR q: T; BEGIN q.h := p.h - FLOAT(TRUNC(p.h/n))*n; WHILE q.h > n DO q.h := q.h - n END; WHILE q.h < 0.0 DO q.h := q.h + n END; q.v := p.v - FLOAT(TRUNC(p.v/n))*n; WHILE q.v > n DO q.v := q.v - n END; WHILE q.v < 0.0 DO q.v := q.v + n END; RETURN q END Mod; PROCEDUREScale (READONLY p: T; num, den: REAL): T RAISES {} = VAR q: T; BEGIN q.h := (p.h * num) / den; q.v := (p.v * num) / den; RETURN q; END Scale; PROCEDUREMin (READONLY p, q: T): T RAISES {} = VAR r: T; BEGIN r.h := MIN (p.h, q.h); r.v := MIN (p.v, q.v); RETURN r; END Min; PROCEDUREMax (READONLY p, q: T): T RAISES {} = VAR r: T; BEGIN r.h := MAX (p.h, q.h); r.v := MAX (p.v, q.v); RETURN r; END Max; PROCEDUREMove (READONLY p, dp: T): T RAISES {} = VAR r: T; BEGIN r.h := p.h + dp.h; r.v := p.v + dp.v; RETURN r; END Move; PROCEDUREMoveH (READONLY p: T; dh: REAL): T RAISES {} = VAR r: T; BEGIN r.h := p.h + dh; r.v := p.v; RETURN r; END MoveH; PROCEDUREMoveV (READONLY p: T; dv: REAL): T RAISES {} = VAR r: T; BEGIN r.h := p.h; r.v := p.v + dv; RETURN r; END MoveV; PROCEDUREMoveHV (READONLY p: T; dh, dv: REAL): T RAISES {} = VAR r: T; BEGIN r.h := p.h + dh; r.v := p.v + dv; RETURN r; END MoveHV; PROCEDUREEqual (READONLY p, q: T): BOOLEAN RAISES {} = BEGIN RETURN (p.h = q.h) AND (p.v = q.v); END Equal; PROCEDURELess (READONLY p, q: T): BOOLEAN RAISES {} = BEGIN RETURN (p.h < q.h) AND (p.v < q.v); END Less; PROCEDURELessEq (READONLY p, q: T): BOOLEAN RAISES {} = BEGIN RETURN (p.h <= q.h) AND (p.v <= q.v); END LessEq; PROCEDURENew (READONLY value: T): REF T = VAR r: REF T; BEGIN r := NEW (REF T); r^ := value; RETURN r; END New; PROCEDURENewArray (size: CARDINAL; READONLY value := Origin): REF ARRAY OF T = VAR arr: REF ARRAY OF T; BEGIN arr := NEW (REF ARRAY OF T, size); (* Assumes the allocator initializes to Origin automatically: *) IF value # Origin THEN FOR i := 0 TO size - 1 DO arr[i] := value END; END; RETURN arr END NewArray; PROCEDUREUntracedNew (READONLY value: T): UNTRACED REF T = VAR r: UNTRACED REF T; BEGIN r := NEW (UNTRACED REF T); r^ := value; RETURN r; END UntracedNew; PROCEDUREUntracedNewArray (size: CARDINAL; READONLY value := Origin): UNTRACED REF ARRAY OF T = VAR arr: UNTRACED REF ARRAY OF T; BEGIN arr := NEW (UNTRACED REF ARRAY OF T, size); (* Assumes the allocator initializes to Origin automatically: *) IF value # Origin THEN FOR i := 0 TO size - 1 DO arr[i] := value END; END; RETURN arr END UntracedNewArray; PROCEDURECompare (READONLY a, b: T): INTEGER = BEGIN IF (a.h < b.h) THEN RETURN -1; ELSIF (a.h > b.h) THEN RETURN +1; ELSIF (a.v = b.v) THEN RETURN 0; ELSIF (a.v < b.v) THEN RETURN -1; ELSE RETURN +1; END; END Compare; PROCEDURELt (READONLY a, b: T): BOOLEAN = BEGIN RETURN (a.h < b.h) OR ((a.h = b.h) AND (a.v < b.v)); END Lt; PROCEDUREEq (READONLY a, b: T): BOOLEAN = BEGIN RETURN (a.h = b.h) AND (a.v = b.v); END Eq; PROCEDUREHash (READONLY a: T): INTEGER = BEGIN RETURN ROUND(a.h * a.v); END Hash; BEGIN END RealPoint.