about summary refs log tree commit diff
path: root/src/boot/util/bits.ml
blob: aed0f2b836141bbcb9685792890bcff90c5ef607 (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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
type t = {
  storage: int array;
  nbits: int;
}
;;

let int_bits =
  if max_int = (1 lsl 30) - 1
  then 31
  else 63
;;

let create nbits flag =
  { storage = Array.make (nbits / int_bits + 1) (if flag then lnot 0 else 0);
    nbits = nbits }
;;

(* 
 * mutate v0 in place: v0.(i) <- v0.(i) op v1.(i), returning bool indicating
 * whether any bits in v0 changed in the process. 
 *)
let process (op:int -> int -> int) (v0:t) (v1:t) : bool =
  let changed = ref false in
    assert (v0.nbits = v1.nbits);
    assert ((Array.length v0.storage) = (Array.length v1.storage));
    Array.iteri
      begin
        fun i w1 ->
          let w0 = v0.storage.(i) in
          let w0' = op w0 w1 in
            if not (w0' = w0)
            then changed := true;
            v0.storage.(i) <- w0';
      end
      v1.storage;
    !changed
;;

let union = process (lor) ;;
let intersect = process (land) ;;
let copy = process (fun _ w1 -> w1) ;;

let get (v:t) (i:int) : bool =
  assert (i >= 0);
  assert (i < v.nbits);
  let w = i / int_bits in
  let b = i mod int_bits in
  let x = 1 land (v.storage.(w) lsr b) in
    x = 1
;;

let equal (v1:t) (v0:t) : bool =
  v0 = v1
;;

let clear (v:t) : unit =
  for i = 0 to (Array.length v.storage) - 1
  do
    v.storage.(i) <- 0
  done
;;

let invert (v:t) : unit =
  for i = 0 to (Array.length v.storage) - 1
  do
    v.storage.(i) <- lnot v.storage.(i)
  done
;;

(* dst = dst - src *)
let difference (dst:t) (src:t) : bool =
  invert src;
  let b = intersect dst src in
    invert src;
    b
;;


let set (v:t) (i:int) (x:bool) : unit =
  assert (i >= 0);
  assert (i < v.nbits);
  let w = i / int_bits in
  let b = i mod int_bits in
  let w0 = v.storage.(w) in
  let flag = 1 lsl b in
    v.storage.(w) <-
      if x
      then w0 lor flag
      else w0 land (lnot flag)
;;

let to_list (v:t) : int list =
  if v.nbits = 0
  then []
  else
    let accum = ref [] in
    let word = ref v.storage.(0) in
      for i = 0 to (v.nbits-1) do
        if i mod int_bits = 0
        then word := v.storage.(i / int_bits);
        if (1 land (!word)) = 1
        then accum := i :: (!accum);
        word := (!word) lsr 1;
      done;
      !accum
;;


(*
 * Local Variables:
 * fill-column: 78;
 * indent-tabs-mode: nil
 * buffer-file-coding-system: utf-8-unix
 * compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
 * End:
 *)