UNSAFE MODULE TestHypot EXPORTS Main; (* Computes the costs of "Math.hypot(x,y)" and "Math.sqrt(x*x + y*y)". *) IMPORT Wr, Fmt, Math, Uresource, Thread; FROM Stdio IMPORT stderr; FROM Fmt IMPORT Style; CONST Microsecond = 1.0d0; Second = 1000000.0d0 * Microsecond; TYPE NormFn = PROCEDURE (x, y, z: LONGREAL): LONGREAL; PROCEDURE DoIt() = VAR F: NormFn; T: TEXT; VAR x, y, z: LONGREAL; <* FATAL Wr.Failure, Thread.Alerted *> BEGIN FOR k := 0 TO 3 DO CASE k OF | 0 => F := NormEmpty; T := "empty"; | 1 => F := NormSqrt; T := "sqrt "; | 2 => F := NormHypot; T := "hypot"; | 3 => F := NormNaive; T := "naive"; END; x := 0.5d0; y := 0.5d0; WITH start = Now(), N = 200000 DO FOR i := 0 TO N-1 DO z := F(x, y, y); x := x + 1024.0d0; y := y + 4615.0d0 END; WITH stop = Now(), t = (stop-start)/FLOAT(N, LONGREAL)/Microsecond DO Wr.PutText(stderr, T); Wr.PutText(stderr, " = "); Wr.PutText(stderr, Fmt.LongReal(t, prec := 2, style := Style.Fix)); Wr.PutText(stderr, "\n"); END END END END DoIt; PROCEDURE NormEmpty( <*UNUSED*> x: LONGREAL; <*UNUSED*> y: LONGREAL; <*UNUSED*> z: LONGREAL; ): LONGREAL = BEGIN RETURN 0.0d0 END NormEmpty; PROCEDURE NormSqrt(x, y, z: LONGREAL): LONGREAL = BEGIN WITH m = MAX(MAX(MAX(ABS(x), ABS(y)), ABS(z)), 1.0d0), nx = x/m, ny = y/m, nz = z/m DO RETURN m * Math.sqrt(nx*nx + ny*ny + nz*nz) END END NormSqrt; PROCEDURE NormHypot(x, y, z: LONGREAL): LONGREAL = BEGIN RETURN Math.hypot(Math.hypot(x, y), z) END NormHypot; PROCEDURE NormNaive(x, y, z: LONGREAL): LONGREAL = BEGIN RETURN Math.sqrt(x*x + y*y + z*z) END NormNaive; PROCEDURE Now(): LONGREAL = VAR ru: Uresource.struct_rusage; BEGIN WITH rCode = Uresource.getrusage(Uresource.RUSAGE_SELF, ADR(ru)) DO <* ASSERT rCode = 0 *> RETURN FLOAT(ru.ru_utime.tv_sec, LONGREAL) * Second + FLOAT(ru.ru_utime.tv_usec, LONGREAL) * Microsecond END END Now; BEGIN DoIt() END TestHypot.