(* solution using mutation * * on AMD64, * 2.0 secs for OCaml 3.11.1 * (-nodynlink -inline 100, with OCAMLRUNPARAM=o=120,h=70M to set the heap size) * 8.3 secs for silly.java (java -Xms512m -server) * Java HotSpot(TM) 64-Bit Server VM (build 10.0-b19, mixed mode) * *) open Printf type point = { mutable x : float; mutable y : float; mutable z : float } let makePoint n = let fn = float_of_int n in let x = sin fn in let y = 3.0 *. cos fn in let z = let s = sin fn in s *. s /. 2.0 in {x = x; y = y; z = z} let toString p = sprintf "%f, %f, %f" p.x p.y p.z let makePoints n = Array.init n makePoint let pointNorm p = p.x *. p.x +. p.y *. p.y +. p.z *. p.z let normalizePoint p = let norm = pointNorm p in p.x <- p.x /. norm; p.y <- p.y /. norm; p.z <- p.z /. norm let normalizePoints arr = Array.iter normalizePoint arr; arr let max (x : float) y = if x < y then y else x let maxPoints arr = let m = { x = -2.; y = -2.; z = -2. } in Array.iter (fun p -> m.x <- max m.x p.x; m.y <- max m.y p.y; m.z <- max m.z p.z) arr; m let benchmark n = print_endline (toString (maxPoints (normalizePoints (makePoints n)))) let runBenchmark () = Gc.compact (); for n = 1 to 5 do printf "Run #%d\n%!" n; let t1 = Sys.time () in benchmark 5000000; let t2 = Sys.time () in printf "Time: %f\n%!" (t2 -. t1) done let () = runBenchmark ()