let rank arr =
  let arr = Array.copy arr in
  let arr = Array.mapi (fun i a -> a,i) arr in
  Array.sort (fun (a,_) (b,_) -> Pervasives.compare a b) arr;
  let g prev il ans =
    let count = List.length il in
    let n = count + (List.length ans) in
    let hi = Float.of_int n in
    let lo = Float.of_int (n - count + 1) in
    let rank = (hi +. lo) /. 2. in
    (List.map ~f:(fun i -> rank,i) il) @ ans
  in
  let f (prev, il, ans) (x,i) =   (* prev is the value that was equal *)
    let count = List.length il in (* il is list of original indices in
                                     reverse for items that were equal *)

    if count = 0 then (* ans is list of ranks and original index pairs
                         in reverse *)

      x, [i], ans
    else if x = prev then
      x, i::il, ans
    else
      x, [i], g prev il ans
  in
  let prev,il,ans = Array.fold ~f ~init:(0.,[],[]) arr in
  let ans = g prev il ans in
  let ans = List.sort ~cmp:(fun (_,a) (_,b) -> Pervasives.compare a b) ans in
  Array.of_list (List.map ~f:fst ans)