MODULE R2 EXPORTS R2, R2Extras; (* Hand-optimized implementation of the interfaces "R2" and "R2Extras". Created 94-05-04 by J. Stolfi, with contributions by M. C. Carrard. *) IMPORT R2Rep, RN, Math, Wr, Thread, Random, GaussRandom; PROCEDURE Zero(): T = BEGIN RETURN T{0.0, 0.0} END Zero; PROCEDURE All(x: LONGREAL): T = BEGIN WITH xx = FLOAT(x, REAL) DO RETURN T{xx, xx} END END All; PROCEDURE Axis(i: [0..N-1]): T = VAR r: T := T{0.0, 0.0}; BEGIN r[i] := 1.0; RETURN r END Axis; PROCEDURE Get(READONLY a: T; i: [0..N-1]): LONGREAL = BEGIN RETURN FLOAT(a[i], LONGREAL) END Get; PROCEDURE Set(VAR a: T; i: [0..N-1]; x: LONGREAL) = BEGIN a[i] := FLOAT(x, ElemT) END Set; PROCEDURE Add(READONLY a, b: T): T = BEGIN RETURN T{a[0] + b[0], a[1] + b[1]} END Add; PROCEDURE Sub(READONLY a, b: T): T = BEGIN RETURN T{a[0] - b[0], a[1] - b[1]} END Sub; PROCEDURE Neg(READONLY a: T): T = BEGIN RETURN T{- a[0], - a[1]} END Neg; PROCEDURE Scale(s: LONGREAL; READONLY a: T): T = BEGIN WITH a0 = s * FLOAT(a[0], LONGREAL), a1 = s * FLOAT(a[1], LONGREAL) DO RETURN T{FLOAT(a0), FLOAT(a1)} END END Scale; PROCEDURE Weigh(READONLY w: LongRealT; READONLY a: T): T = BEGIN WITH c0 = FLOAT(a[0], LONGREAL) * w[0], c1 = FLOAT(a[1], LONGREAL) * w[1] DO RETURN T{FLOAT(c0), FLOAT(c1)} END END Weigh; PROCEDURE Mix(s: LONGREAL; READONLY a: T; t: LONGREAL; READONLY b: T): T = BEGIN WITH c0 = s * FLOAT(a[0], LONGREAL) + t * FLOAT(b[0], LONGREAL), c1 = s * FLOAT(a[1], LONGREAL) + t * FLOAT(b[1], LONGREAL) DO RETURN T{FLOAT(c0), FLOAT(c1)} END END Mix; PROCEDURE Norm(READONLY a: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), (* This can't overflow, and is probably faster than "Math.hypot": *) norm = Math.sqrt(a0*a0 + a1*a1) DO RETURN norm END END Norm; PROCEDURE NormSqr(READONLY a: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), normSqr = a0*a0 + a1*a1 DO RETURN normSqr END END NormSqr; PROCEDURE Dist(READONLY a, b: T): LONGREAL = BEGIN WITH t0 = FLOAT(a[0], LONGREAL) - FLOAT(b[0], LONGREAL), t1 = FLOAT(a[1], LONGREAL) - FLOAT(b[1], LONGREAL), (* This can't overflow, and is probably faster than "Math.hypot": *) dist = Math.sqrt(t0*t0 + t1*t1) DO RETURN dist END END Dist; PROCEDURE DistSqr(READONLY a, b: T): LONGREAL = BEGIN WITH t0 = FLOAT(a[0], LONGREAL) - FLOAT(b[0], LONGREAL), t1 = FLOAT(a[1], LONGREAL) - FLOAT(b[1], LONGREAL), distSqr = t0*t0 + t1*t1 DO RETURN distSqr END END DistSqr; PROCEDURE Dir(READONLY a: T): T = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), (* This can't overflow, and is probably faster than "Math.hypot": *) norm = Math.sqrt(a0*a0 + a1*a1) DO RETURN T{FLOAT(a0/norm), FLOAT(a1/norm)} END END Dir; PROCEDURE LInfNorm(READONLY a: T): LONGREAL = BEGIN WITH norm = MAX(ABS(a[0]), ABS(a[1])) DO RETURN FLOAT(norm, LONGREAL) END END LInfNorm; PROCEDURE LInfDist(READONLY a, b: T): LONGREAL = BEGIN WITH dist = MAX(ABS(a[0] - b[0]), ABS(a[1] - b[1])) DO RETURN FLOAT(dist, LONGREAL) END END LInfDist; PROCEDURE LInfDir(READONLY a: T): T = BEGIN WITH norm = MAX(ABS(a[0]), ABS(a[1])) DO RETURN T{a[0]/norm, a[1]/norm} END END LInfDir; PROCEDURE Dot(READONLY a, b: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), b0 = FLOAT(b[0], LONGREAL), b1 = FLOAT(b[1], LONGREAL), dot = a0*b0 + a1*b1 DO RETURN dot END END Dot; PROCEDURE Cos(READONLY a, b: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), b0 = FLOAT(b[0], LONGREAL), b1 = FLOAT(b[1], LONGREAL), aa = a0*a0 + a1*a1, bb = b0*b0 + b1*b1, ab = a0*b0 + a1*b1, cos = ab/(Math.sqrt(aa)*Math.sqrt(bb)) DO RETURN cos END END Cos; PROCEDURE Sin(READONLY a, b: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), b0 = FLOAT(b[0], LONGREAL), b1 = FLOAT(b[1], LONGREAL), aa = a0*a0 + a1*a1, bb = b0*b0 + b1*b1, c = a0*b1 - a1*b0, sin = Math.sqrt((c/aa)*(c/bb)) DO RETURN sin END END Sin; PROCEDURE Det(READONLY a, b: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), b0 = FLOAT(b[0], LONGREAL), b1 = FLOAT(b[1], LONGREAL), t = a0*b1 - a1*b0 DO RETURN t END END Det; PROCEDURE Cross(READONLY a: T): T = BEGIN RETURN T{-a[1], +a[0]} END Cross; PROCEDURE Project(READONLY a, u: T): T = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), u0 = FLOAT(u[0], LONGREAL), u1 = FLOAT(u[1], LONGREAL), sau = a0*u0 + a1*u1 DO IF sau = 0.0d0 THEN RETURN T{0.0, 0.0} ELSE WITH suu = u0*u0 + u1*u1, c = sau/suu DO RETURN T{FLOAT(c*u0), FLOAT(c*u1)} END END END; END Project; PROCEDURE Orthize(READONLY a, u: T): T = BEGIN WITH u0 = FLOAT(u[0], LONGREAL), u1 = FLOAT(u[1], LONGREAL), suu = u0*u0 + u1*u1 DO IF suu = 0.0d0 THEN RETURN a ELSE WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), sau = a0*u0 + a1*u1 DO IF sau = 0.0d0 THEN RETURN a ELSE WITH c = sau/suu DO RETURN T{FLOAT(a0-c*u0), FLOAT(a1-c*u1)} END END END END END; END Orthize; PROCEDURE ToReal(READONLY a: T): RealT = BEGIN RETURN a END ToReal; PROCEDURE FromReal(READONLY a: RealT): T = BEGIN RETURN a END FromReal; PROCEDURE ToLongReal(READONLY a: T): LongRealT = BEGIN RETURN LongRealT{ FLOAT(a[0], LONGREAL), FLOAT(a[1], LONGREAL) } END ToLongReal; PROCEDURE FromLongReal(READONLY a: LongRealT): T = BEGIN RETURN T{ FLOAT(a[0], REAL), FLOAT(a[1], REAL) } END FromLongReal; PROCEDURE URandom(rnd: Random.T; min, max: LONGREAL): T = VAR r: T; BEGIN FOR i := 0 TO N-1 DO r[i] := rnd.real(FLOAT(min), FLOAT(max)) END; RETURN r END URandom; PROCEDURE NRandom(rnd: Random.T; avg, dev: LONGREAL): T = VAR r: T; BEGIN FOR i := 0 TO N-1 DO r[i] := FLOAT(avg + dev * FLOAT(GaussRandom.Real(rnd), LONGREAL)) END; RETURN r END NRandom; PROCEDURE Print( wr: Wr.T; READONLY a: T; lp := "("; sep := " "; rp := ")"; fmt: PROCEDURE (x: ElemT): TEXT := R2Rep.DefaultElemFmt; ) RAISES {Wr.Failure, Thread.Alerted} = BEGIN RN.Print(wr, a, lp, sep, rp, fmt) END Print; PROCEDURE ToText(READONLY a: T): TEXT = BEGIN RETURN RN.ToText(a) END ToText; BEGIN END R2.