MODULE LR3 EXPORTS LR3, LR3Extras; (* Hand-optimized implementation of the interfaces "LR3" and "LR3Extras". Created by J. Stolfi, with contributions by M. C. Carrard and R. L. W. Liesenfeld. *) IMPORT LR3Rep, LRN, Math, Wr, Thread, Random, GaussRandom; PROCEDURE Zero(): T = BEGIN RETURN T{0.0d0, 0.0d0, 0.0d0} END Zero; PROCEDURE All(x: LONGREAL): T = BEGIN RETURN T{x, x, x} END All; PROCEDURE Axis(i: [0..N-1]): T = VAR r: T := T{0.0d0, 0.0d0, 0.0d0}; BEGIN r[i] := 1.0d0; RETURN r END Axis; PROCEDURE Get(READONLY a: T; i: [0..N-1]): LONGREAL = BEGIN RETURN a[i] END Get; PROCEDURE Set(VAR a: T; i: [0..N-1]; x: LONGREAL) = BEGIN a[i] := x END Set; PROCEDURE Add(READONLY a, b: T): T = BEGIN RETURN T{a[0] + b[0], a[1] + b[1], a[2] + b[2]} END Add; PROCEDURE Sub(READONLY a, b: T): T = BEGIN RETURN T{a[0] - b[0], a[1] - b[1], a[2] - b[2]} END Sub; PROCEDURE Neg(READONLY a: T): T = BEGIN RETURN T{- a[0], - a[1], - a[2]} END Neg; PROCEDURE Scale(s: LONGREAL; READONLY a: T): T = BEGIN WITH a0 = s * a[0], a1 = s * a[1], a2 = s * a[2] DO RETURN T{a0, a1, a2} END END Scale; PROCEDURE Weigh(READONLY w: LongRealT; READONLY a: T): T = BEGIN RETURN T{a[0] * w[0], a[1] * w[1], a[2] * w[2]} END Weigh; PROCEDURE Mix(s: LONGREAL; READONLY a: T; t: LONGREAL; READONLY b: T): T = BEGIN WITH c0 = s * a[0] + t * b[0], c1 = s * a[1] + t * b[1], c2 = s * a[2] + t * b[2] DO RETURN T{c0, c1, c2} END END Mix; PROCEDURE Norm(READONLY a: T): LONGREAL = BEGIN WITH a0 = a[0], a1 = a[1], a2 = a[2], norm = Math.hypot(Math.hypot(a0, a1), a2) DO RETURN norm END END Norm; PROCEDURE NormSqr(READONLY a: T): LONGREAL = BEGIN WITH a0 = a[0], a1 = a[1], a2 = a[2], normSqr = a0*a0 + a1*a1 + a2*a2 DO RETURN normSqr END END NormSqr; PROCEDURE Dist(READONLY a, b: T): LONGREAL = BEGIN WITH t0 = a[0] - b[0], t1 = a[1] - b[1], t2 = a[2] - b[2], dist = Math.hypot(Math.hypot(t0, t1), t2) DO RETURN dist END END Dist; PROCEDURE DistSqr(READONLY a, b: T): LONGREAL = BEGIN WITH t0 = a[0] - b[0], t1 = a[1] - b[1], t2 = a[2] - b[2], distSqr = t0*t0 + t1*t1 + t2*t2 DO RETURN distSqr END END DistSqr; PROCEDURE LInfNorm(READONLY a: T): LONGREAL = BEGIN WITH norm = MAX(MAX(ABS(a[0]), ABS(a[1])), ABS(a[2])) DO RETURN norm END END LInfNorm; PROCEDURE LInfDist(READONLY a, b: T): LONGREAL = BEGIN WITH dist = MAX(ABS(a[0] - b[0]), MAX(ABS(a[1] - b[1]), ABS(a[2] - b[2]))) DO RETURN dist END END LInfDist; PROCEDURE Dir(READONLY a: T): T = BEGIN WITH a0 = a[0], a1 = a[1], a2 = a[2], norm = Math.hypot(Math.hypot(a0, a1), a2) DO RETURN T{a0/norm, a1/norm, a2/norm} END END Dir; PROCEDURE LInfDir(READONLY a: T): T = BEGIN WITH norm = MAX(MAX(ABS(a[0]), ABS(a[1])), ABS(a[2])) DO RETURN T{a[0]/norm, a[1]/norm, a[2]/norm} END END LInfDir; PROCEDURE Dot(READONLY a, b: T): LONGREAL = BEGIN WITH a0 = a[0], a1 = a[1], a2 = a[2], b0 = b[0], b1 = b[1], b2 = b[2], dot = a0*b0 + a1*b1 + a2*b2 DO RETURN dot END END Dot; PROCEDURE Cos(READONLY a, b: T): LONGREAL = BEGIN WITH a0 = a[0], a1 = a[1], a2 = a[2], b0 = b[0], b1 = b[1], b2 = b[2], aa = a0*a0 + a1*a1 + a2*a2, bb = b0*b0 + b1*b1 + b2*b2, ab = a0*b0 + a1*b1 + a2*b2, cos = ab/(Math.sqrt(aa)*Math.sqrt(bb)) DO RETURN cos END END Cos; PROCEDURE Sin(READONLY a, b: T): LONGREAL = BEGIN WITH a0 = a[0], a1 = a[1], a2 = a[2], b0 = b[0], b1 = b[1], b2 = b[2], c0 = a1*b2 - a2*b1, c1 = a2*b1 - a1*b2, c2 = a0*b1 - a1*b0, aa = a0*a0 + a1*a1 + a2*a2, bb = b0*b0 + b1*b1 + b2*b2, cc = c0*c0 + c1*c1 + c2*c2, sin = Math.sqrt(cc/aa/bb) DO RETURN sin END END Sin; PROCEDURE Det(READONLY a, b, c: T): LONGREAL = BEGIN WITH a_0 = a[0], a_1 = a[1], a_2 = a[2], b_0 = b[0], b_1 = b[1], b_2 = b[2], c_0 = c[0], c_1 = c[1], c_2 = c[2], ab_01 = a_0 * b_1 - a_1 * b_0, ab_02 = a_0 * b_2 - a_2 * b_0, ab_12 = a_1 * b_2 - a_2 * b_1, t = + ab_01 * c_2 - ab_02 * c_1 + ab_12 * c_0 DO RETURN t END END Det; PROCEDURE Cross(READONLY a, b: T): T = BEGIN WITH a0 = a[0], a1 = a[1], a2 = a[2], b0 = b[0], b1 = b[1], b2 = b[2], t01 = a0*b1 - a1*b0, t02 = a0*b2 - a2*b0, t12 = a1*b2 - a2*b1 DO RETURN T{+ t12, - t02, + t01} END; END Cross; PROCEDURE Project(READONLY a, u: T): T = BEGIN WITH a0 = a[0], a1 = a[1], a2 = a[2], u0 = u[0], u1 = u[1], u2 = u[2], sau = a0*u0 + a1*u1 + a2*u2 DO IF sau = 0.0d0 THEN RETURN T{0.0d0, 0.0d0, 0.0d0} ELSE WITH suu = u0*u0 + u1*u1 + u2*u2, c = sau/suu DO RETURN T{c*u0, c*u1, c*u2} END END END; END Project; PROCEDURE Orthize(READONLY a, u: T): T = BEGIN WITH u0 = u[0], u1 = u[1], u2 = u[2], suu = u0*u0 + u1*u1 + u2*u2 DO IF suu = 0.0d0 THEN RETURN a ELSE WITH a0 = a[0], a1 = a[1], a2 = a[2], sau = a0*u0 + a1*u1 + a2*u2 DO IF sau = 0.0d0 THEN RETURN a ELSE WITH c = sau/suu DO RETURN T{a0-c*u0, a1-c*u1, a2-c*u2} END END END END END; END Orthize; PROCEDURE ToReal(READONLY a: T): RealT = BEGIN RETURN RealT{ FLOAT(a[0], REAL), FLOAT(a[1], REAL), FLOAT(a[2], REAL) } END ToReal; PROCEDURE FromReal(READONLY a: RealT): T = BEGIN RETURN T{ FLOAT(a[0], LONGREAL), FLOAT(a[1], LONGREAL), FLOAT(a[2], LONGREAL) } END FromReal; PROCEDURE ToLongReal(READONLY a: T): LongRealT = BEGIN RETURN a END ToLongReal; PROCEDURE FromLongReal(READONLY a: LongRealT): T = BEGIN RETURN a 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.longreal(min, 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] := avg + dev * GaussRandom.LongReal(rnd) END; RETURN r END NRandom; PROCEDURE Print( wr: Wr.T; READONLY a: T; lp := "("; sep := " "; rp := ")"; fmt: PROCEDURE (x: ElemT): TEXT := LR3Rep.DefaultElemFmt; ) RAISES {Wr.Failure, Thread.Alerted} = BEGIN LRN.Print(wr, a, lp, sep, rp, fmt) END Print; PROCEDURE ToText(READONLY a: T): TEXT = BEGIN RETURN LRN.ToText(a) END ToText; BEGIN END LR3.