2
* Copyright (c) 1997-1999 Massachusetts Institute of Technology
3
* Copyright (c) 2000-2001 Stefan Kral
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
(* various utility functions *)
25
(*****************************************
27
*****************************************)
28
(* fint the inverse of n modulo m *)
31
if ((i * n) mod m == 1) then i
36
(* Yooklid's algorithm *)
46
(* reduce the fraction m/n to lowest terms, modulo factors of n/n *)
47
let lowest_terms n m =
48
if (m mod n == 0) then
51
let nn = (abs n) in let mm = m * (n / nn)
53
if (mm > 0) then (mm mod nn)
54
else (mm + (1 + (abs mm) / nn) * nn) mod nn
55
and d = gcd nn (abs mm)
58
(* find a generator for the multiplicative group mod p
59
(where p must be prime for a generator to exist!!) *)
61
exception No_Generator
63
let find_generator p =
64
let rec period x prod =
66
else 1 + (period x (prod * x mod p))
67
in let rec findgen x =
68
if (x == 0) then raise No_Generator
69
else if ((period x x) == (p - 1)) then x
70
else findgen ((x + 1) mod p)
73
(* raise x to a power n modulo p (requires n > 0) (in principle,
74
negative powers would be fine, provided that x and p are relatively
75
prime...we don't need this functionality, though) *)
77
exception Negative_Power
79
let rec pow_mod x n p =
81
else if (n < 0) then raise Negative_Power
82
else if (n mod 2 == 0) then pow_mod (x * x mod p) (n / 2) p
83
else x * (pow_mod x (n - 1) p) mod p
85
(******************************************
87
******************************************)
88
let rec forall id combiner a b f =
90
else combiner (f a) (forall id combiner (a + 1) b f)
92
let sum_list l = fold_right (+) l 0
93
let max_list l = fold_right (max) l (-999999)
94
let min_list l = fold_right (min) l 999999
95
let count pred = fold_left (fun a elem -> if (pred elem) then 1 + a else a) 0
97
let remove elem = filter ((!=) elem)
100
let null = function [] -> true | _ -> false
102
(* functional composition *)
103
let (@@) f g x = f (g x)
105
(* Hmm... CAML won't allow second-order polymorphism. Oh well.. *)
106
(* let forall_flat = forall (@);; *)
107
let rec forall_flat a b f =
109
else (f a) @ (forall_flat (a + 1) b f)
113
let find_elem p xs = try Some (List.find p xs) with Not_found -> None
115
(* find x, x >= a, such that (p x) is true *)
116
let rec suchthat a pred =
117
if (pred a) then a else suchthat (a + 1) pred
120
let selectFirst p xs =
121
let rec selectFirst' = function
122
| [] -> raise Not_found
123
| x::xs when p x -> (x,xs)
124
| x::xs -> let (x',xs') = selectFirst' xs in (x',x::xs')
125
in try Some(selectFirst' xs) with Not_found -> None
127
(* used for inserting an element into a sorted list *)
128
let insertList stop el xs =
129
let rec insert' = function
131
| x::xs as xxs -> if stop el x then el::xxs else x::(insert' xs)
134
(* used for inserting an element into a sorted list *)
135
let insert_list p el xs =
136
let rec insert' = function
138
| x::xs as xxs -> if p el x < 0 then el::xxs else x::(insert' xs)
142
let rec zip' ls rs = function
144
| x::xs -> zip' (x::rs) ls xs
147
let rec intertwine xs zs = match (xs,zs) with
149
| (x::xs,zs) -> x::(intertwine zs xs)
152
let (@.) (a,b) (c,d) = (a@c,b@d)
154
let listAssoc key assoclist =
155
try Some (List.assoc key assoclist) with Not_found -> None
159
let listToString toString separator =
160
let rec listToString_internal = function
163
| x::xs -> (toString x) ^ separator ^ (listToString_internal xs) in
164
listToString_internal
166
let stringlistToString = listToString identity
168
let intToString = string_of_int
169
let floatToString = string_of_float
171
let same_length xs zs =
172
let rec same_length_internal = function
176
| _::xs,_::zs -> same_length_internal (xs,zs)
177
in same_length_internal (xs,zs)
179
let optionIsSome = function None -> false | Some _ -> true
180
let optionIsNone = function None -> true | Some _ -> false
181
let optionToValue' exn = function None -> raise exn | Some x -> x
182
let optionToValue v = optionToValue' (Failure "optionToValue") v
183
let optionToList = function None -> [] | Some a -> [a]
185
let optionToListAndConcat xs = function
189
let option_to_boolvaluepair oldvalue = function
190
| None -> (false, oldvalue)
191
| Some newvalue -> (true, newvalue)
194
let rec minimize' z z' = function
198
if x' < z' then minimize' x x' xs else minimize' z z' xs
202
| x::xs -> minimize' x (f x) xs
204
let list_removefirst p =
205
let rec remove_internal = function
207
| x::xs -> if p x then xs else x::(remove_internal xs)
212
let mapOption f = function
213
| Some x -> Some (f x)
217
use return/identity for that
222
use Pervasives.fst and Pervasives.snd for that
223
let get1of2 (x,_) = x
224
let get2of2 (_,x) = x
227
let get1of3 (x,_,_) = x
228
let get2of3 (_,x,_) = x
229
let get3of3 (_,_,x) = x
231
let get1of4 (x,_,_,_) = x
232
let get2of4 (_,x,_,_) = x
233
let get3of4 (_,_,x,_) = x
234
let get4of4 (_,_,_,x) = x
236
let get1of5 (x,_,_,_,_) = x
237
let get2of5 (_,x,_,_,_) = x
238
let get3of5 (_,_,x,_,_) = x
239
let get4of5 (_,_,_,x,_) = x
240
let get5of5 (_,_,_,_,x) = x
242
let get1of6 (x,_,_,_,_,_) = x
243
let get2of6 (_,x,_,_,_,_) = x
244
let get3of6 (_,_,x,_,_,_) = x
245
let get4of6 (_,_,_,x,_,_) = x
246
let get5of6 (_,_,_,_,x,_) = x
247
let get6of6 (_,_,_,_,_,x) = x
249
let repl1of2 x (_,a) = (x,a)
250
let repl2of2 x (a,_) = (a,x)
252
let repl1of3 x (_,a,b) = (x,a,b)
253
let repl2of3 x (a,_,b) = (a,x,b)
254
let repl3of3 x (a,b,_) = (a,b,x)
256
let repl1of4 x (_,a,b,c) = (x,a,b,c)
257
let repl2of4 x (a,_,b,c) = (a,x,b,c)
258
let repl3of4 x (a,b,_,c) = (a,b,x,c)
259
let repl4of4 x (a,b,c,_) = (a,b,c,x)
261
let repl1of5 x (_,a,b,c,d) = (x,a,b,c,d)
262
let repl2of5 x (a,_,b,c,d) = (a,x,b,c,d)
263
let repl3of5 x (a,b,_,c,d) = (a,b,x,c,d)
264
let repl4of5 x (a,b,c,_,d) = (a,b,c,x,d)
265
let repl5of5 x (a,b,c,d,_) = (a,b,c,d,x)
267
let repl1of6 x (_,a,b,c,d,e) = (x,a,b,c,d,e)
268
let repl2of6 x (a,_,b,c,d,e) = (a,x,b,c,d,e)
269
let repl3of6 x (a,b,_,c,d,e) = (a,b,x,c,d,e)
270
let repl4of6 x (a,b,c,_,d,e) = (a,b,c,x,d,e)
271
let repl5of6 x (a,b,c,d,_,e) = (a,b,c,d,x,e)
272
let repl6of6 x (a,b,c,d,e,_) = (a,b,c,d,e,x)
275
let rec fixpoint f a = match f a with
277
| (true, b') -> fixpoint f b'
281
let diff a b = filter (fun x -> not (List.mem x b)) a
283
let addelem a set = if not (List.mem a set) then a :: set else set
286
let f x = addelem x (* let is source of polymorphism *)
287
in List.fold_right f l
290
List.fold_right (fun a b -> if List.mem a b then b else a :: b) l []
293
let rec msb_internal msb0 = function
295
| n -> msb_internal (msb0+1) (n lsr 1) in
298
let lists_overlap xs zs = List.exists (fun i -> List.mem i xs) zs
305
(* print an information message *)
307
if !Magic.verbose then begin
308
let now = Unix.times ()
309
and pid = Unix.getpid () in
310
prerr_string ((string_of_int pid) ^ ": " ^
311
"at t = " ^ (string_of_float now.tms_utime) ^ " : ");
312
prerr_string (string ^ "\n");
313
flush Pervasives.stderr;
316
let debugOutputString str =
317
if !Magic.do_debug_output then Printf.printf "/* %s */\n" str else ()
319
let rec list_last = function
320
| [] -> failwith "list_last"
322
| x::xs -> list_last xs
325
* freeze a function, i.e., compute it only once on demand, and
326
* cache it into an array.
329
let a = Array.init n (fun i -> lazy (f i))
330
in fun i -> Lazy.force a.(i)
332
(* iota n produces the list [0; 1; ...; n - 1] *)
333
let iota n = forall [] cons 0 n identity
335
(* interval a b produces the list [a; 1; ...; b - 1] *)
336
let interval a b = List.map ((+) a) (iota (b - a))