Blame src/extArray.ml

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