1 /*******************************************************************************
2 
3         Copyright:
4             Copyright (c) 2009 Kris Bell.
5             Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
6             All rights reserved.
7 
8         License:
9             Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
10             See LICENSE_TANGO.txt for details.
11 
12         Version: Sept 2009: Initial release
13 
14         Authors: Kris
15 
16 *******************************************************************************/
17 
18 module ocean.util.container.more.BitSet;
19 
20 import ocean.core.BitManip;
21 
22 /******************************************************************************
23 
24         A fixed or dynamic set of bits. Note that this does no memory
25         allocation of its own when Size != 0, and does heap allocation
26         when Size is zero. Thus you can have a fixed-size low-overhead
27         'instance, or a heap oriented instance. The latter has support
28         for resizing, whereas the former does not.
29 
30         Note that leveraging intrinsics is slower when using dmd ...
31 
32 ******************************************************************************/
33 
34 struct BitSet (int Count=0)
35 {
36         public alias and        opAnd;
37         public alias or         opOrAssign;
38         public alias xor        opXorAssign;
39         private enum           width = size_t.sizeof * 8;
40 
41         static if (Count == 0)
42                    private size_t[] bits;
43                else
44                   private size_t [(Count+width-1)/width] bits;
45 
46         /**********************************************************************
47 
48                 Set the indexed bit, resizing as necessary for heap-based
49                 instances (IndexOutOfBounds for statically-sized instances)
50 
51         **********************************************************************/
52 
53         void add (size_t i)
54         {
55                 static if (Count == 0)
56                            size (i);
57                 or (i);
58         }
59 
60         /**********************************************************************
61 
62                 Test whether the indexed bit is enabled
63 
64         **********************************************************************/
65 
66         bool has (size_t i)
67         {
68                 auto idx = i / width;
69                 return idx < bits.length && (bits[idx] & (1 << (i % width))) != 0;
70                 //return idx < bits.length && bt(&bits[idx], i % width) != 0;
71         }
72 
73         /**********************************************************************
74 
75                 Like get() but a little faster for when you know the range
76                 is valid
77 
78         **********************************************************************/
79 
80         bool and (size_t i)
81         {
82                 return (bits[i / width] & (1 << (i % width))) != 0;
83                 //return bt(&bits[i / width], i % width) != 0;
84         }
85 
86         /**********************************************************************
87 
88                 Turn on an indexed bit
89 
90         **********************************************************************/
91 
92         void or (size_t i)
93         {
94                 bits[i / width] |= (1 << (i % width));
95                 //bts (&bits[i / width], i % width);
96         }
97 
98         /**********************************************************************
99 
100                 Invert an indexed bit
101 
102         **********************************************************************/
103 
104         void xor (size_t i)
105         {
106                 bits[i / width] ^= (1 << (i % width));
107                 //btc (&bits[i / width], i % width);
108         }
109 
110         /**********************************************************************
111 
112                 Clear an indexed bit
113 
114         **********************************************************************/
115 
116         void clr (size_t i)
117         {
118                 bits[i / width] &= ~(1 << (i % width));
119                 //btr (&bits[i / width], i % width);
120         }
121 
122         /**********************************************************************
123 
124                 Clear all bits
125 
126         **********************************************************************/
127 
128         BitSet* clr ()
129         {
130                 bits[] = 0;
131                 return &this;
132         }
133 
134         /**********************************************************************
135 
136                 Clone this BitSet and return it
137 
138         **********************************************************************/
139 
140         BitSet dup ()
141         {
142                 BitSet x;
143                 static if (Count == 0)
144                            x.bits.length = this.bits.length;
145                 x.bits[] = bits[];
146                 return x;
147         }
148 
149         /**********************************************************************
150 
151                 Return the number of bits we have room for
152 
153         **********************************************************************/
154 
155         size_t size ()
156         {
157                 return width * bits.length;
158         }
159 
160         /**********************************************************************
161 
162                 Expand to include the indexed bit (dynamic only)
163 
164         **********************************************************************/
165 
166         static if (Count == 0) BitSet* size (size_t i)
167         {
168                 i = i / width;
169                 if (i >= bits.length)
170                     bits.length = i + 1;
171                 return &this;
172         }
173 }