src/Tools/Metis/src/Useful.sml
author blanchet
Mon, 13 Sep 2010 21:24:10 +0200
changeset 39353 7f11d833d65b
parent 25430 372d6749f00e
parent 39349 2d0a4361c3ef
child 39408 65a379f4c8f3
permissions -rw-r--r--
merged
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
39348
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     1
(* ========================================================================= *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     2
(* ML UTILITY FUNCTIONS                                                      *)
39349
2d0a4361c3ef change license, with Joe Hurd's permission
blanchet
parents: 39348
diff changeset
     3
(* Copyright (c) 2001 Joe Hurd, distributed under the BSD License            *)
39348
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     4
(* ========================================================================= *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     5
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     6
structure Useful :> Useful =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     7
struct
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     8
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     9
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    10
(* Exceptions.                                                               *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    11
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    12
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    13
exception Error of string;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    14
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    15
exception Bug of string;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    16
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    17
fun errorToStringOption err =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    18
    case err of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    19
      Error message => SOME ("Error: " ^ message)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    20
    | _ => NONE;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    21
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    22
(*mlton
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    23
val () = MLton.Exn.addExnMessager errorToStringOption;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    24
*)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    25
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    26
fun errorToString err =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    27
    case errorToStringOption err of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    28
      SOME s => "\n" ^ s ^ "\n"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    29
    | NONE => raise Bug "errorToString: not an Error exception";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    30
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    31
fun bugToStringOption err =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    32
    case err of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    33
      Bug message => SOME ("Bug: " ^ message)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    34
    | _ => NONE;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    35
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    36
(*mlton
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    37
val () = MLton.Exn.addExnMessager bugToStringOption;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    38
*)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    39
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    40
fun bugToString err =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    41
    case bugToStringOption err of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    42
      SOME s => "\n" ^ s ^ "\n"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    43
    | NONE => raise Bug "bugToString: not a Bug exception";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    44
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    45
fun total f x = SOME (f x) handle Error _ => NONE;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    46
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    47
fun can f = Option.isSome o total f;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    48
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    49
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    50
(* Tracing.                                                                  *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    51
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    52
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    53
val tracePrint = ref print;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    54
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    55
fun trace mesg = !tracePrint mesg;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    56
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    57
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    58
(* Combinators.                                                              *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    59
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    60
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    61
fun C f x y = f y x;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    62
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    63
fun I x = x;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    64
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    65
fun K x y = x;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    66
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    67
fun S f g x = f x (g x);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    68
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    69
fun W f x = f x x;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    70
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    71
fun funpow 0 _ x = x
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    72
  | funpow n f x = funpow (n - 1) f (f x);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    73
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    74
fun exp m =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    75
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    76
      fun f _ 0 z = z
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    77
        | f x y z = f (m (x,x)) (y div 2) (if y mod 2 = 0 then z else m (z,x))
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    78
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    79
      f
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    80
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    81
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    82
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    83
(* Pairs.                                                                    *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    84
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    85
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    86
fun fst (x,_) = x;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    87
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    88
fun snd (_,y) = y;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    89
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    90
fun pair x y = (x,y);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    91
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    92
fun swap (x,y) = (y,x);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    93
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    94
fun curry f x y = f (x,y);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    95
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    96
fun uncurry f (x,y) = f x y;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    97
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    98
val op## = fn (f,g) => fn (x,y) => (f x, g y);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    99
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   100
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   101
(* State transformers.                                                       *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   102
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   103
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   104
val unit : 'a -> 's -> 'a * 's = pair;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   105
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   106
fun bind f (g : 'a -> 's -> 'b * 's) = uncurry g o f;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   107
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   108
fun mmap f (m : 's -> 'a * 's) = bind m (unit o f);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   109
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   110
fun mjoin (f : 's -> ('s -> 'a * 's) * 's) = bind f I;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   111
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   112
fun mwhile c b = let fun f a = if c a then bind (b a) f else unit a in f end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   113
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   114
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   115
(* Equality.                                                                 *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   116
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   117
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   118
val equal = fn x => fn y => x = y;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   119
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   120
val notEqual = fn x => fn y => x <> y;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   121
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   122
fun listEqual xEq =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   123
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   124
      fun xsEq [] [] = true
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   125
        | xsEq (x1 :: xs1) (x2 :: xs2) = xEq x1 x2 andalso xsEq xs1 xs2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   126
        | xsEq _ _ = false
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   127
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   128
      xsEq
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   129
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   130
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   131
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   132
(* Comparisons.                                                              *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   133
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   134
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   135
fun mapCompare f cmp (a,b) = cmp (f a, f b);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   136
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   137
fun revCompare cmp x_y =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   138
    case cmp x_y of LESS => GREATER | EQUAL => EQUAL | GREATER => LESS;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   139
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   140
fun prodCompare xCmp yCmp ((x1,y1),(x2,y2)) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   141
    case xCmp (x1,x2) of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   142
      LESS => LESS
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   143
    | EQUAL => yCmp (y1,y2)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   144
    | GREATER => GREATER;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   145
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   146
fun lexCompare cmp =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   147
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   148
      fun lex ([],[]) = EQUAL
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   149
        | lex ([], _ :: _) = LESS
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   150
        | lex (_ :: _, []) = GREATER
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   151
        | lex (x :: xs, y :: ys) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   152
          case cmp (x,y) of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   153
            LESS => LESS
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   154
          | EQUAL => lex (xs,ys)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   155
          | GREATER => GREATER
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   156
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   157
      lex
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   158
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   159
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   160
fun optionCompare _ (NONE,NONE) = EQUAL
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   161
  | optionCompare _ (NONE,_) = LESS
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   162
  | optionCompare _ (_,NONE) = GREATER
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   163
  | optionCompare cmp (SOME x, SOME y) = cmp (x,y);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   164
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   165
fun boolCompare (false,true) = LESS
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   166
  | boolCompare (true,false) = GREATER
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   167
  | boolCompare _ = EQUAL;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   168
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   169
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   170
(* Lists.                                                                    *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   171
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   172
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   173
fun cons x y = x :: y;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   174
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   175
fun hdTl l = (hd l, tl l);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   176
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   177
fun append xs ys = xs @ ys;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   178
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   179
fun singleton a = [a];
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   180
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   181
fun first f [] = NONE
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   182
  | first f (x :: xs) = (case f x of NONE => first f xs | s => s);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   183
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   184
fun maps (_ : 'a -> 's -> 'b * 's) [] = unit []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   185
  | maps f (x :: xs) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   186
    bind (f x) (fn y => bind (maps f xs) (fn ys => unit (y :: ys)));
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   187
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   188
fun mapsPartial (_ : 'a -> 's -> 'b option * 's) [] = unit []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   189
  | mapsPartial f (x :: xs) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   190
    bind
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   191
      (f x)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   192
      (fn yo =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   193
          bind
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   194
            (mapsPartial f xs)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   195
            (fn ys => unit (case yo of NONE => ys | SOME y => y :: ys)));
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   196
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   197
fun zipWith f =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   198
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   199
      fun z l [] [] = l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   200
        | z l (x :: xs) (y :: ys) = z (f x y :: l) xs ys
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   201
        | z _ _ _ = raise Error "zipWith: lists different lengths";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   202
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   203
      fn xs => fn ys => rev (z [] xs ys)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   204
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   205
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   206
fun zip xs ys = zipWith pair xs ys;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   207
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   208
fun unzip ab =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   209
    foldl (fn ((x, y), (xs, ys)) => (x :: xs, y :: ys)) ([], []) (rev ab);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   210
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   211
fun cartwith f =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   212
  let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   213
    fun aux _ res _ [] = res
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   214
      | aux xsCopy res [] (y :: yt) = aux xsCopy res xsCopy yt
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   215
      | aux xsCopy res (x :: xt) (ys as y :: _) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   216
        aux xsCopy (f x y :: res) xt ys
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   217
  in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   218
    fn xs => fn ys =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   219
       let val xs' = rev xs in aux xs' [] xs' (rev ys) end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   220
  end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   221
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   222
fun cart xs ys = cartwith pair xs ys;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   223
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   224
fun takeWhile p =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   225
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   226
      fun f acc [] = rev acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   227
        | f acc (x :: xs) = if p x then f (x :: acc) xs else rev acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   228
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   229
      f []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   230
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   231
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   232
fun dropWhile p =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   233
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   234
      fun f [] = []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   235
        | f (l as x :: xs) = if p x then f xs else l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   236
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   237
      f
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   238
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   239
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   240
fun divideWhile p =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   241
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   242
      fun f acc [] = (rev acc, [])
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   243
        | f acc (l as x :: xs) = if p x then f (x :: acc) xs else (rev acc, l)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   244
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   245
      f []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   246
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   247
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   248
fun groups f =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   249
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   250
      fun group acc row x l =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   251
          case l of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   252
            [] =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   253
            let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   254
              val acc = if null row then acc else rev row :: acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   255
            in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   256
              rev acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   257
            end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   258
          | h :: t =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   259
            let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   260
              val (eor,x) = f (h,x)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   261
            in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   262
              if eor then group (rev row :: acc) [h] x t
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   263
              else group acc (h :: row) x t
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   264
            end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   265
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   266
      group [] []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   267
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   268
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   269
fun groupsBy eq =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   270
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   271
      fun f (x_y as (x,_)) = (not (eq x_y), x)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   272
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   273
      fn [] => []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   274
       | h :: t =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   275
         case groups f h t of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   276
           [] => [[h]]
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   277
         | hs :: ts => (h :: hs) :: ts
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   278
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   279
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   280
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   281
  fun fstEq ((x,_),(y,_)) = x = y;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   282
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   283
  fun collapse l = (fst (hd l), map snd l);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   284
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   285
  fun groupsByFst l = map collapse (groupsBy fstEq l);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   286
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   287
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   288
fun groupsOf n =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   289
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   290
      fun f (_,i) = if i = 1 then (true,n) else (false, i - 1)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   291
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   292
      groups f (n + 1)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   293
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   294
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   295
fun index p =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   296
  let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   297
    fun idx _ [] = NONE
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   298
      | idx n (x :: xs) = if p x then SOME n else idx (n + 1) xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   299
  in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   300
    idx 0
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   301
  end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   302
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   303
fun enumerate l = fst (maps (fn x => fn m => ((m, x), m + 1)) l 0);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   304
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   305
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   306
  fun revDiv acc l 0 = (acc,l)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   307
    | revDiv _ [] _ = raise Subscript
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   308
    | revDiv acc (h :: t) n = revDiv (h :: acc) t (n - 1);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   309
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   310
  fun revDivide l = revDiv [] l;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   311
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   312
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   313
fun divide l n = let val (a,b) = revDivide l n in (rev a, b) end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   314
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   315
fun updateNth (n,x) l =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   316
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   317
      val (a,b) = revDivide l n
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   318
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   319
      case b of [] => raise Subscript | _ :: t => List.revAppend (a, x :: t)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   320
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   321
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   322
fun deleteNth n l =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   323
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   324
      val (a,b) = revDivide l n
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   325
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   326
      case b of [] => raise Subscript | _ :: t => List.revAppend (a,t)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   327
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   328
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   329
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   330
(* Sets implemented with lists.                                              *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   331
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   332
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   333
fun mem x = List.exists (equal x);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   334
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   335
fun insert x s = if mem x s then s else x :: s;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   336
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   337
fun delete x s = List.filter (not o equal x) s;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   338
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   339
fun setify s = rev (foldl (fn (v,x) => if mem v x then x else v :: x) [] s);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   340
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   341
fun union s t = foldl (fn (v,x) => if mem v t then x else v :: x) t (rev s);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   342
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   343
fun intersect s t =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   344
    foldl (fn (v,x) => if mem v t then v :: x else x) [] (rev s);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   345
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   346
fun difference s t =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   347
    foldl (fn (v,x) => if mem v t then x else v :: x) [] (rev s);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   348
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   349
fun subset s t = List.all (fn x => mem x t) s;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   350
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   351
fun distinct [] = true
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   352
  | distinct (x :: rest) = not (mem x rest) andalso distinct rest;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   353
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   354
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   355
(* Sorting and searching.                                                    *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   356
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   357
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   358
(* Finding the minimum and maximum element of a list, wrt some order. *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   359
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   360
fun minimum cmp =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   361
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   362
      fun min (l,m,r) _ [] = (m, List.revAppend (l,r))
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   363
        | min (best as (_,m,_)) l (x :: r) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   364
          min (case cmp (x,m) of LESS => (l,x,r) | _ => best) (x :: l) r
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   365
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   366
      fn [] => raise Empty
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   367
       | h :: t => min ([],h,t) [h] t
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   368
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   369
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   370
fun maximum cmp = minimum (revCompare cmp);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   371
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   372
(* Merge (for the following merge-sort, but generally useful too). *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   373
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   374
fun merge cmp =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   375
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   376
      fun mrg acc [] ys = List.revAppend (acc,ys)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   377
        | mrg acc xs [] = List.revAppend (acc,xs)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   378
        | mrg acc (xs as x :: xt) (ys as y :: yt) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   379
          (case cmp (x,y) of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   380
             GREATER => mrg (y :: acc) xs yt
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   381
           | _ => mrg (x :: acc) xt ys)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   382
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   383
      mrg []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   384
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   385
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   386
(* Merge sort (stable). *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   387
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   388
fun sort cmp =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   389
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   390
      fun findRuns acc r rs [] = rev (rev (r :: rs) :: acc)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   391
        | findRuns acc r rs (x :: xs) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   392
          case cmp (r,x) of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   393
            GREATER => findRuns (rev (r :: rs) :: acc) x [] xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   394
          | _ => findRuns acc x (r :: rs) xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   395
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   396
      fun mergeAdj acc [] = rev acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   397
        | mergeAdj acc (xs as [_]) = List.revAppend (acc,xs)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   398
        | mergeAdj acc (x :: y :: xs) = mergeAdj (merge cmp x y :: acc) xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   399
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   400
      fun mergePairs [xs] = xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   401
        | mergePairs l = mergePairs (mergeAdj [] l)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   402
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   403
      fn [] => []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   404
       | l as [_] => l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   405
       | h :: t => mergePairs (findRuns [] h [] t)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   406
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   407
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   408
fun sortMap _ _ [] = []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   409
  | sortMap _ _ (l as [_]) = l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   410
  | sortMap f cmp xs =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   411
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   412
      fun ncmp ((m,_),(n,_)) = cmp (m,n)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   413
      val nxs = map (fn x => (f x, x)) xs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   414
      val nys = sort ncmp nxs
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   415
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   416
      map snd nys
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   417
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   418
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   419
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   420
(* Integers.                                                                 *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   421
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   422
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   423
fun interval m 0 = []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   424
  | interval m len = m :: interval (m + 1) (len - 1);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   425
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   426
fun divides _ 0 = true
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   427
  | divides 0 _ = false
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   428
  | divides a b = b mod (Int.abs a) = 0;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   429
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   430
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   431
  fun hcf 0 n = n
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   432
    | hcf 1 _ = 1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   433
    | hcf m n = hcf (n mod m) m;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   434
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   435
  fun gcd m n =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   436
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   437
        val m = Int.abs m
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   438
        and n = Int.abs n
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   439
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   440
        if m < n then hcf m n else hcf n m
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   441
      end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   442
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   443
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   444
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   445
  fun calcPrimes ps n i =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   446
      if List.exists (fn p => divides p i) ps then calcPrimes ps n (i + 1)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   447
      else
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   448
        let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   449
          val ps = ps @ [i]
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   450
          and n = n - 1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   451
        in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   452
          if n = 0 then ps else calcPrimes ps n (i + 1)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   453
        end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   454
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   455
  val primesList = ref [2];
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   456
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   457
  fun primes n =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   458
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   459
        val ref ps = primesList
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   460
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   461
        val k = n - length ps
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   462
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   463
        if k <= 0 then List.take (ps,n)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   464
        else
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   465
          let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   466
            val ps = calcPrimes ps k (List.last ps + 1)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   467
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   468
            val () = primesList := ps
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   469
          in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   470
            ps
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   471
          end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   472
      end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   473
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   474
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   475
fun primesUpTo n =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   476
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   477
      fun f k =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   478
          let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   479
            val l = primes k
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   480
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   481
            val p = List.last l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   482
          in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   483
            if p < n then f (2 * k) else takeWhile (fn j => j <= n) l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   484
          end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   485
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   486
      f 8
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   487
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   488
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   489
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   490
(* Strings.                                                                  *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   491
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   492
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   493
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   494
  fun len l = (length l, l)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   495
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   496
  val upper = len (explode "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   497
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   498
  val lower = len (explode "abcdefghijklmnopqrstuvwxyz");
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   499
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   500
  fun rotate (n,l) c k =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   501
      List.nth (l, (k + Option.valOf (index (equal c) l)) mod n);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   502
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   503
  fun rot k c =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   504
      if Char.isLower c then rotate lower c k
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   505
      else if Char.isUpper c then rotate upper c k
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   506
      else c;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   507
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   508
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   509
fun charToInt #"0" = SOME 0
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   510
  | charToInt #"1" = SOME 1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   511
  | charToInt #"2" = SOME 2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   512
  | charToInt #"3" = SOME 3
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   513
  | charToInt #"4" = SOME 4
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   514
  | charToInt #"5" = SOME 5
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   515
  | charToInt #"6" = SOME 6
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   516
  | charToInt #"7" = SOME 7
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   517
  | charToInt #"8" = SOME 8
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   518
  | charToInt #"9" = SOME 9
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   519
  | charToInt _ = NONE;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   520
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   521
fun charFromInt 0 = SOME #"0"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   522
  | charFromInt 1 = SOME #"1"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   523
  | charFromInt 2 = SOME #"2"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   524
  | charFromInt 3 = SOME #"3"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   525
  | charFromInt 4 = SOME #"4"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   526
  | charFromInt 5 = SOME #"5"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   527
  | charFromInt 6 = SOME #"6"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   528
  | charFromInt 7 = SOME #"7"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   529
  | charFromInt 8 = SOME #"8"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   530
  | charFromInt 9 = SOME #"9"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   531
  | charFromInt _ = NONE;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   532
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   533
fun nChars x =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   534
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   535
      fun dup 0 l = l | dup n l = dup (n - 1) (x :: l)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   536
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   537
      fn n => implode (dup n [])
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   538
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   539
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   540
fun chomp s =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   541
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   542
      val n = size s
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   543
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   544
      if n = 0 orelse String.sub (s, n - 1) <> #"\n" then s
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   545
      else String.substring (s, 0, n - 1)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   546
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   547
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   548
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   549
  fun chop [] = []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   550
    | chop (l as (h :: t)) = if Char.isSpace h then chop t else l;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   551
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   552
  val trim = implode o chop o rev o chop o rev o explode;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   553
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   554
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   555
fun join _ [] = ""
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   556
  | join s (h :: t) = foldl (fn (x,y) => y ^ s ^ x) h t;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   557
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   558
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   559
  fun match [] l = SOME l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   560
    | match _ [] = NONE
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   561
    | match (x :: xs) (y :: ys) = if x = y then match xs ys else NONE;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   562
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   563
  fun stringify acc [] = acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   564
    | stringify acc (h :: t) = stringify (implode h :: acc) t;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   565
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   566
  fun split sep =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   567
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   568
        val pat = String.explode sep
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   569
        fun div1 prev recent [] = stringify [] (rev recent :: prev)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   570
          | div1 prev recent (l as h :: t) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   571
            case match pat l of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   572
              NONE => div1 prev (h :: recent) t
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   573
            | SOME rest => div1 (rev recent :: prev) [] rest
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   574
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   575
        fn s => div1 [] [] (explode s)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   576
      end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   577
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   578
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   579
fun capitalize s =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   580
    if s = "" then s
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   581
    else str (Char.toUpper (String.sub (s,0))) ^ String.extract (s,1,NONE);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   582
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   583
fun mkPrefix p s = p ^ s;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   584
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   585
fun destPrefix p =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   586
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   587
      fun check s =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   588
          if String.isPrefix p s then ()
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   589
          else raise Error "destPrefix"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   590
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   591
      val sizeP = size p
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   592
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   593
      fn s =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   594
         let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   595
           val () = check s
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   596
         in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   597
           String.extract (s,sizeP,NONE)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   598
         end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   599
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   600
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   601
fun isPrefix p = can (destPrefix p);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   602
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   603
fun stripPrefix pred s =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   604
    Substring.string (Substring.dropl pred (Substring.full s));
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   605
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   606
fun mkSuffix p s = s ^ p;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   607
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   608
fun destSuffix p =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   609
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   610
      fun check s =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   611
          if String.isSuffix p s then ()
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   612
          else raise Error "destSuffix"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   613
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   614
      val sizeP = size p
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   615
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   616
      fn s =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   617
         let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   618
           val () = check s
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   619
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   620
           val sizeS = size s
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   621
         in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   622
           String.substring (s, 0, sizeS - sizeP)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   623
         end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   624
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   625
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   626
fun isSuffix p = can (destSuffix p);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   627
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   628
fun stripSuffix pred s =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   629
    Substring.string (Substring.dropr pred (Substring.full s));
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   630
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   631
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   632
(* Tables.                                                                   *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   633
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   634
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   635
type columnAlignment = {leftAlign : bool, padChar : char}
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   636
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   637
fun alignColumn {leftAlign,padChar} column =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   638
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   639
      val (n,_) = maximum Int.compare (map size column)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   640
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   641
      fun pad entry row =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   642
          let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   643
            val padding = nChars padChar (n - size entry)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   644
          in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   645
            if leftAlign then entry ^ padding ^ row
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   646
            else padding ^ entry ^ row
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   647
          end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   648
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   649
      zipWith pad column
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   650
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   651
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   652
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   653
  fun alignTab aligns rows =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   654
      case aligns of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   655
        [] => map (K "") rows
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   656
      | [{leftAlign = true, padChar = #" "}] => map hd rows
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   657
      | align :: aligns =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   658
        alignColumn align (map hd rows) (alignTab aligns (map tl rows));
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   659
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   660
  fun alignTable aligns rows =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   661
      if null rows then [] else alignTab aligns rows;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   662
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   663
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   664
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   665
(* Reals.                                                                    *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   666
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   667
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   668
val realToString = Real.toString;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   669
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   670
fun percentToString x = Int.toString (Real.round (100.0 * x)) ^ "%";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   671
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   672
fun pos r = Real.max (r,0.0);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   673
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   674
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   675
  val invLn2 = 1.0 / Math.ln 2.0;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   676
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   677
  fun log2 x = invLn2 * Math.ln x;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   678
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   679
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   680
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   681
(* Sums.                                                                     *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   682
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   683
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   684
datatype ('a,'b) sum = Left of 'a | Right of 'b
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   685
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   686
fun destLeft (Left l) = l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   687
  | destLeft _ = raise Error "destLeft";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   688
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   689
fun isLeft (Left _) = true
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   690
  | isLeft (Right _) = false;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   691
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   692
fun destRight (Right r) = r
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   693
  | destRight _ = raise Error "destRight";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   694
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   695
fun isRight (Left _) = false
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   696
  | isRight (Right _) = true;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   697
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   698
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   699
(* Useful impure features.                                                   *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   700
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   701
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   702
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   703
  val generator = ref 0
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   704
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   705
  fun newInt () =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   706
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   707
        val n = !generator
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   708
        val () = generator := n + 1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   709
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   710
        n
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   711
      end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   712
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   713
  fun newInts 0 = []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   714
    | newInts k =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   715
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   716
        val n = !generator
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   717
        val () = generator := n + k
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   718
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   719
        interval n k
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   720
      end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   721
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   722
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   723
fun withRef (r,new) f x =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   724
  let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   725
    val old = !r
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   726
    val () = r := new
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   727
    val y = f x handle e => (r := old; raise e)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   728
    val () = r := old
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   729
  in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   730
    y
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   731
  end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   732
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   733
fun cloneArray a =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   734
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   735
      fun index i = Array.sub (a,i)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   736
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   737
      Array.tabulate (Array.length a, index)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   738
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   739
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   740
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   741
(* Environment.                                                              *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   742
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   743
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   744
fun host () = Option.getOpt (OS.Process.getEnv "HOSTNAME", "unknown");
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   745
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   746
fun time () = Date.fmt "%H:%M:%S" (Date.fromTimeLocal (Time.now ()));
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   747
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   748
fun date () = Date.fmt "%d/%m/%Y" (Date.fromTimeLocal (Time.now ()));
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   749
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   750
fun readDirectory {directory = dir} =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   751
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   752
      val dirStrm = OS.FileSys.openDir dir
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   753
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   754
      fun readAll acc =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   755
          case OS.FileSys.readDir dirStrm of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   756
            NONE => acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   757
          | SOME file =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   758
            let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   759
              val filename = OS.Path.joinDirFile {dir = dir, file = file}
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   760
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   761
              val acc = {filename = filename} :: acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   762
            in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   763
              readAll acc
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   764
            end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   765
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   766
      val filenames = readAll []
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   767
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   768
      val () = OS.FileSys.closeDir dirStrm
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   769
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   770
      rev filenames
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   771
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   772
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   773
fun readTextFile {filename} =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   774
  let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   775
    open TextIO
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   776
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   777
    val h = openIn filename
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   778
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   779
    val contents = inputAll h
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   780
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   781
    val () = closeIn h
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   782
  in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   783
    contents
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   784
  end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   785
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   786
fun writeTextFile {contents,filename} =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   787
  let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   788
    open TextIO
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   789
    val h = openOut filename
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   790
    val () = output (h,contents)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   791
    val () = closeOut h
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   792
  in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   793
    ()
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   794
  end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   795
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   796
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   797
(* Profiling and error reporting.                                            *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   798
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   799
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   800
fun chat s = TextIO.output (TextIO.stdErr, s ^ "\n");
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   801
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   802
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   803
  fun err x s = chat (x ^ ": " ^ s);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   804
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   805
  fun try f x = f x
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   806
      handle e as Error _ => (err "try" (errorToString e); raise e)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   807
           | e as Bug _ => (err "try" (bugToString e); raise e)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   808
           | e => (err "try" "strange exception raised"; raise e);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   809
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   810
  val warn = err "WARNING";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   811
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   812
  fun die s = (err "\nFATAL ERROR" s; OS.Process.exit OS.Process.failure);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   813
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   814
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   815
fun timed f a =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   816
  let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   817
    val tmr = Timer.startCPUTimer ()
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   818
    val res = f a
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   819
    val {usr,sys,...} = Timer.checkCPUTimer tmr
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   820
  in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   821
    (Time.toReal usr + Time.toReal sys, res)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   822
  end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   823
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   824
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   825
  val MIN = 1.0;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   826
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   827
  fun several n t f a =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   828
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   829
      val (t',res) = timed f a
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   830
      val t = t + t'
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   831
      val n = n + 1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   832
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   833
      if t > MIN then (t / Real.fromInt n, res) else several n t f a
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   834
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   835
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   836
  fun timedMany f a = several 0 0.0 f a
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   837
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   838
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   839
val executionTime =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   840
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   841
      val startTime = Time.toReal (Time.now ())
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   842
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   843
      fn () => Time.toReal (Time.now ()) - startTime
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   844
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   845
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   846
end