File: dynamic-bitset.sml

package info (click to toggle)
mlton 20210117%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 58,464 kB
  • sloc: ansic: 27,682; sh: 4,455; asm: 3,569; lisp: 2,879; makefile: 2,347; perl: 1,169; python: 191; pascal: 68; javascript: 7
file content (128 lines) | stat: -rw-r--r-- 3,593 bytes parent folder | download | duplicates (5)
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
117
118
119
120
121
122
123
124
125
126
127
128
(*
 * Growable bitset.
 *
 * -- Allen
 *)

structure DynamicBitSet :> BITSET =
struct

   structure A = Word8Array
   structure W = Word8
   open A

   infix << >> & ||
   infix sub

   type bitset = array ref

   val word  = Word.fromInt 
   val int   = Word.toInt
   val op &  = Word.andb
   val op >> = Word.>>
   val op << = W.<<

   fun create n = ref(array((n+7)div 8, 0wx0))

   fun size a = length(! a) * 8

   fun grow (r as ref a, i) =
   let val new_size  = Int.max(length a * 2, i)
       val new_array = array(new_size, 0wx0)
       val _         = copy { src = a, si = 0, dst = new_array, di = 0, 
                              len = NONE }
   in  r := new_array
   end

   fun set (r as ref a, i) =
   let val byte = int((word i) >> 0w3)
       val mask = W.<< (0w1, (word i) & 0w7)
   in  update(a, byte, W.orb(a sub byte, mask)) end
   handle Subscript => (grow (r, i+1); set(r,i))

   fun reset (r as ref a, i) =
   let val byte = int((word i) >> 0w3)
       val mask = W.notb(W.<< (0w1, (word i) & 0w7))
   in  update(a, byte, W.andb(a sub byte, mask)) end
   handle Subscript => ()

   fun clear (ref a) = modify (fn _ => 0wx0) a

   fun negate (ref a) = ref(tabulate (length a, fn i => W.notb(a sub i)))

   fun union (ref a, ref b) =
   let val m         = Int.max(length a, length b)
       val n         = Int.min(length a, length b)
       val c         = array(m, 0wx0)
       fun f ~1      = ()
         | f i       = update(c, i, W.orb(a sub i, b sub i))
   in  f n;
       copy { src = if length a > length b then a else b,
              si  = n,  dst = c, di  = n, len = NONE };
       ref c 
   end

   fun intersect (ref a, ref b) =
   let val n         = Int.min(length a, length b)
       val c         = array(n, 0wx0)
       fun f ~1      = ()
         | f i       = update(c, i, W.andb(a sub i, b sub i))
   in  f n;
       ref c 
   end

   fun diff (ref a, ref b) =
   let val m         = length a
       val c         = array(m, 0wx0)
       fun f ~1      = ()
         | f i       = update(c, i, W.andb(a sub i, W.notb(b sub i)))
   in  f m; ref c
   end

   fun unionWith (r as ref a, ref b) =
      (if length b > length a then grow(r, length b) else ();
       modifyi (fn (i,x) => W.orb(x,b sub i)) (a, 0, NONE))
   
   fun intersectWith (ref a, ref b) =
      modifyi (fn (i,x) => W.andb(x,b sub i)) (a, 0, NONE)

   fun diffWith (ref a, ref b) =
      modifyi (fn (i,x) => W.andb(x,W.notb(b sub i))) (a, 0, NONE)

   fun complement (ref a) = modify W.notb a

   fun copy (ref a) = ref(tabulate (length a, fn i => a sub i))

   fun toString (ref a) = 
   let fun f i = if i < length a then W.toString(a sub i)::f(i+1) else []
       val s = String.concat(f 0)
   in  "[" ^ s ^ "]" end

   fun contains (r as ref a, i) = 
   let val byte = int((word i) >> 0w3)
       val mask = W.<<(0w1, (word i) & 0w7)
   in  W.andb(A.sub(a, byte), mask) <> 0wx0 end
   handle Subscript => false
 
   fun markAndTest (r as ref a, i) =
   let val byte = int((word i) >> 0w3)
       val mask = W.<<(0w1, (word i) & 0w7)
       val word = A.sub(a,byte)
   in  if W.andb(word, mask) <> 0wx0 then
          true
       else 
          (A.update(a, byte, W.orb(word, mask)); false)
   end handle Subscript => (grow (r, i+1); markAndTest(r,i))

   fun unmarkAndTest (r as ref a, i) =
   let val byte = int(word i >> 0w3)
       val mask = W.<<(0w1, (word i) & 0w7)
       val word = A.sub(a,byte)
   in  if W.andb(word, mask) <> 0wx0 then
          (A.update(a, byte, W.andb(word,W.notb mask)); true)
       else 
          false
   end handle Subscript => false

end