• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

A Nix-friendly SQLite-enhanced fork of Flitter, a speedrunning split timer for Unix-style terminals


Commit MetaInfo

Révision11b06680b1e995070318ab534081c7cd1598e21d (tree)
l'heure2022-12-21 08:06:10
AuteurCorbin <cds@corb...>
CommiterCorbin

Message de Log

Factor out Welford's algorithm.

Change Summary

Modification

--- a/src/summary.ml
+++ b/src/summary.ml
@@ -7,33 +7,16 @@ type t = {
77 splits : (string * Duration.t list) array;
88 }
99
10-type welford = { n : int; m1 : float; m2 : float }
11-
12-let do_welford =
13- List.fold
14- ~f:(fun { n; m1; m2 } d ->
15- let delta = Float.of_int d -. m1 in
16- let dn = delta /. Float.of_int (n + 1) in
17- let t = delta *. dn *. Float.of_int n in
18- { n = n + 1; m1 = m1 +. dn; m2 = m2 +. t })
19- ~init:{ n = 0; m1 = 0.0; m2 = 0.0 }
20-
21-let mean { m1; _ } = m1
22-
23-let variance { n; m2; _ } =
24- if n < 2 then None else Some (m2 /. Float.of_int (n - 1))
25-
26-let stddev s = Option.value_map (variance s) ~default:0.0 ~f:Float.sqrt
2710 let best = List.fold ~f:Int.min ~init:Int.max_value
2811
2912 let print_summary_segment width segment times =
30- let w = do_welford times in
13+ let w = Welford.summarize_list times in
3114 (* NB: 12 digits is a reasonable width for durations; it would take over a
3215 week for a segment to surpass it! *)
3316 Printf.printf "%*s: %12s %12s %12s (best/mean/stddev)\n" (width + 2) segment
3417 (Duration.to_string (best times) 3)
35- (Duration.to_string (Float.to_int (mean w)) 3)
36- (Duration.to_string (Float.to_int (stddev w)) 3)
18+ (Duration.to_string (Float.to_int (Welford.mean w)) 3)
19+ (Duration.to_string (Float.to_int (Welford.stddev w)) 3)
3720
3821 let print_route (route : Route.t) =
3922 Printf.printf "Title: %s Category: %s" route.title route.category;
--- /dev/null
+++ b/src/welford.ml
@@ -0,0 +1,20 @@
1+open Core
2+
3+type t = { n : int; m1 : float; m2 : float }
4+
5+let empty = { n = 0; m1 = 0.0; m2 = 0.0 }
6+
7+let observe { n; m1; m2 } d =
8+ let delta = Float.of_int d -. m1 in
9+ let dn = delta /. Float.of_int (n + 1) in
10+ let t = delta *. dn *. Float.of_int n in
11+ { n = n + 1; m1 = m1 +. dn; m2 = m2 +. t }
12+
13+let summarize_list = List.fold ~f:observe ~init:empty
14+let summarize_array = Array.fold ~f:observe ~init:empty
15+let mean { m1 } = m1
16+
17+let variance { n; m2 } =
18+ if n < 2 then None else Some (m2 /. Float.of_int (n - 1))
19+
20+let stddev s = Option.value_map (variance s) ~default:0.0 ~f:Float.sqrt
--- /dev/null
+++ b/src/welford.mli
@@ -0,0 +1,28 @@
1+(* Welford's algorithm takes the mean and variance of a stream of inputs. This
2+ type holds a summary of observed inputs. *)
3+type t
4+
5+(* A summary with no observations. *)
6+val empty : t
7+
8+(* Observe an input. *)
9+val observe : t -> int -> t
10+
11+(* Observe a list of inputs. *)
12+val summarize_list : int list -> t
13+
14+(* Observe an array of inputs. *)
15+val summarize_array : int array -> t
16+
17+(* The mean value, or expected value, or average, of a stream. *)
18+val mean : t -> float
19+
20+(* The variance of a stream. Note that streams with very few samples do not
21+ have a meaningful variance. *)
22+val variance : t -> float option
23+
24+(* The standard deviation of a stream. When a stream is normally distributed,
25+ or as enough samples are taken for the Central Limit Theorem to apply, then
26+ this indicates how samples are distributed around the mean. When variance is
27+ undefined, the standard deviation is zero. *)
28+val stddev : t -> float