MODULE R4 EXPORTS R4, R4Extras; (* Hand-optimized implementation OF the interfaces "R4" and "R4Extras". Created by J. Stolfi, with contributions by M. C. Carrard. *) IMPORT R4Rep, RN, Math, Wr, Thread, Random, GaussRandom; PROCEDURE Zero(): T = BEGIN RETURN T{0.0, ..} END Zero; PROCEDURE All(x: LONGREAL): T = BEGIN WITH xx = FLOAT(x, REAL) DO RETURN T{xx, ..} END END All; PROCEDURE Axis(i: [0..N-1]): T = VAR r: T := T{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], a[2] + b[2], a[3] + b[3]} END Add; PROCEDURE Sub(READONLY a, b: T): T = BEGIN RETURN T{a[0] - b[0], a[1] - b[1], a[2] - b[2], a[3] - b[3]} END Sub; PROCEDURE Neg(READONLY a: T): T = BEGIN RETURN T{- a[0], - a[1], - a[2], - a[3]} END Neg; PROCEDURE Scale(s: LONGREAL; READONLY a: T): T = BEGIN WITH a0 = s * FLOAT(a[0], LONGREAL), a1 = s * FLOAT(a[1], LONGREAL), a2 = s * FLOAT(a[2], LONGREAL), a3 = s * FLOAT(a[3], LONGREAL) DO RETURN T{FLOAT(a0), FLOAT(a1), FLOAT(a2), FLOAT(a3)} 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], c2 = FLOAT(a[2], LONGREAL) * w[2], c3 = FLOAT(a[3], LONGREAL) * w[3] DO RETURN T{FLOAT(c0), FLOAT(c1), FLOAT(c2), FLOAT(c3)} 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), c2 = s * FLOAT(a[2], LONGREAL) + t * FLOAT(b[2], LONGREAL), c3 = s * FLOAT(a[3], LONGREAL) + t * FLOAT(b[3], LONGREAL) DO RETURN T{FLOAT(c0), FLOAT(c1), FLOAT(c2), FLOAT(c3)} END END Mix; PROCEDURE Norm(READONLY a: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), a2 = FLOAT(a[2], LONGREAL), a3 = FLOAT(a[3], LONGREAL), (* This can't overflow, and is probably faster than "Math.hypot": *) norm = Math.sqrt(a0*a0 + a1*a1 + a2*a2 + a3*a3) DO RETURN norm END END Norm; PROCEDURE NormSqr(READONLY a: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), a2 = FLOAT(a[2], LONGREAL), a3 = FLOAT(a[3], LONGREAL), normSqr = a0*a0 + a1*a1 + a2*a2 + a3*a3 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), t2 = FLOAT(a[2], LONGREAL) - FLOAT(b[2], LONGREAL), t3 = FLOAT(a[3], LONGREAL) - FLOAT(b[3], LONGREAL), (* This can't overflow, and is probably faster than "Math.hypot": *) dist = Math.sqrt(t0*t0 + t1*t1 + t2*t2 + t3*t3) 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), t2 = FLOAT(a[2], LONGREAL) - FLOAT(b[2], LONGREAL), t3 = FLOAT(a[3], LONGREAL) - FLOAT(b[3], LONGREAL), distSqr = t0*t0 + t1*t1 + t2*t2 + t3*t3 DO RETURN distSqr END END DistSqr; PROCEDURE Dir(READONLY a: T): T = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), a2 = FLOAT(a[2], LONGREAL), a3 = FLOAT(a[3], LONGREAL), (* This can't overflow, and is probably faster than "Math.hypot": *) norm = Math.sqrt(a0*a0 + a1*a1 + a2*a2 + a3*a3) DO RETURN T{FLOAT(a0/norm), FLOAT(a1/norm), FLOAT(a2/norm), FLOAT(a3/norm)} END END Dir; PROCEDURE LInfNorm(READONLY a: T): LONGREAL = BEGIN WITH norm = MAX(MAX(ABS(a[0]), ABS(a[1])), MAX(ABS(a[2]), ABS(a[3]))) DO RETURN FLOAT(norm, LONGREAL) END END LInfNorm; PROCEDURE LInfDist(READONLY a, b: T): LONGREAL = BEGIN WITH dist = MAX( MAX(ABS(a[0]-b[0]), ABS(a[1]-b[1])), MAX(ABS(a[2]-b[2]), ABS(a[3]-b[3])) ) DO RETURN FLOAT(dist, LONGREAL) END END LInfDist; PROCEDURE LInfDir(READONLY a: T): T = BEGIN WITH norm = MAX(MAX(ABS(a[0]), ABS(a[1])), MAX(ABS(a[2]), ABS(a[3]))) DO RETURN T{a[0]/norm, a[1]/norm, a[2]/norm, a[3]/norm} END END LInfDir; PROCEDURE Dot(READONLY a, b: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), a2 = FLOAT(a[2], LONGREAL), a3 = FLOAT(a[3], LONGREAL), b0 = FLOAT(b[0], LONGREAL), b1 = FLOAT(b[1], LONGREAL), b2 = FLOAT(b[2], LONGREAL), b3 = FLOAT(b[3], LONGREAL), dot = a0*b0 + a1*b1 + a2*b2 + a3*b3 DO RETURN dot END END Dot; PROCEDURE Cos(READONLY a, b: T): LONGREAL = BEGIN RETURN RN.Cos(a, b) END Cos; PROCEDURE Sin(READONLY a, b: T): LONGREAL = BEGIN RETURN RN.Sin(a, b) END Sin; PROCEDURE Det(READONLY a, b, c, d: T): LONGREAL = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), a2 = FLOAT(a[2], LONGREAL), a3 = FLOAT(a[3], LONGREAL), b0 = FLOAT(b[0], LONGREAL), b1 = FLOAT(b[1], LONGREAL), b2 = FLOAT(b[2], LONGREAL), b3 = FLOAT(b[3], LONGREAL), ab_01 = a0 * b1 - a1 * b0, ab_02 = a0 * b2 - a2 * b0, ab_12 = a1 * b2 - a2 * b1, ab_03 = a0 * b3 - a3 * b0, ab_13 = a1 * b3 - a3 * b1, ab_23 = a2 * b3 - a3 * b2, c0 = FLOAT(c[0], LONGREAL), c1 = FLOAT(c[1], LONGREAL), c2 = FLOAT(c[2], LONGREAL), c3 = FLOAT(c[3], LONGREAL), d0 = FLOAT(d[0], LONGREAL), d1 = FLOAT(d[1], LONGREAL), d2 = FLOAT(d[2], LONGREAL), d3 = FLOAT(d[3], LONGREAL), cd_01 = c0 * d1 - c1 * d0, cd_02 = c0 * d2 - c2 * d0, cd_12 = c1 * d2 - c2 * d1, cd_03 = c0 * d3 - c3 * d0, cd_13 = c1 * d3 - c3 * d1, cd_23 = c2 * d3 - c3 * d2, d = + ab_01 * cd_23 - ab_02 * cd_13 + ab_12 * cd_03 + ab_03 * cd_12 - ab_13 * cd_02 + ab_23 * cd_01 DO RETURN d END END Det; PROCEDURE Cross(READONLY a, b, c: T): T = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), a2 = FLOAT(a[2], LONGREAL), a3 = FLOAT(a[3], LONGREAL), b0 = FLOAT(b[0], LONGREAL), b1 = FLOAT(b[1], LONGREAL), b2 = FLOAT(b[2], LONGREAL), b3 = FLOAT(b[3], LONGREAL), ab_01 = a0*b1 - a1*b0, ab_02 = a0*b2 - a2*b0, ab_12 = a1*b2 - a2*b1, ab_03 = a0*b3 - a3*b0, ab_13 = a1*b3 - a3*b1, ab_23 = a2*b3 - a3*b2, c0 = FLOAT(c[0], LONGREAL), c1 = FLOAT(c[1], LONGREAL), c2 = FLOAT(c[2], LONGREAL), c3 = FLOAT(c[3], LONGREAL), abc_012 = ab_01 * c2 - ab_02 * c1 + ab_12 * c0, abc_013 = ab_01 * c3 - ab_03 * c1 + ab_13 * c0, abc_023 = ab_02 * c3 - ab_03 * c2 + ab_23 * c0, abc_123 = ab_12 * c3 - ab_13 * c2 + ab_23 * c1 DO RETURN T{ FLOAT(- abc_123), FLOAT(+ abc_023), FLOAT(- abc_013), FLOAT(+ abc_012) } END; END Cross; PROCEDURE Project(READONLY a, u: T): T = BEGIN WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), a2 = FLOAT(a[2], LONGREAL), a3 = FLOAT(a[3], LONGREAL), u0 = FLOAT(u[0], LONGREAL), u1 = FLOAT(u[1], LONGREAL), u2 = FLOAT(u[2], LONGREAL), u3 = FLOAT(u[3], LONGREAL), sau = a0*u0 + a1*u1 + a2*u2 + a3*u3 DO IF sau = 0.0d0 THEN RETURN T{0.0, 0.0, 0.0, 0.0} ELSE WITH suu = u0*u0 + u1*u1 + u2*u2 + u3*u3, c = sau/suu DO RETURN T{FLOAT(c*u0), FLOAT(c*u1), FLOAT(c*u2), FLOAT(c*u3)} END END END; END Project; PROCEDURE Orthize(READONLY a, u: T): T = BEGIN WITH u0 = FLOAT(u[0], LONGREAL), u1 = FLOAT(u[1], LONGREAL), u2 = FLOAT(u[2], LONGREAL), u3 = FLOAT(u[3], LONGREAL), suu = u0*u0 + u1*u1 + u2*u2 + u3*u3 DO IF suu = 0.0d0 THEN RETURN a ELSE WITH a0 = FLOAT(a[0], LONGREAL), a1 = FLOAT(a[1], LONGREAL), a2 = FLOAT(a[2], LONGREAL), a3 = FLOAT(a[3], LONGREAL), sau = a0*u0 + a1*u1 + a2*u2 + a3*u3 DO IF sau = 0.0d0 THEN RETURN a ELSE WITH c = sau/suu DO RETURN T{FLOAT(a0-c*u0), FLOAT(a1-c*u1), FLOAT(a2-c*u2), FLOAT(a3-c*u3)} 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), FLOAT(a[2], LONGREAL), FLOAT(a[3], LONGREAL) } END ToLongReal; PROCEDURE FromLongReal(READONLY a: LongRealT): T = BEGIN RETURN T{ FLOAT(a[0], REAL), FLOAT(a[1], REAL), FLOAT(a[2], REAL), FLOAT(a[3], 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 := R4Rep.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 R4.