1 (* Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
4 * MLton is released under a BSD-style license.
5 * See the file MLton-LICENSE for details.
10 val unsafeSub: 'a t * int -> 'a
18 fun unfold (n, a, f) = unfoldi (n, a, f o #2)
20 fun tabulate (n, f) = #1 (unfoldi (n, (), fn (i, ()) => (f i, ())))
23 tabulate (Pervasive.Array.length a, fn i => Pervasive.Array.sub (a, i))
26 Pervasive.Array.tabulate (length v, fn i => sub (v, i))
28 datatype ('a, 'b) continue =
37 then Error.bug "Vector.first"
41 fun fold' (v, start, b, f, g) =
48 case f (i, unsafeSub (v, i), b) of
49 Continue b => loop (i + 1, b)
52 if 0 <= start andalso start <= n
54 else Error.bug "Vector.fold'"
57 fun foldFrom (v, start, b, f) =
59 fn (_, a, b) => Continue (f (a, b)),
62 fun fold (a, b, f) = foldFrom (a, 0, b, f)
64 fun isEmpty a = 0 = length a
66 fun dropPrefix (v, n) = tabulate (length v - n, fn i => sub (v, i + n))
68 fun dropSuffix (v, n) = tabulate (length v - n, fn i => sub (v, i))
70 fun new (n, x) = tabulate (n, fn _ => x)
72 fun mapi (a, f) = tabulate (length a, fn i => f (i, unsafeSub (a, i)))
74 fun map (v, f) = mapi (v, f o #2)
76 fun copy v = map (v, fn x => x)
78 fun existsR (v, start, stop, f) =
80 fn (i, a, ()) => if i = stop
87 fun foldi (v, b, f) = fold' (v, 0, b, Continue o f, fn b => b)
91 fn (i, a, ()) => (case f (i, a) of
96 fun loop (v, f, g) = loopi (v, f o #2, g)
105 (case f (sub (v, i)) of
107 | SOME b => SOME (i, b))
119 fun fromListMap (l, f) =
123 tabulate (List.length l, fn _ =>
125 [] => Error.bug "Vector.fromListMap"
126 | x :: l => (r := l; f x))
129 fun fromList l = fromListMap (l, fn x => x)
131 fun foldr2 (a, a', b, f) =
138 else loop (i - 1, f (unsafeSub (a, i), unsafeSub (a', i), b))
142 else Error.bug "Vector.foldr2"
145 fun foldi2From (a, a', start, b, f) =
152 else loop (i + 1, f (i, unsafeSub (a, i), unsafeSub (a', i), b))
154 if n = n' andalso 0 <= start andalso start <= n
156 else Error.bug "Vector.foldi2From"
159 fun foldi2 (a, a', b, f) = foldi2From (a, a', 0, b, f)
161 fun foreachi2 (v, v', f) =
162 foldi2 (v, v', (), fn (i, x, x', ()) => f (i, x, x'))
164 fun fold2 (a, a', b, f) =
165 foldi2 (a, a', b, fn (_, x, x', b) => f (x, x', b))
167 fun fold3From (a, a', a'', start, b, f) =
175 else loop (i + 1, f (unsafeSub (a, i),
180 if n = n' andalso n = n'' andalso 0 <= start andalso start <= n
182 else Error.bug "Vector.fold3From"
185 fun fold3 (a, a', a'', b, f) = fold3From (a, a', a'', 0, b, f)
187 fun foreachR (v, start, stop, f: 'a -> unit) =
188 if 0 <= start andalso start <= stop andalso stop <= length v
191 fun step (i, a, ()) =
194 else (f a; Continue ())
196 fold' (v, start, (), step, fn () => ())
198 else Error.bug "Vector.foreachR"
200 fun foreach2 (a, a', f) =
201 fold2 (a, a', (), fn (x, x', ()) => f (x, x'))
203 fun forall2 (v, v', f) =
208 orelse (f (sub (v, i), sub (v', i))
209 andalso loop (i + 1))
213 else Error.bug "Vector.forall2"
216 fun foreach3 (v1, v2, v3, f: 'a * 'b * 'c -> unit) =
220 if n = length v2 andalso n = length v3
222 else Error.bug "Vector.foreach3"
226 else (f (sub (v1, i), sub (v2, i), sub (v3, i))
232 fun foreachi (a, f) = foldi (a, (), fn (i, x, ()) => f (i, x))
234 fun foreach (a, f) = foreachi (a, f o #2)
236 fun 'a peeki (v, f) =
253 fun peek (a, f) = Option.map (peeki (a, f o #2), #2)
255 fun existsi (a, f) = isSome (peeki (a, f))
257 fun exists (a, f) = existsi (a, f o #2)
259 fun contains (v, a, f) = exists (v, fn a' => f (a, a'))
261 fun foralli (a, f) = not (existsi (a, not o f))
263 fun forall (a, f) = foralli (a, f o #2)
265 fun equals (a, a', equals) =
267 andalso foralli (a, fn (i, x) => equals (x, unsafeSub (a', i)))
269 fun foldri (a, b, f) =
270 Int.foldDown (0, length a, b, fn (i, b) => f (i, unsafeSub (a, i), b))
272 fun foldr (a, b, f) =
273 foldri (a, b, fn (_, a, b) => f (a, b))
275 fun foreachri (a, f) = foldri (a, (), fn (i, x, ()) => f (i, x))
277 fun foreachr (a, f) = foreachri (a, f o #2)
279 fun toList a = foldr (a, [], op ::)
281 fun toListMap (a, f) = foldr (a, [], fn (a, ac) => f a :: ac)
283 fun layout l v = Layout.tuple (toListMap (v, l))
285 fun toString xToString l =
286 Layout.toString (layout (Layout.str o xToString) l)
288 fun new0 () = tabulate (0, fn _ => Error.bug "Vector.new0")
290 fun new1 x = tabulate (1, fn _ => x)
292 fun new2 (x0, x1) = tabulate (2, fn 0 => x0 | 1 => x1 | _ => Error.bug "Vector.new2")
294 fun new3 (x0, x1, x2) =
299 | _ => Error.bug "Vector.new3")
301 fun new4 (x0, x1, x2, x3) =
307 | _ => Error.bug "Vector.new4")
309 fun new5 (x0, x1, x2, x3, x4) =
316 | _ => Error.bug "Vector.new5")
318 fun new6 (x0, x1, x2, x3, x4, x5) =
326 | _ => Error.bug "Vector.new6")
328 fun unzip (a: ('a * 'b) t) = (map (a, #1), map (a, #2))
330 fun unzip3 (a: ('a * 'b * 'c) t) = (map (a, #1), map (a, #2), map (a, #3))
337 tabulate (n, fn i => unsafeSub (v, n1 - i))
340 fun fromListRev l = rev (fromList l)
342 fun mapAndFold (v, b, f) =
345 val v = map (v, fn x =>
347 val (c, b) = f (x, !r)
354 fun map2i (v, v', f) =
359 then tabulate (n, fn i => f (i, unsafeSub (v, i), unsafeSub (v', i)))
360 else Error.bug "Vector.map2i"
363 fun map2 (v, v', f) = map2i (v, v', fn (_, x, x') => f (x, x'))
365 fun map2AndFold (v, v', b, f) =
369 map2 (v, v', fn (x, x') =>
371 val (y, b) = f (x, x', !r)
378 fun map3 (v1, v2, v3, f) =
382 if n = length v2 andalso n = length v3
383 then tabulate (n, fn i => f (unsafeSub (v1, i),
386 else Error.bug "Vector.map3"
389 fun zip (v, v') = map2 (v, v', fn z => z)
395 val b = mapi (fn x =>
398 val _ = if isSome b then n := 1 + !n else ()
403 case unsafeSub (b, i) of
405 | SOME b => (r := i + 1; b)
406 in tabulate (!n, fn _ => loop (!r))
409 fun keepAllMapi (a, f) = doit (f, fn f => mapi (a, f))
410 fun keepAllMap2i (a, b, f) = doit (f, fn f => map2i (a, b, f))
413 fun keepAllMap (v, f) = keepAllMapi (v, f o #2)
415 fun keepAllMap2 (v, v', f) = keepAllMap2i (v, v', fn (_, x, x') => f (x, x'))
417 fun keepAllSome v = keepAllMap (v, fn a => a)
419 fun keepAll (v, f) = keepAllMap (v, fn a => if f a then SOME a else NONE)
421 fun compare (v, v', comp) =
427 (Int.compare (n, n'), fn () =>
434 (comp (unsafeSub (v, i), unsafeSub (v', i)), fn () =>
441 fun toListRev v = fold (v, [], op ::)
448 then Error.bug "Vector.last"
449 else unsafeSub (v, n - 1)
452 fun tabulator (n: int, f: ('a -> unit) -> unit) =
454 val a = Pervasive.Array.array (n, NONE)
462 then Error.bug "Vector.tabulator: too many elements"
463 else (Pervasive.Array.update (a, i, SOME x)
468 then Error.bug "Vector.tabulator: not enough elements"
469 else tabulate (n, fn i => valOf (Pervasive.Array.sub (a, i)))
472 fun 'a concat (vs: 'a t list): 'a t =
477 val n = List.fold (vs, 0, fn (v, s) => s + length v)
479 #1 (unfold (n, (0, v, vs'),
481 fun loop (i, v, vs) =
483 then (sub (v, i), (i + 1, v, vs))
486 [] => Error.bug "Vector.concat"
487 | v :: vs => loop (0, v, vs)
493 if 0 = length vs then
497 val n = fold (vs, 0, fn (v, s) => s + length v)
498 fun state i = (i, sub (vs, i), 0)
500 #1 (unfold (n, state 0,
504 (sub (v, j), (i, v, j + 1))
516 then Error.bug "Vector.splitLast"
517 else (tabulate (n - 1, fn i => unsafeSub (v, i)),
518 unsafeSub (v, n - 1))
521 fun isSortedRange (v: 'a t,
524 le : 'a * 'a -> bool): bool =
526 ("Vector.isSortedRange", fn () =>
527 0 <= start andalso start <= stop andalso stop <= length v)
533 orelse let val cur = sub (v, i)
536 andalso loop (i + 1, cur)
538 in loop (start + 1, sub (v, start))
541 fun isSorted (v, op <=) = isSortedRange (v, 0, length v, op <=)
545 fn (i, a, _) => if f (i, a) then Done (SOME i) else Continue (),
548 fun index (v, f) = indexi (v, f o #2)
550 fun indices (a: bool t): int t =
551 keepAllMapi (a, fn (i, b) => if b then SOME i else NONE)
554 Trace.trace ("Vector.indices", layout Bool.layout, layout Int.layout)
557 fun isSubsequence (va, vb, f) =
567 andalso if f (a, sub (vb, ib))
568 then loop (ia + 1, ib + 1)
577 fun removeFirst (v, f) =
580 val v = keepAll (v, fn a =>
585 val _ = if !seen then () else Error.bug "Vector.removeFirst"
590 fun partitioni (v, f) =
593 val v' = mapi (v, fn (i, x) =>
596 val _ = if b then n := 1 + !n else ()
603 case unsafeSub (v', i) of
607 val yes = tabulate (n, fn _ => loop true (!r))
609 val no = tabulate (length v - n, fn _ => loop false (!r))
614 fun partition (v, f) = partitioni (v, f o #2)
616 fun prefix (v, n) = tabulate (n, fn i => sub (v, i))
618 fun removeDuplicates (v, equals) =
619 keepAllMapi (v, fn (i, x) =>
620 if i > 0 andalso equals (x, sub (v, i - 1))
624 fun randomElement v = sub (v, Random.natLessThan (length v))