Source file range.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
exception Modulo_is_invalid
exception Range_is_invalid
type 'a range =
[ `Range_inc of 'a * 'a
| `Range_exc of 'a * 'a
]
let map ~(f_inc : 'a * 'a -> 'b * 'b) ~(f_exc : 'a * 'a -> 'b * 'b)
(t : 'a range) : 'b range =
match t with
| `Range_inc (x, y) ->
let x, y = f_inc (x, y) in
`Range_inc (x, y)
| `Range_exc (x, y) ->
let x, y = f_exc (x, y) in
`Range_exc (x, y)
let int64_range_of_range (type a) ~(to_int64 : a -> int64) (x : a range) :
int64 range =
let f (x, y) = (to_int64 x, to_int64 y) in
map ~f_inc:f ~f_exc:f x
let int64_inc_range_of_range (type a) ~(to_int64 : a -> int64) (x : a range) :
int64 * int64 =
match x with
| `Range_inc (x, y) -> (to_int64 x, to_int64 y)
| `Range_exc (x, y) -> (to_int64 x, y |> to_int64 |> Int64.pred)
let int64_exc_range_of_range (type a) ~(to_int64 : a -> int64) (x : a range) :
int64 * int64 =
match x with
| `Range_inc (x, y) -> (to_int64 x, y |> to_int64 |> Int64.succ)
| `Range_exc (x, y) -> (to_int64 x, to_int64 y)
let inc_range_of_range (type a) ~(to_int64 : a -> int64)
~(of_int64 : int64 -> a) (x : a range) : a * a =
match x with
| `Range_inc (x, y) -> (x, y)
| `Range_exc (x, y) -> (x, y |> to_int64 |> Int64.pred |> of_int64)
let exc_range_of_range (type a) ~(to_int64 : a -> int64)
~(of_int64 : int64 -> a) (x : a range) : a * a =
match x with
| `Range_inc (x, y) -> (x, y |> to_int64 |> Int64.succ |> of_int64)
| `Range_exc (x, y) -> (x, y)
let join (type a) ~(to_int64 : a -> int64) ~(of_int64 : int64 -> a)
(x : a range) (y : a range) : a range option =
let x = int64_exc_range_of_range ~to_int64 x in
let y = int64_exc_range_of_range ~to_int64 y in
Time_slot.join x y
|> Option.map (fun (x, y) -> `Range_exc (of_int64 x, of_int64 y))
let is_valid (type a) ~(modulo : int64 option) ~(to_int64 : a -> int64)
(t : a range) : bool =
match modulo with
| None ->
let x, y = int64_exc_range_of_range ~to_int64 t in
x <= y
| Some _ -> true
module Flatten = struct
let flatten_into_seq (type a) ~(modulo : int64 option)
~(to_int64 : a -> int64) ~(of_int64 : int64 -> a) (t : a range) : a Seq.t
=
match t with
| `Range_inc (start, end_inc) -> (
let start = to_int64 start in
let end_inc = to_int64 end_inc in
if start <= end_inc then
Seq_utils.a_to_b_inc_int64 ~a:start ~b:end_inc |> Seq.map of_int64
else
match modulo with
| None -> raise Range_is_invalid
| Some modulo ->
if modulo <= 0L then raise Modulo_is_invalid
else
OSeq.append
(Seq_utils.a_to_b_exc_int64 ~a:start ~b:modulo)
(Seq_utils.a_to_b_inc_int64 ~a:0L ~b:end_inc)
|> Seq.map of_int64 )
| `Range_exc (start, end_exc) -> (
let start = to_int64 start in
let end_exc = to_int64 end_exc in
if start <= end_exc then
Seq_utils.a_to_b_exc_int64 ~a:start ~b:end_exc |> Seq.map of_int64
else
match modulo with
| None -> raise Range_is_invalid
| Some modulo ->
if modulo <= 0L then raise Modulo_is_invalid
else
OSeq.append
(Seq_utils.a_to_b_exc_int64 ~a:start ~b:modulo)
(Seq_utils.a_to_b_exc_int64 ~a:0L ~b:end_exc)
|> Seq.map of_int64 )
let flatten_into_list (type a) ~(modulo : int64 option)
~(to_int64 : a -> int64) ~(of_int64 : int64 -> a) (t : a range) : a list =
flatten_into_seq ~modulo ~to_int64 ~of_int64 t |> List.of_seq
end
module type B = sig
type t
val modulo : int64 option
val to_int64 : t -> int64
val of_int64 : int64 -> t
end
module type S = sig
type t
val int64_range_of_range : t range -> int64 range
val int64_inc_range_of_range : t range -> int64 * int64
val int64_exc_range_of_range : t range -> int64 * int64
val inc_range_of_range : t range -> t * t
val exc_range_of_range : t range -> t * t
val join : t range -> t range -> t range option
val is_valid : t range -> bool
module Flatten : sig
val flatten_into_seq : t range -> t Seq.t
val flatten_into_list : t range -> t list
end
end
module Make (B : B) : S with type t := B.t = struct
open B
let int64_range_of_range (x : t range) : int64 range =
int64_range_of_range ~to_int64 x
let int64_inc_range_of_range (x : t range) : int64 * int64 =
int64_inc_range_of_range ~to_int64 x
let int64_exc_range_of_range (x : t range) : int64 * int64 =
int64_exc_range_of_range ~to_int64 x
let inc_range_of_range (x : t range) : t * t =
inc_range_of_range ~to_int64 ~of_int64 x
let exc_range_of_range (x : t range) : t * t =
exc_range_of_range ~to_int64 ~of_int64 x
let join (x : t range) (y : t range) : t range option =
join ~to_int64 ~of_int64 x y
let is_valid (x : t range) : bool = is_valid ~modulo ~to_int64 x
module Flatten = struct
let flatten_into_seq (t : t range) : t Seq.t =
Flatten.flatten_into_seq ~modulo ~to_int64 ~of_int64 t
let flatten_into_list (t : t range) : t list =
Flatten.flatten_into_seq ~modulo ~to_int64 ~of_int64 t |> List.of_seq
end
end