let performance_curve ~scores ~labels =
  let n = Array.length scores in
  if n <> Array.length labels
  then
    invalid_argf
      "Biocaml_bin_pred.make_curve: scores and labels have different lengths (%d and %d)"
      n (Array.length labels) () ;
  let examples =
    let r = Array.map2_exn scores labels ~f:(fun x y -> x, y) in
    Array.sort ~cmp:(Fn.flip compare) r ;
    r
  in
  let np = Array.count labels ~f:ident in
  let nn = Array.count labels ~f:(fun x -> not x) in
  let initial = Float.infinity, { tp = 0 ; tn = nn ; fp = 0 ; fn = np } in
  let r = Array.create (n + 2) initial in
  for i = 0 to n - 1 do
    let score, label = examples.(i) in
    let m = snd r.(i) in
    let m' =
      if label then
        { m with tp = m.tp + 1 ; fn = m.fn - 1 }
      else
        { m with fp = m.fp + 1 ; tn = m.tn - 1 }
    in
    r.(i + 1) <- (score,m')
  done ;
  r.(n + 1) <- Float.neg_infinity, { tp = np ; tn = 0 ; fp = nn ; fn = 0 } ;
  r