(* * ExtList - additional and modified functions for lists. * Copyright (C) 2005 Richard W.M. Jones (rich @ annexia.org) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version, * with the special exception on linking described in file LICENSE. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) module Array = struct include Array let rev_in_place xs = let n = length xs in let j = ref (n-1) in for i = 0 to n/2-1 do let c = xs.(i) in xs.(i) <- xs.(!j); xs.(!j) <- c; decr j done let rev xs = let ys = Array.copy xs in rev_in_place ys; ys #if OCAML < 403 let for_all p xs = let n = length xs in let rec loop i = if i = n then true else if p xs.(i) then loop (succ i) else false in loop 0 exception Exists let exists p xs = try for i = 0 to Array.length xs - 1 do if p xs.(i) then raise Exists done; false with Exists -> true let mem a xs = let n = length xs in let rec loop i = if i = n then false else if a = xs.(i) then true else loop (succ i) in loop 0 let memq a xs = let n = length xs in let rec loop i = if i = n then false else if a == xs.(i) then true else loop (succ i) in loop 0 #endif let findi p xs = let n = length xs in let rec loop i = if i = n then raise Not_found else if p xs.(i) then i else loop (succ i) in loop 0 let find p xs = xs.(findi p xs) (* Use of BitSet suggested by Brian Hurt. *) let filter p xs = let n = length xs in (* Use a bitset to store which elements will be in the final array. *) let bs = BitSet.create n in for i = 0 to n-1 do if p xs.(i) then BitSet.set bs i done; (* Allocate the final array and copy elements into it. *) let n' = BitSet.count bs in let j = ref 0 in let xs' = init n' (fun _ -> (* Find the next set bit in the BitSet. *) while not (BitSet.is_set bs !j) do incr j done; let r = xs.(!j) in incr j; r) in xs' let find_all = filter let partition p xs = let n = length xs in (* Use a bitset to store which elements will be in which final array. *) let bs = BitSet.create n in for i = 0 to n-1 do if p xs.(i) then BitSet.set bs i done; (* Allocate the final arrays and copy elements into them. *) let n1 = BitSet.count bs in let n2 = n - n1 in let j = ref 0 in let xs1 = init n1 (fun _ -> (* Find the next set bit in the BitSet. *) while not (BitSet.is_set bs !j) do incr j done; let r = xs.(!j) in incr j; r) in let j = ref 0 in let xs2 = init n2 (fun _ -> (* Find the next clear bit in the BitSet. *) while BitSet.is_set bs !j do incr j done; let r = xs.(!j) in incr j; r) in xs1, xs2 let enum xs = let rec make start xs = let n = length xs in Enum.make ~next:(fun () -> if !start < n then ( let r = xs.(!start) in incr start; r ) else raise Enum.No_more_elements) ~count:(fun () -> n - !start) ~clone:(fun () -> let xs' = Array.sub xs !start (n - !start) in make (ref 0) xs') in make (ref 0) xs let of_enum e = let n = Enum.count e in (* This assumes, reasonably, that init traverses the array in order. *) Array.init n (fun i -> match Enum.get e with | Some x -> x | None -> assert false) #if OCAML < 403 let iter2 f a1 a2 = if Array.length a1 <> Array.length a2 then raise (Invalid_argument "Array.iter2"); for i = 0 to Array.length a1 - 1 do f a1.(i) a2.(i); done let map2 f a1 a2 = if Array.length a1 <> Array.length a2 then raise (Invalid_argument "Array.map2"); Array.init (Array.length a1) (fun i -> f a1.(i) a2.(i)) #endif #if OCAML >= 403 #else #if OCAML >= 402 let create_float = make_float #else let make_float n = make n 0. let create_float = make_float #endif #endif end