[MLton-commit] r5054

Vesa Karvonen vesak at mlton.org
Fri Jan 12 04:35:39 PST 2007


Initial commit of a lib of misc utils to be refactored.
----------------------------------------------------------------------

A   mltonlib/trunk/com/ssh/misc-util/unstable/sorted-list.sml

----------------------------------------------------------------------

Added: mltonlib/trunk/com/ssh/misc-util/unstable/sorted-list.sml
===================================================================
--- mltonlib/trunk/com/ssh/misc-util/unstable/sorted-list.sml	2007-01-12 12:35:12 UTC (rev 5053)
+++ mltonlib/trunk/com/ssh/misc-util/unstable/sorted-list.sml	2007-01-12 12:35:32 UTC (rev 5054)
@@ -0,0 +1,142 @@
+(* Copyright (C) 2007 SSH Communications Security, Helsinki, Finland
+ *
+ * This code is released under the MLton license, a BSD-style license.
+ * See the LICENSE file or http://mlton.org/License for details.
+ *)
+
+(*
+ * Operations on sorted (or ordered) lists.  The provided signature is not
+ * type safe meaning that it is possible to apply these operations to
+ * unsorted lists as well as lists sorted with a different compare
+ * function.
+ *)
+
+structure SortedList :> sig
+   type 'a policy
+   type 'a card = {1 : 'a policy, n : 'a policy} -> 'a policy
+   (**
+    * Cardinality policy is specified as either {#1} or {#n}.  {#1}
+    * means that a sorted list has at most 1 element of any value,
+    * while {#n} means that a list may have any number of equal values.
+    *)
+
+   val insert : 'a card -> 'a Cmp.t -> 'a -> 'a List.t UnOp.t
+      (** {insert #? cmp x xs = merge #? cmp ([x], xs)} *)
+
+   val isSorted : 'a card -> 'a Cmp.t -> 'a List.t UnPr.t
+   (**
+    * Returns true iff the list is sorted to the specified cardinality and
+    * ordering.
+    *)
+
+   val merge : 'a card -> 'a Cmp.t -> 'a List.t BinOp.t
+   (**
+    * Merges two lists sorted to the specified cardinality and ordering.
+    *
+    * It is guaranteed that in {merge #n cmp (l, r)} elements from the
+    * list {l} appear before equal elements from the list {r}.
+    *)
+
+   val remove : 'a card -> 'a Cmp.t -> 'a -> 'a List.t UnOp.t
+   (**
+    * Removes the specified cardinality of elements that compare equal to
+    * the specified element from the sorted list.
+    *)
+
+   val stableSort : 'a card -> 'a Cmp.t -> 'a List.t UnOp.t
+   (**
+    * Sorts the given list to the specified cardinality and ordering.
+    *
+    * It is guaranteed that the relative ordering of equal elements is
+    * retained.
+    *)
+end = struct
+   type 'a policy = {cond : Order.t UnPr.t,
+                     cont : 'a List.t Sq.t UnOp.t UnOp.t,
+                     dups : 'a * 'a List.t -> 'a List.t}
+   type 'a card = {1 : 'a policy, n : 'a policy} -> 'a policy
+
+   fun P m (c : 'a card) =
+       {1 = {cond = LESS <\ op =,
+             cont = const id,
+             dups = Pair.snd},
+        n = {cond = GREATER <\ op <>,
+             cont = id,
+             dups = op ::}} >| c >| m
+
+   fun isSorted card compare = let
+      fun lp [] = true
+        | lp [_] = true
+        | lp (x1::(xs as x2::_)) =
+          P #cond card (compare (x1, x2))
+          andalso lp xs
+   in
+      lp
+   end
+
+   fun revMerge' #? compare (xs, ys) = let
+      fun lp ([], ys, zs) = (ys, zs)
+        | lp (xs, [], zs) = (xs, zs)
+        | lp (x::xs, y::ys, zs) =
+          case compare (x, y) of
+             LESS => lp (xs, y::ys, x::zs)
+           | EQUAL => lp (xs, P #dups #? (y, ys), x::zs)
+           | GREATER => lp (x::xs, ys, y::zs)
+   in
+      lp (xs, ys, [])
+   end
+
+   fun merge #? ? = List.revAppend o Pair.swap o revMerge' #? ?
+
+   fun insert #? compare x xs = merge #? compare ([x], xs)
+
+   fun remove #? compare x ys = let
+      fun lp (zs, []) = (zs, [])
+        | lp (zs, y::ys) =
+          case compare (x, y) of
+             LESS => (zs, y::ys)
+           | EQUAL => P #cont #? lp (zs, ys)
+           | GREATER => lp (y::zs, ys)
+   in
+      List.revAppend (lp ([], ys))
+   end
+
+   (*
+    * This is an optimized implementation of merge sort that tries to
+    * avoid unnecessary list reversals.  This is done by performing
+    * reverse merges and flipping the compare direction as appropriate.
+    *)
+   fun stableSort #? compare = let
+      fun revOdd (w, l) = if Word.isEven w then l else rev l
+      fun merge r =
+          List.revAppend o (if Word.isOdd r then revMerge' #? compare
+                            else revMerge' #? (compare o Pair.swap) o Pair.swap)
+      val finish =
+          fn [] => []
+           | e::es =>
+             revOdd
+                (foldl
+                    (fn ((r1, l1), (r0, l0)) =>
+                        (r1+0w1, merge (r1+0w1) (revOdd (r1-r0, l0), l1)))
+                    e es)
+      fun build (stack as ((r0, l0)::(r1, l1)::rest)) =
+          if r0 <> r1 then push stack
+          else build ((r1+0w1, merge (r1+0w1) (l0, l1))::rest)
+        | build stack = push stack
+      and push stack =
+          fn [] => finish stack
+           | x::xs => let
+             fun lp y ys =
+                 fn [] => finish ((0w1, y::ys)::stack)
+                  | x::xs =>
+                    case compare (x, y) of
+                       LESS => build ((0w1, y::ys)::stack) (x::xs)
+                     | EQUAL => lp x (P #dups #? (y, ys)) xs
+                     | GREATER => lp x (y::ys) xs
+          in
+             lp x [] xs
+          end
+   in
+      push []
+   end
+end


Property changes on: mltonlib/trunk/com/ssh/misc-util/unstable/sorted-list.sml
___________________________________________________________________
Name: svn:eol-style
   + native




More information about the MLton-commit mailing list