This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,86 @@
(** Functions for performing binary searches over ordered sequences given
[length] and [get] functions.
These functions can be specialized and added to a data structure using the functors
supplied in {{!Base.Binary_searchable}[Binary_searchable]} and described in
{{!Base.Binary_searchable_intf}[Binary_searchable_intf]}.
{2:examples Examples}
Below we assume that the functions [get], [length] and [compare] are in scope:
{[
(* Find the index of an element [e] in [t] *)
binary_search t ~get ~length ~compare `First_equal_to e;
(* Find the index where an element [e] should be inserted *)
binary_search t ~get ~length ~compare `First_greater_than_or_equal_to e;
(* Find the index in [t] where all elements to the left are less than [e] *)
binary_search_segmented t ~get ~length ~segment_of:(fun e' ->
if compare e' e <= 0 then `Left else `Right) `First_on_right
]} *)
open! Import
(** [binary_search ?pos ?len t ~length ~get ~compare which elt] takes [t] that is sorted
in increasing order according to [compare], where [compare] and [elt] divide [t] into
three (possibly empty) segments:
{v
| < elt | = elt | > elt |
v}
[binary_search] returns the index in [t] of an element on the boundary of segments
as specified by [which]. See the diagram below next to the [which] variants.
By default, [binary_search] searches the entire [t]. One can supply [?pos] or
[?len] to search a slice of [t].
[binary_search] does not check that [compare] orders [t], and behavior is
unspecified if [compare] doesn't order [t]. Behavior is also unspecified if
[compare] mutates [t]. *)
val binary_search
: ?pos:int
-> ?len:int
-> 't
-> length:('t -> int)
-> get:('t -> int -> 'elt)
-> compare:('elt -> 'key -> int)
-> [ `Last_strictly_less_than (** {v | < elt X | v} *)
| `Last_less_than_or_equal_to (** {v | <= elt X | v} *)
| `Last_equal_to (** {v | = elt X | v} *)
| `First_equal_to (** {v | X = elt | v} *)
| `First_greater_than_or_equal_to (** {v | X >= elt | v} *)
| `First_strictly_greater_than (** {v | X > elt | v} *)
]
-> 'key
-> int option
(** [binary_search_segmented ?pos ?len t ~length ~get ~segment_of which] takes a
[segment_of] function that divides [t] into two (possibly empty) segments:
{v
| segment_of elt = `Left | segment_of elt = `Right |
v}
[binary_search_segmented] returns the index of the element on the boundary of the
segments as specified by [which]: [`Last_on_left] yields the index of the last
element of the left segment, while [`First_on_right] yields the index of the first
element of the right segment. It returns [None] if the segment is empty.
By default, [binary_search] searches the entire [t]. One can supply [?pos] or
[?len] to search a slice of [t].
[binary_search_segmented] does not check that [segment_of] segments [t] as in the
diagram, and behavior is unspecified if [segment_of] doesn't segment [t]. Behavior
is also unspecified if [segment_of] mutates [t]. *)
val binary_search_segmented
: ?pos:int
-> ?len:int
-> 't
-> length:('t -> int)
-> get:('t -> int -> 'elt)
-> segment_of:('elt -> [ `Left | `Right ])
-> [ `Last_on_left | `First_on_right ]
-> int option