Import Debian changes 20180207-1
[hcoop/debian/mlton.git] / basis-library / arrays-and-vectors / sequence0.sml
CommitLineData
7f918cf1
CE
1(* Copyright (C) 2015,2017 Matthew Fluet.
2 * Copyright (C) 2014 Rob Simmons.
3 * Copyright (C) 2013 Matthew Fluet.
4 * Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
5 * Jagannathan, and Stephen Weeks.
6 * Copyright (C) 1997-2000 NEC Research Institute.
7 *
8 * MLton is released under a BSD-style license.
9 * See the file MLton-LICENSE for details.
10 *)
11
12functor PrimSequence (S: sig
13 type 'a sequence
14 type 'a elt
15 val copyUnsafe: 'a elt array * SeqIndex.int * 'a sequence * SeqIndex.int * SeqIndex.int -> unit
16 (* fromArray should be constant time. *)
17 val fromArray: 'a elt array -> 'a sequence
18 val isMutable: bool
19 val length: 'a sequence -> SeqIndex.int
20 val sameArray: 'a elt array * 'a sequence -> bool
21 val subUnsafe: 'a sequence * SeqIndex.int -> 'a elt
22 val uninitIsNop: 'a sequence -> bool
23 val uninitUnsafe: 'a sequence * SeqIndex.int -> unit
24 val updateUnsafe: 'a sequence * SeqIndex.int * 'a elt -> unit
25 end) :> PRIM_SEQUENCE where type 'a sequence = 'a S.sequence
26 where type 'a elt = 'a S.elt =
27 struct
28 structure Array = Primitive.Array
29
30 val op +? = SeqIndex.+?
31 val op + = SeqIndex.+
32 val op -? = SeqIndex.-?
33 val op < = SeqIndex.<
34 val op <= = SeqIndex.<=
35 val op > = SeqIndex.>
36 val op >= = SeqIndex.>=
37 val gtu = SeqIndex.gtu
38 val geu = SeqIndex.geu
39 val ! = Primitive.Ref.deref
40 val op := = Primitive.Ref.assign
41 fun (f o g) x = f (g x)
42
43 type 'a sequence = 'a S.sequence
44 type 'a elt = 'a S.elt
45
46 local
47 fun valOf x: Primitive.Int32.int = case x of SOME y => y | NONE => 0
48 fun doit (precision, fromInt, maxInt') =
49 if Primitive.Int32.>= (valOf SeqIndex.precision, precision)
50 then fromInt maxInt'
51 else SeqIndex.maxInt'
52 structure S =
53 Int_ChooseInt
54 (type 'a t = SeqIndex.int
55 val fInt8 = doit (valOf Primitive.Int8.precision,
56 SeqIndex.schckFromInt8,
57 Primitive.Int8.maxInt')
58 val fInt16 = doit (valOf Primitive.Int16.precision,
59 SeqIndex.schckFromInt16,
60 Primitive.Int16.maxInt')
61 val fInt32 = doit (valOf Primitive.Int32.precision,
62 SeqIndex.schckFromInt32,
63 Primitive.Int32.maxInt')
64 val fInt64 = doit (valOf Primitive.Int64.precision,
65 SeqIndex.schckFromInt64,
66 Primitive.Int64.maxInt')
67 val fIntInf = SeqIndex.maxInt')
68 in
69 val maxLen = S.f
70 end
71
72 fun length s = S.length s
73
74 fun unsafeArrayAlloc n = Array.allocUnsafe n
75 fun arrayAlloc n =
76 if Primitive.Controls.safe
77 andalso gtu (n, maxLen)
78 then raise Size
79 else unsafeArrayAlloc n
80 fun unsafeAlloc n = S.fromArray (unsafeArrayAlloc n)
81 fun alloc n = S.fromArray (arrayAlloc n)
82 val unsafeFromArray = S.fromArray
83 exception CreateAlreadyGotVector
84 exception CreateVectorNotFull
85 fun create n =
86 let
87 val a = arrayAlloc n
88 val subLim : SeqIndex.t ref = ref 0
89 fun sub i =
90 if Primitive.Controls.safe andalso geu (i, !subLim) then
91 raise Subscript
92 else
93 Array.subUnsafe (a, i)
94 val updateLim : SeqIndex.t ref = ref 0
95 fun update (i, x) =
96 if Primitive.Controls.safe andalso geu (i, !updateLim) then
97 if i = !updateLim andalso i < n then
98 (Array.updateUnsafe (a, i, x);
99 subLim := i + 1;
100 updateLim := i + 1)
101 else
102 raise Subscript
103 else
104 Array.updateUnsafe (a, i, x)
105 val gotIt = ref false
106 fun done () =
107 if !gotIt then
108 raise CreateAlreadyGotVector
109 else
110 if n = !updateLim then
111 (gotIt := true;
112 updateLim := 0;
113 S.fromArray a)
114 else
115 raise CreateVectorNotFull
116 in
117 {done = done,
118 sub = sub,
119 update = update}
120 end
121
122 fun unfoldi (n, b, f) =
123 let
124 val a = arrayAlloc n
125 fun loop (i, b) =
126 if i >= n
127 then b
128 else
129 let
130 val (x, b) = f (i, b)
131 val () = Array.updateUnsafe (a, i, x)
132 in
133 loop (i +? 1, b)
134 end
135 val b = loop (0, b)
136 in
137 (S.fromArray a, b)
138 end
139
140 fun unfold (n, b, f) = unfoldi (n, b, f o #2)
141
142 fun tabulate (n, f) =
143 #1 (unfoldi (n, (), fn (i, ()) => (f i, ())))
144
145 fun new (n, x) = tabulate (n, fn _ => x)
146
147 structure Slice =
148 struct
149 type 'a sequence = 'a sequence
150 type 'a elt = 'a elt
151 datatype 'a t = T of {seq: 'a sequence,
152 start: SeqIndex.int, len: SeqIndex.int}
153 type 'a slice = 'a t
154
155 fun length (T {len, ...}) = len
156 fun unsafeSub (T {seq, start, ...}, i) =
157 S.subUnsafe (seq, start +? i)
158 fun sub (sl as T {len, ...}, i) =
159 if Primitive.Controls.safe andalso geu (i, len)
160 then raise Subscript
161 else unsafeSub (sl, i)
162 fun unsafeUpdate (T {seq, start, ...}, i, x) =
163 S.updateUnsafe (seq, start +? i, x)
164 fun update (sl as T {len, ...}, i, x) =
165 if Primitive.Controls.safe andalso geu (i, len)
166 then raise Subscript
167 else unsafeUpdate (sl, i, x)
168 fun uninitIsNop (T {seq, ...}) =
169 S.uninitIsNop seq
170 fun unsafeUninit (T {seq, start, ...}, i) =
171 S.uninitUnsafe (seq, start +? i)
172 fun uninit (sl as T {len, ...}, i) =
173 if Primitive.Controls.safe andalso geu (i, len)
174 then raise Subscript
175 else unsafeUninit (sl, i)
176 local
177 fun smallCopy {dst: 'a elt array, di: SeqIndex.int,
178 src: 'a sequence, si: SeqIndex.int,
179 len: SeqIndex.int,
180 overlap: unit -> bool} =
181 let
182 fun move i = Array.updateUnsafe (dst, di +? i, S.subUnsafe (src, si +? i))
183 val len = len -? 1
184 in
185 if overlap ()
186 then let
187 fun loop i =
188 if i < 0
189 then ()
190 else (move i; loop (i -? 1))
191 in
192 loop len
193 end
194 else let
195 fun loop i =
196 if i > len
197 then ()
198 else (move i; loop (i +? 1))
199 in
200 loop 0
201 end
202 end
203 val smallCopyLimit = 5
204 fun maybeSmallCopy {dst: 'a elt array, di: SeqIndex.int,
205 src: 'a sequence, si: SeqIndex.int,
206 len: SeqIndex.int,
207 overlap: unit -> bool} =
208 if len < smallCopyLimit
209 then smallCopy {dst = dst, di = di,
210 src = src, si = si,
211 len = len,
212 overlap = overlap}
213 else S.copyUnsafe (dst, di, src, si, len)
214 in
215 fun unsafeCopy {dst: 'a elt array, di: SeqIndex.int,
216 src = T {seq = src, start = si, len}} =
217 maybeSmallCopy {dst = dst, di = di,
218 src = src, si = si,
219 len = len,
220 overlap = fn () => false}
221 fun copy {dst: 'a elt array, di: SeqIndex.int,
222 src = T {seq = src, start = si, len}} =
223 if Primitive.Controls.safe
224 andalso (gtu (di, Array.length dst)
225 orelse gtu (di +? len, Array.length dst))
226 then raise Subscript
227 else let
228 fun overlap () =
229 S.sameArray (dst, src)
230 andalso si < di
231 andalso di <= si +? len
232 in
233 maybeSmallCopy {dst = dst, di = di,
234 src = src, si = si,
235 len = len,
236 overlap = overlap}
237 end
238 end
239 fun full (seq: 'a sequence) : 'a slice =
240 T {seq = seq, start = 0, len = S.length seq}
241 fun unsafeSubslice (T {seq, start, len}, start', len') =
242 T {seq = seq,
243 start = start +? start',
244 len = (case len' of
245 NONE => len -? start'
246 | SOME len' => len')}
247 fun unsafeSlice (seq, start, len) =
248 unsafeSubslice (full seq, start, len)
249 fun subslice (T {seq, start, len}, start', len') =
250 case len' of
251 NONE =>
252 if Primitive.Controls.safe
253 andalso gtu (start', len)
254 then raise Subscript
255 else T {seq = seq,
256 start = start +? start',
257 len = len -? start'}
258 | SOME len' =>
259 if Primitive.Controls.safe
260 andalso (gtu (start', len)
261 orelse gtu (len', len -? start'))
262 then raise Subscript
263 else T {seq = seq,
264 start = start +? start',
265 len = len'}
266 fun slice (seq: 'a sequence, start, len) =
267 subslice (full seq, start, len)
268 fun base (T {seq, start, len}) =
269 (seq, start, len)
270 fun isEmpty sl = length sl = 0
271 fun getItem (sl as T {seq, start, len}) =
272 if isEmpty sl
273 then NONE
274 else SOME (S.subUnsafe (seq, start),
275 T {seq = seq,
276 start = start +? 1,
277 len = len -? 1})
278 fun foldli f b (T {seq, start, len}) =
279 let
280 val min = start
281 val len = len -? 1
282 val max = start +? len
283 fun loop (i, b) =
284 if i > max then b
285 else loop (i +? 1, f (i -? min, S.subUnsafe (seq, i), b))
286 in loop (min, b)
287 end
288 fun foldri f b (T {seq, start, len}) =
289 let
290 val min = start
291 val len = len -? 1
292 val max = start +? len
293 fun loop (i, b) =
294 if i < min then b
295 else loop (i -? 1, f (i -? min, S.subUnsafe (seq, i), b))
296 in loop (max, b)
297 end
298 local
299 fun make foldi f b sl = foldi (fn (_, x, b) => f (x, b)) b sl
300 in
301 fun foldl f = make foldli f
302 fun foldr f = make foldri f
303 end
304 fun appi f sl = foldli (fn (i, x, ()) => f (i, x)) () sl
305 fun app f sl = appi (f o #2) sl
306 fun mapi f (T {seq, start, len}) =
307 tabulate (len, fn i => f (i, S.subUnsafe (seq, start +? i)))
308 fun map f sl = mapi (f o #2) sl
309 fun findi p (T {seq, start, len}) =
310 let
311 val min = start
312 val len = len -? 1
313 val max = start +? len
314 fun loop i =
315 if i > max
316 then NONE
317 else let val z = (i -? min, S.subUnsafe (seq, i))
318 in if p z
319 then SOME z
320 else loop (i +? 1)
321 end
322 in loop min
323 end
324 fun find p sl =
325 case findi (p o #2) sl of
326 NONE => NONE
327 | SOME (_, x) => SOME x
328 fun existsi p sl =
329 case findi p sl of
330 NONE => false
331 | SOME _ => true
332 fun exists p sl = existsi (p o #2) sl
333 fun alli p sl = not (existsi (not o p) sl)
334 fun all p sl = alli (p o #2) sl
335 fun collate cmp (T {seq = seq1, start = start1, len = len1},
336 T {seq = seq2, start = start2, len = len2}) =
337 let
338 val min1 = start1
339 val min2 = start2
340 val max1 = start1 +? len1
341 val max2 = start2 +? len2
342 fun loop (i, j) =
343 case (i >= max1, j >= max2) of
344 (true, true) => EQUAL
345 | (true, false) => LESS
346 | (false, true) => GREATER
347 | (false, false) =>
348 (case cmp (S.subUnsafe (seq1, i),
349 S.subUnsafe (seq2, j)) of
350 EQUAL => loop (i +? 1, j +? 1)
351 | ans => ans)
352 in loop (min1, min2)
353 end
354 fun sequence (sl as T {seq, start, len}): 'a sequence =
355 if S.isMutable orelse (start <> 0 orelse len <> S.length seq)
356 then let
357 val a = arrayAlloc len
358 in
359 S.copyUnsafe (a, 0, seq, start, len)
360 ; S.fromArray a
361 end
362 else seq
363 fun append (sl1: 'a slice, sl2: 'a slice): 'a sequence =
364 if length sl1 = 0
365 then sequence sl2
366 else if length sl2 = 0
367 then sequence sl1
368 else
369 let
370 val (seq1, start1, len1) = base sl1
371 val (seq2, start2, len2) = base sl2
372 val n = len1 +? len2
373 val a = arrayAlloc n
374 in
375 S.copyUnsafe (a, 0, seq1, start1, len1)
376 ; S.copyUnsafe (a, len1, seq2, start2, len2)
377 ; S.fromArray a
378 end
379 fun split (T {seq, start, len}, i) =
380 (unsafeSlice (seq, start, SOME (i -? start)),
381 unsafeSlice (seq, i, SOME (len -? (i -? start))))
382 fun splitl f (sl as T {seq, start, len}) =
383 let
384 val stop = start +? len
385 fun loop i =
386 if i >= stop
387 then i
388 else if f (S.subUnsafe (seq, i))
389 then loop (i +? 1)
390 else i
391 in split (sl, loop start)
392 end
393 fun splitr f (sl as T {seq, start, len}) =
394 let
395 fun loop i =
396 if i < start
397 then start
398 else if f (S.subUnsafe (seq, i))
399 then loop (i -? 1)
400 else i +? 1
401 in split (sl, loop (start +? len -? 1))
402 end
403 fun splitAt (T {seq, start, len}, i) =
404 if Primitive.Controls.safe andalso gtu (i, len)
405 then raise Subscript
406 else (unsafeSlice (seq, start, SOME i),
407 unsafeSlice (seq, start +? i, SOME (len -? i)))
408 fun dropl p s = #2 (splitl p s)
409 fun dropr p s = #1 (splitr p s)
410 fun takel p s = #1 (splitl p s)
411 fun taker p s = #2 (splitr p s)
412 fun position (eq: 'a elt * 'a elt -> bool)
413 (seq': 'a sequence)
414 (sl as T {seq, start, len}) =
415 let
416 val len' = S.length seq'
417 val max = start +? len -? len' +? 1
418 (* loop returns the index of the front of the suffix. *)
419 fun loop i =
420 if i >= max
421 then start +? len
422 else let
423 fun loop' j =
424 if j >= len'
425 then i
426 else if eq (S.subUnsafe (seq, i +? j),
427 S.subUnsafe (seq', j))
428 then loop' (j +? 1)
429 else loop (i +? 1)
430 in loop' 0
431 end
432 in split (sl, loop start)
433 end
434 fun span (eq: 'a sequence * 'a sequence -> bool)
435 (T {seq, start, ...},
436 T {seq = seq', start = start', len = len'}) =
437 if Primitive.Controls.safe andalso
438 (not (eq (seq, seq')) orelse start' +? len' < start)
439 then raise Span
440 else unsafeSlice (seq, start, SOME ((start' +? len') -? start))
441 end
442
443 local
444 fun make f seq = f (Slice.full seq)
445 fun make2 f (seq1, seq2) = f (Slice.full seq1, Slice.full seq2)
446 in
447 fun sub (seq, i) = Slice.sub (Slice.full seq, i)
448 fun unsafeSub (seq, i) = Slice.unsafeSub (Slice.full seq, i)
449 fun update (seq, i, x) = Slice.update (Slice.full seq, i, x)
450 fun unsafeUpdate (seq, i, x) = Slice.unsafeUpdate (Slice.full seq, i, x)
451 fun uninitIsNop seq = Slice.uninitIsNop (Slice.full seq)
452 fun uninit (seq, i) = Slice.uninit (Slice.full seq, i)
453 fun unsafeUninit (seq, i) = Slice.unsafeUninit (Slice.full seq, i)
454 fun copy {dst, di, src} = Slice.copy {dst = dst, di = di, src = Slice.full src}
455 fun unsafeCopy {dst, di, src} = Slice.unsafeCopy {dst = dst, di = di, src = Slice.full src}
456 fun appi f = make (Slice.appi f)
457 fun app f = make (Slice.app f)
458 fun mapi f = make (Slice.mapi f)
459 fun map f = make (Slice.map f)
460 fun foldli f b = make (Slice.foldli f b)
461 fun foldl f b = make (Slice.foldl f b)
462 fun foldri f b = make (Slice.foldri f b)
463 fun foldr f b = make (Slice.foldr f b)
464 fun findi p = make (Slice.findi p)
465 fun find p = make (Slice.find p)
466 fun existsi p = make (Slice.existsi p)
467 fun exists p = make (Slice.exists p)
468 fun alli p = make (Slice.alli p)
469 fun all p = make (Slice.all p)
470 fun collate cmp = make2 (Slice.collate cmp)
471 fun append seqs = make2 Slice.append seqs
472 fun duplicate seq = make Slice.sequence seq
473 end
474
475 end
476
477structure Primitive = struct
478open Primitive
479
480structure Array =
481 struct
482 local
483 structure P = PrimSequence (type 'a sequence = 'a array
484 type 'a elt = 'a
485 val sameArray = op =
486 val copyUnsafe = Primitive.Array.copyArrayUnsafe
487 val fromArray = fn a => a
488 val isMutable = true
489 val length = Primitive.Array.length
490 val subUnsafe = Primitive.Array.subUnsafe
491 val uninitIsNop = Primitive.Array.uninitIsNop
492 val uninitUnsafe = Primitive.Array.uninitUnsafe
493 val updateUnsafe = Primitive.Array.updateUnsafe)
494 in
495 open P
496 type 'a array = 'a array
497 structure Slice =
498 struct
499 open Slice
500 fun vector sl =
501 let
502 val a = unsafeAlloc (length sl)
503 val () = unsafeCopy {dst = a, di = 0, src = sl}
504 in
505 Vector.fromArrayUnsafe a
506 end
507 fun modifyi f sl =
508 appi (fn (i, x) => unsafeUpdate (sl, i, f (i, x))) sl
509 fun modify f sl = modifyi (fn (_, x) => f x) sl
510 end
511 fun vector s = Slice.vector (Slice.full s)
512 fun modifyi f s = Slice.modifyi f (Slice.full s)
513 fun modify f s = Slice.modify f (Slice.full s)
514 end
515 structure Raw =
516 struct
517 type 'a rawarr = 'a Primitive.Array.Raw.rawarr
518
519 val length = Primitive.Array.Raw.length
520
521 val unsafeAlloc = Primitive.Array.Raw.allocUnsafe
522 fun alloc n =
523 if Primitive.Controls.safe
524 andalso SeqIndex.gtu (n, maxLen)
525 then raise Size
526 else unsafeAlloc n
527
528 val unsafeToArray = Primitive.Array.Raw.toArrayUnsafe
529
530 val uninitIsNop = Primitive.Array.Raw.uninitIsNop
531 val unsafeUninit = Primitive.Array.Raw.uninitUnsafe
532 fun uninit (a, i) =
533 if Primitive.Controls.safe andalso SeqIndex.geu (i, length a)
534 then raise Subscript
535 else unsafeUninit (a, i)
536
537 end
538 end
539
540structure Vector =
541 struct
542 local
543 exception Vector_uninitIsNop
544 exception Vector_uninitUnsafe
545 exception Vector_updateUnsafe
546 structure P = PrimSequence (type 'a sequence = 'a vector
547 type 'a elt = 'a
548 val copyUnsafe = Primitive.Array.copyVectorUnsafe
549 val fromArray = Primitive.Vector.fromArrayUnsafe
550 val isMutable = false
551 val length = Vector.length
552 val sameArray = fn _ => false
553 val subUnsafe = Primitive.Vector.subUnsafe
554 val uninitIsNop = fn _ =>
555 raise Vector_uninitIsNop
556 val uninitUnsafe = fn _ =>
557 raise Vector_uninitUnsafe
558 val updateUnsafe = fn _ =>
559 raise Vector_updateUnsafe)
560 in
561 open P
562 type 'a vector = 'a vector
563 fun updateVector (v, i, x) =
564 if Primitive.Controls.safe andalso SeqIndex.geu (i, length v)
565 then raise Subscript
566 else let
567 val a = Array.unsafeAlloc (length v)
568 val () = copy {dst = a, di = 0, src = v}
569 val () = Array.unsafeUpdate (a, i, x)
570 in
571 unsafeFromArray a
572 end
573 end
574 end
575
576end
577
578structure Array =
579 struct
580 type 'a array = 'a array
581 end
582structure Vector =
583 struct
584 type 'a vector = 'a vector
585 end