package core_kernel

  1. Overview
  2. Docs
Industrial strength alternative to OCaml's standard library

Install

Dune Dependency

Authors

Maintainers

Sources

core_kernel-v0.15.0.tar.gz
sha256=34a0288f16027c6b90e4ad16cb5cc677d7063d310faf918748ce70f1745116c0

doc/src/core_kernel.int_set/int_set.ml.html

Source file int_set.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


open! Core
open! Import

module Range : sig
  (* A range represents a closed interval of integers *)

  type t = private
    { lo : int
    ; hi : int
    }

  (* Invariant: lo <= hi *)

  (** Create [t] from a range *)
  val make : int -> int -> t

  val to_string : t -> string

  (** [merge s t] merges mergeable ranges *)
  val merge : t -> t -> [ `Ok of t | `Lt_and_not_adjacent | `Gt_and_not_adjacent ]

  val contains : int -> t -> bool
end = struct
  type t =
    { lo : int
    ; hi : int
    }

  let make x y = if x <= y then { lo = x; hi = y } else { lo = y; hi = x }
  let to_string t = if t.lo = t.hi then Int.to_string t.lo else sprintf "%d-%d" t.lo t.hi

  (* on the number line, r1 is either on the left, on the right, or
     intersected with r2 *)
  let compare r1 r2 =
    if r1.hi < r2.lo - 1
    then `Lt_and_not_adjacent
    else if r1.lo > r2.hi + 1
    then `Gt_and_not_adjacent
    else `Mergeable
  ;;

  let merge r1 r2 =
    match compare r1 r2 with
    | `Lt_and_not_adjacent -> `Lt_and_not_adjacent
    | `Gt_and_not_adjacent -> `Gt_and_not_adjacent
    | `Mergeable -> `Ok { lo = Int.min r1.lo r2.lo; hi = Int.max r1.hi r2.hi }
  ;;

  let contains i r = r.lo <= i && i <= r.hi
end

type t = Range.t list

(* invariant : the elements of [t] must be pairwise discrete (not mergeable) and sorted
   in DECREASING order. *)

let empty = []
let to_string t = String.concat ~sep:"," (List.rev_map t ~f:Range.to_string)

let add_range t x y =
  (* note: not tail recursive *)
  let rec loop ranges to_add =
    match ranges with
    | r :: rest ->
      (* the following keeps the invariant: discrete + sorted *)
      (match Range.merge to_add r with
       | `Lt_and_not_adjacent -> r :: loop rest to_add
       | `Gt_and_not_adjacent -> to_add :: r :: rest
       | `Ok merged -> loop rest merged)
    | [] -> [ to_add ]
  in
  loop t (Range.make x y)
;;

let add t i = add_range t i i
let mem t i = List.exists t ~f:(fun x -> Range.contains i x)
let ranges t = List.map t ~f:(fun { Range.lo; hi } -> lo, hi)

let max t =
  match t with
  | [] -> None
  | { Range.hi; lo = _ } :: _ -> Some hi
;;

let min t =
  match List.last t with
  | None -> None
  | Some { Range.lo; hi = _ } -> Some lo
;;
OCaml

Innovation. Community. Security.