package incr_map
Helpers for incremental operations on map like data structures
Install
Dune Dependency
Authors
Maintainers
Sources
v0.17.0.tar.gz
sha256=91acc784e4760af8544c4504bee1a9f6d7385eb0620f8e56392cd193a250b7d2
doc/src/incr_map.erase_key/opaque_map.ml.html
Source file opaque_map.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
open! Core open Incremental.Let_syntax module Key = struct include Bignum include Bignum.Unstable let to_string s = (* It's important that different numbers serialize to different strings, since the partial render table uses the serialization as a virtual-dom key in a context which requires that all the keys be unique. Thus, we use [to_string_accurate] to ensure no loss of precision. *) to_string_accurate s ;; module Stable = struct module V1 = Bignum.Stable.V3 end end type 'a t = 'a Map.M(Key).t [@@deriving sexp, compare, equal, bin_io] module Stable = struct module V1 = struct include Comparable.Stable.V1.With_stable_witness.Make (struct type t = Bignum.Stable.V3.t [@@deriving bin_io, sexp, compare, stable_witness] type comparator_witness = Bignum.comparator_witness let comparator = Bignum.comparator end) type 'a t = 'a Map.t [@@deriving sexp, bin_io, diff ~stable_version:1, stable_witness] end end module Diff = Stable.V1.Diff let with_comparator x f = Incremental.bind (Incremental.freeze (Incremental.map x ~f:Map.comparator_s)) ~f ;; let nearest map k = ( Map.closest_key map `Less_than k |> Option.map ~f:snd , Map.closest_key map `Greater_than k |> Option.map ~f:snd ) ;; let ( + ) = Bignum.( + ) let ( - ) = Bignum.( - ) let ( / ) = Bignum.( / ) let ( < ) = Bignum.( < ) let ( > ) = Bignum.( > ) let zero = Bignum.zero let two = Bignum.one + Bignum.one let denom_rebalance_cutoff = Bigint.of_int 100_000_000 let separation = Bignum.of_int 100 let erase_key_incrementally (type key data res cmp) ?data_equal (map : ((key, data, cmp) Map.t, 'w) Incremental.t) ~(get : key:key -> data:data -> res) : (res t, 'incr_witness) Incremental.t = let module Acc = struct type t = { key_to_bignum : (key, Bignum.t, cmp) Map.t ; out : res Bignum.Map.t ; comparator : (key, cmp) Comparator.Module.t ; additions : (key * data) list ; removals : key list ; rebalance_necessary : bool } let empty cmp = { key_to_bignum = Map.empty cmp ; out = Bignum.Map.empty ; comparator = cmp ; additions = [] ; removals = [] ; rebalance_necessary = false } ;; let of_maps cmp ~key_to_bignum ~out = { key_to_bignum ; out ; comparator = cmp ; additions = [] ; removals = [] ; rebalance_necessary = false } ;; let add ~key ~data ({ key_to_bignum; out; _ } as t) = let bignum = match nearest key_to_bignum key with | None, None -> zero | None, Some lowest -> (* Round to a nearby integer so that we don't retain the potentially large fractional part of the lowest key. We assume that [separation > 1] so that we don't round to a number greater than [lowest]. *) Bignum.truncate (lowest - separation) | Some highest, None -> Bignum.truncate (highest + separation) | Some low, Some high -> let precise = (low + high) / two in let truncated = Bignum.truncate precise in if truncated > low && truncated < high then truncated else precise in let rebalance_necessary = t.rebalance_necessary || Bigint.(Bignum.den_as_bigint bignum > denom_rebalance_cutoff) in let key_to_bignum = Map.add_exn key_to_bignum ~key ~data:bignum in let out = Map.add_exn out ~key:bignum ~data:(get ~key ~data) in { t with key_to_bignum; out; rebalance_necessary } ;; let remove ~key ({ key_to_bignum; out; _ } as t) = let bignum = Map.find_exn key_to_bignum key in let key_to_bignum = Map.remove key_to_bignum key in let out = Map.remove out bignum in { t with key_to_bignum; out } ;; let update ~key ~data ({ key_to_bignum; out; _ } as t) = let bignum = Map.find_exn key_to_bignum key in let out = Map.set out ~key:bignum ~data:(get ~key ~data) in { t with key_to_bignum; out } ;; let add_all l acc = List.fold l ~init:acc ~f:(fun acc (key, data) -> add ~key ~data acc) ;; let process_removals_and_additions (module M : Comparator.S with type comparator_witness = cmp and type t = key) acc = let acc = List.fold acc.removals ~init:acc ~f:(fun acc key -> remove ~key acc) in let acc = let lower_than_lowest, rest = match Map.min_elt acc.key_to_bignum with | None -> [], acc.additions | Some (lowest, _) -> List.partition_tf acc.additions ~f:(fun (a, _) -> Int.(M.comparator.compare a lowest < 0)) in acc |> add_all lower_than_lowest |> add_all (List.rev rest) in { acc with removals = []; additions = [] } ;; let rebalance acc = let fresh = empty acc.comparator in let i = ref zero in let init = fresh.key_to_bignum, fresh.out in let key_to_bignum, out = Map.fold acc.key_to_bignum ~init ~f:(fun ~key ~data:prev_bignum (key_to_bignum, out) -> let prev_res = Map.find_exn acc.out prev_bignum in let k = !i in i := k + separation; Map.add_exn key_to_bignum ~key ~data:k, Map.add_exn out ~key:k ~data:prev_res) in of_maps acc.comparator ~key_to_bignum ~out ;; let finalize cmp acc = let acc = process_removals_and_additions cmp acc in if acc.rebalance_necessary then rebalance acc else acc ;; end in let%pattern_bind { Acc.out; _ } = with_comparator map (fun cmp -> Incr_map.unordered_fold ?data_equal ~init:(Acc.empty cmp) ~specialized_initial:(fun ~init data -> let i = ref zero in let init = init.key_to_bignum, init.out in let key_to_bignum, out = Map.fold data ~init ~f:(fun ~key ~data (key_to_bignum, out) -> let k = !i in i := k + separation; ( Map.add_exn key_to_bignum ~key ~data:k , Map.add_exn out ~key:k ~data:(get ~key ~data) )) in Acc.of_maps cmp ~key_to_bignum ~out) ~add:(fun ~key ~data acc -> { acc with additions = (key, data) :: acc.additions }) ~remove:(fun ~key ~data:_ acc -> { acc with removals = key :: acc.removals }) ~update:(fun ~key ~old_data:_ ~new_data:data acc -> Acc.update ~key ~data acc) ~finalize:(Acc.finalize cmp) map) in out ;; let empty = Bignum.Map.empty let of_list xs = Bignum.Map.of_alist_exn (List.mapi xs ~f:(fun i x -> Bignum.of_int i, x)) let of_array arr = Bignum.Map.of_sorted_array_unchecked (Array.mapi arr ~f:(fun i x -> Bignum.of_int i, x)) ;;
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>