Source file maybe_bound.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
open! Import

type interval_comparison =
  | Below_lower_bound
  | In_range
  | Above_upper_bound
[@@deriving sexp ~stackify, sexp_grammar, compare ~localize, hash]

[%%template
[@@@kind.default k = base_or_null]

type ('a : k) t =
  | Incl of 'a
  | Excl of 'a
  | Unbounded
[@@deriving sexp ~stackify, sexp_grammar, globalize]

let all (all_of_a : ('a List.t[@kind k])) : ('a t[@kind k]) list =
  (List.map [@kind k value_or_null]) all_of_a ~f:(fun a : ('a t[@kind k]) -> Incl a)
  @ (List.map [@kind k value_or_null]) all_of_a ~f:(fun a : ('a t[@kind k]) -> Excl a)
  @ [ (Unbounded : ('a t[@kind k])) ]
;;

let map (t : (_ t[@kind k])) ~f : (_ t[@kind k]) =
  match t with
  | Incl incl -> Incl (f incl)
  | Excl excl -> Excl (f excl)
  | Unbounded -> Unbounded
;;

let is_lower_bound (t : (_ t[@kind k])) ~of_:a ~compare =
  match t with
  | Incl incl -> compare incl a <= 0
  | Excl excl -> compare excl a < 0
  | Unbounded -> true
;;

let is_upper_bound (t : (_ t[@kind k])) ~of_:a ~compare =
  match t with
  | Incl incl -> compare a incl <= 0
  | Excl excl -> compare a excl < 0
  | Unbounded -> true
;;

let bounds_crossed ~(lower : ('a t[@kind k])) ~(upper : ('a t[@kind k])) ~compare =
  match lower with
  | Unbounded -> false
  | Incl lower | Excl lower ->
    (match upper with
     | Unbounded -> false
     | Incl upper | Excl upper -> compare lower upper > 0)
;;

let check_interval_exn ~lower ~upper ~compare =
  if (bounds_crossed [@kind k]) ~lower ~upper ~compare
  then failwith "Maybe_bound.compare_to_interval_exn: lower bound > upper bound"
;;

let compare_to_interval_exn ~lower ~upper a ~compare =
  (check_interval_exn [@kind k]) ~lower ~upper ~compare;
  if not ((is_lower_bound [@kind k]) lower ~of_:a ~compare)
  then Below_lower_bound
  else if not ((is_upper_bound [@kind k]) upper ~of_:a ~compare)
  then Above_upper_bound
  else In_range
;;

let interval_contains_exn ~lower ~upper a ~compare =
  match (compare_to_interval_exn [@kind k]) ~lower ~upper a ~compare with
  | In_range -> true
  | Below_lower_bound | Above_upper_bound -> false
;;]