Source file natural.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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

module type Array = sig

  type index

  type 'a t

  val empty : 'a t

  val singleton : 'a -> 'a t

  val extend : 'a t -> index -> (index -> 'a) -> 'a t

  val retract : 'a t -> index -> 'a t

  val contains : 'a t -> index -> bool

  val last : 'a t -> index option

  val set : 'a t -> index -> 'a -> unit

  val get : 'a t -> index -> 'a

end

module type S_no_zero = sig

  type t

  val one : t

  val maximum : t

  val succ : t -> t

  val pred : t -> t option

  val compare : t -> t -> int

  val equal : t -> t -> bool

  val less_than : t -> t -> bool

  val less_than_or_equal : t -> t -> bool

  val max : t -> t -> t

  val plus : t -> t -> t

  val pp : Format.formatter -> t -> unit

  module Map : Map.S with type key = t

  module Set : Set.S with type elt = t

  module Tbl : Hashtbl.S with type key = t

  module Array : Array with type index = t

end

module type S = sig

  include S_no_zero

  val zero : t

end

module IntOps = struct

  type t = int

  let compare (x : t) (y : t) =
    compare x y

  let equal (x : t) (y : t) =
    x = y

  let less_than (x : t) (y : t) =
    x < y

  let less_than_or_equal (x : t) (y : t) =
    x <= y

  let max (x : t) (y : t) =
    if x >= y then x
    else y

  let hash = Hashtbl.hash

  let pp ppf x = Format.pp_print_int ppf x

end

module IntMap = Map.Make(IntOps)

module IntSet = Set.Make(IntOps)

module IntTbl = Hashtbl.Make(IntOps)

module Array_zero_indexed = struct

  type index = int

  type 'a t = 'a array

  let empty = [| |]

  let singleton x = [| x |]

  let extend t idx init =
    let len = idx + 1 in
    let old_len = Array.length t in
    if old_len > idx then
      failwith "Natural.Array.extend: array already contains index";
    if old_len = 0 then begin
      Array.init len init
    end else begin
      let extended = Array.make len (t.(0)) in
      Array.blit t 0 extended 0 old_len;
      for i = old_len to idx do
        Array.unsafe_set extended i (init i)
      done;
      extended
    end

  let retract t idx =
    let old_len = Array.length t in
    if old_len <= idx then
      failwith "Natural.Array.retract: array already doesn't contain index";
    Array.sub t 0 idx

  let contains t idx =
    let len = Array.length t in
    idx < len

  let last t =
    let len = Array.length t in
    if len = 0 then None
    else Some (len - 1)

  let set t idx data =
    t.(idx) <- data

  let get t idx =
    t.(idx)

end

module Array_one_indexed = struct

  type index = int

  type 'a t = 'a array

  let empty = [| |]

  let singleton x = [| x |]

  let extend t idx init =
    let old_len = Array.length t in
    if old_len >= idx then
      failwith "Natural.Array.extend: array already contains index";
    if old_len = 0 then begin
      let initial = init 1 in
      let res = Array.make idx initial in
      for i = 1 to (idx - 1) do
        Array.unsafe_set res i (init (i + 1))
      done;
      res
    end else begin
      let extended = Array.make idx (t.(0)) in
      Array.blit t 0 extended 0 old_len;
      for i = old_len to (idx - 1) do
        Array.unsafe_set extended i (init (i + 1))
      done;
      extended
    end

  let retract t idx =
    let old_len = Array.length t in
    if old_len < idx then
      failwith "Natural.Array.retract: array already doesn't contain index";
    Array.sub t 0 (idx - 1)

  let contains t idx =
    let len = Array.length t in
    idx <= len

  let last t =
    let len = Array.length t in
    if len = 0 then None
    else Some len

  let set t idx data =
    t.(idx - 1) <- data

  let get t idx =
    t.(idx - 1)

end

module Nat = struct

  include IntOps

  let zero = 0

  let one = 1

  let maximum = max_int

  let succ t =
    if t = maximum then t
    else t + 1

  let pred t =
    if t = 0 then None
    else Some (t - 1)

  let plus t1 t2 =
    let res = t1 + t2 in
    if res < 0 then maximum
    else res

  module Map = IntMap

  module Set = IntSet

  module Tbl = IntTbl

  module Array = Array_zero_indexed

end

module Nat_no_zero = struct

  include IntOps

  let one = 1

  let maximum = max_int

  let succ t =
    if t = maximum then t
    else t + 1

  let pred t =
    if t = 1 then None
    else Some (t - 1)

  let plus t1 t2 =
    let res = t1 + t2 in
    if res < 0 then maximum
    else res

  module Map = IntMap

  module Set = IntSet

  module Tbl = IntTbl

  module Array = Array_one_indexed

end

module Make () = Nat

module Make_no_zero () = Nat_no_zero