summaryrefslogtreecommitdiffstats
path: root/sources/fabrice/simulator/randomArray.ml
blob: 4f5ddf9bbaf4babcbcb82f44f0f669799b9bbea1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  
module type INTERFACE = sig
    
    type 'a t

    val init : int -> (int -> 'a) -> 'a t
    val length : 'a t -> int
    val of_list : 'a list -> 'a t
    val add : 'a t -> 'a -> unit
    val random : 'a t -> 'a
    val reset : 'a t -> unit  
    val set_state : 'a t -> Random.State.t -> unit
  end
  
module IMPLEMENTATION = struct
    
    type 'a t = {
        mutable length : int; 
        mutable left : int;
        array : 'a array;
        mutable state : Random.State.t;
      }

    let init len f =
      let array = Array.init len f in
      {
        array = array;
        length = len;
        left = len;
        state = Random.get_state ();
      }
      
    let of_list list = 
      let array = Array.of_list list in
      let len = Array.length array in
      {
        array = array;
        length = len;
        left = len;
        state = Random.get_state ();
      }
    
    let length t = t.length
    
    let add t x = 
      let len = t.length in
      t.array.(len) <- x;
      t.length <- len + 1;
      if len = t.left then 
        t.left <- len + 1
    
    let random t =
      if t.left <= 0 then raise Not_found;
      let pos = Random.State.int t.state t.left in
      let tab = t.array in
      let len = t.left-1 in 
(*      Printf.fprintf stderr "SWAP(%d)(%d)%!" pos len; *)
      let x = tab.(pos) in
      tab.(pos) <- tab.(len);
      tab.(len) <- x;
      t.left <- len;
      x
      
    let reset t = 
      t.left <- t.length

    let set_state t state = t.state <- state
      
  end

include (IMPLEMENTATION : INTERFACE)