bitset 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 67a16f9ffaa21475905ca59bde6734954735e3c7
4
+ data.tar.gz: c734af4e2b220c01b760f1e93fd05940ca79569d
5
+ SHA512:
6
+ metadata.gz: 6603741fd0c7f3a5e348e3db792695fdfc5926062567d401e49b2c66f8ae7e44dc8e1eed66fc8d69859305dc265a3abe2377dad5486ee234da872fa427a9119b
7
+ data.tar.gz: 50f4c82523b31f15d176d7dc26a47be1610135bd4b826f2633abe960394c3fea407d67b7b624dc27148004374f1035968880fb007753c7efd2e440166d429431
@@ -0,0 +1,158 @@
1
+ Bitset
2
+ ======
3
+
4
+ A fast Bitset implementation for Ruby. Available as the 'bitset' gem.
5
+
6
+
7
+ Installation
8
+ ------------
9
+
10
+ Usually you want to do this:
11
+
12
+ gem install bitset
13
+
14
+ But if you want the latest patches or want to work on it yourself, you may want
15
+ to do this:
16
+
17
+ git clone git://github.com/ericboesch/bitset.git
18
+ cd bitset
19
+ rake build
20
+ gem install pkg/bitset-<version>.gem
21
+
22
+
23
+ Usage
24
+ -----
25
+
26
+ You create a bitset like this:
27
+
28
+ >> Bitset.new(8)
29
+ => 00000000
30
+
31
+ Here we created an 8-bit bitset. All bits are initialized to 0.
32
+
33
+ We can also create a bitset based on a string of ones and zeros.
34
+
35
+ >> Bitset.from_s('00010001')
36
+ => 00010001
37
+
38
+ Obviously you can also set and clear bits...
39
+
40
+ >> bitset = Bitset.new(8)
41
+ => 00000000
42
+
43
+ >> bitset[3] = true
44
+ => 00010000
45
+
46
+ >> bitset[3] = false
47
+ => 00000000
48
+
49
+ >> bitset.set(1, 3, 5, 7)
50
+ => 01010101
51
+
52
+ >> bitset.clear(1, 5)
53
+ => 00010001
54
+
55
+ The point of a bitset is to be, effectively, an array of single bits. It should
56
+ support basic set and bitwise operations. So, let's look at a few of those.
57
+
58
+ >> a = Bitset.from_s('00001111')
59
+ => 00001111
60
+
61
+ >> b = Bitset.from_s('01010101')
62
+ => 01010101
63
+
64
+ >> a & b
65
+ => 00000101
66
+
67
+ >> a | b
68
+ => 01011111
69
+
70
+ >> b - a
71
+ => 01010000
72
+
73
+ >> a ^ b
74
+ => 01011010
75
+
76
+ >> ~a
77
+ => 11110000
78
+
79
+ >> a.hamming(b)
80
+ => 4
81
+
82
+ >> a.cardinality
83
+ => 4
84
+
85
+ >> a.reverse
86
+ => 11110000
87
+
88
+ # Tell whether all of the given bit numbers are set
89
+ >> a.set? 6
90
+ => true
91
+
92
+ # Return a new Bitset composed of bits #1, #3, #5, #4, and #1 again
93
+ >> a.select_bits [1,3,5,4,1]
94
+ => 00110
95
+
96
+ # Tell whether all of the given bit numbers are clear
97
+ >> a.clear? 1,3,5
98
+ => false
99
+
100
+ # Tell whether all bits are clear
101
+ >> a.empty?
102
+ => false
103
+
104
+ # Pass all bits to the block
105
+ >> b.each { |v| puts v }
106
+ => false
107
+ true
108
+ false
109
+ ...
110
+
111
+ # Pass the positions of all set bits to the block
112
+ >> b.each_set { |bit| puts bit }
113
+ => 1
114
+ 3
115
+ 5
116
+ 7
117
+
118
+ # Return an array of the positions of all set bits
119
+ >> b.each_set
120
+ => [1, 3, 5, 7]
121
+
122
+ # The following methods modify a Bitset in place very quickly:
123
+ >> a.intersect!(b) # like a &= b
124
+ >> a.union!(b) # like a |= b
125
+ >> a.difference!(b) # like a -= b
126
+ >> a.xor!(b) # alias a.symmetric_difference!(b), like a ^= b
127
+ >> a.reset!
128
+
129
+ # Above, "like" does not mean "identical to." a |= b creates a new
130
+ # Bitset object. a.union!(b) changes an existing object which
131
+ # affects all variables that point to the same object.
132
+
133
+ # Attempting to apply bitwise binary operators or their in-place
134
+ # equivalents between bitsets of different sizes will raise an
135
+ # ArgumentError.
136
+
137
+ # b.dup and b.clone are also available.
138
+
139
+ # Marshal.dump and Marshal.load are also supported. If you want to
140
+ # save a few bytes and don't need Marshal.load to work, you can
141
+ # use #pack and Bitset.unpack instead.
142
+
143
+ Contributing
144
+ ------------
145
+
146
+ The best way to contribute is to fork the project on GitHub, make your changes,
147
+ and send a pull request. This is always much appreciated. If you want to mess
148
+ around with the version numbers, gemspec, or anything like that feel free... But
149
+ do it in separate commits so I can easily ignore them.
150
+
151
+
152
+ License
153
+ -------
154
+
155
+ See LICENSE.txt.
156
+
157
+
158
+ ### Thanks for using Bitset!
data/Rakefile CHANGED
@@ -12,17 +12,17 @@ task :default => :spec
12
12
  require 'jeweler'
13
13
  Jeweler::Tasks.new do |gem|
14
14
  gem.name = "bitset"
15
- gem.homepage = "http://github.com/tyler/bitset"
15
+ gem.homepage = "http://github.com/ericboesch/bitset"
16
16
  gem.license = "MIT"
17
17
  gem.summary = 'Bitset implementation.'
18
18
  gem.description = 'A fast C-based Bitset. It supports the standard set operations as well as operations you may expect on bit arrays. (popcount, for instance)'
19
- gem.email = "tbmcmullen@gmail.com"
19
+ gem.email = "eric.boesch@nist.gov"
20
20
  gem.authors = ["Tyler McMullen"]
21
21
  end
22
22
  Jeweler::RubygemsDotOrgTasks.new
23
23
 
24
- require 'rake/rdoctask'
25
- Rake::RDocTask.new do |rdoc|
24
+ require 'rdoc/task'
25
+ RDoc::Task.new do |rdoc|
26
26
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
27
27
 
28
28
  rdoc.rdoc_dir = 'rdoc'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 1.0.0
@@ -5,13 +5,13 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{bitset}
8
- s.version = "0.1.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Tyler McMullen"]
12
- s.date = %q{2011-03-03}
11
+ s.authors = ["Tyler McMullen", "Eric Boesch"]
12
+ s.date = %q{2016-02-22}
13
13
  s.description = %q{A fast C-based Bitset. It supports the standard set operations as well as operations you may expect on bit arrays. (popcount, for instance)}
14
- s.email = %q{tbmcmullen@gmail.com}
14
+ s.email = %q{ericboesch@gmail.com}
15
15
  s.extensions = ["ext/bitset/extconf.rb"]
16
16
  s.extra_rdoc_files = [
17
17
  "LICENSE.txt",
@@ -25,9 +25,10 @@ Gem::Specification.new do |s|
25
25
  "bitset.gemspec",
26
26
  "ext/bitset/bitset.c",
27
27
  "ext/bitset/extconf.rb",
28
+ "lib/bitset/bitset.rb",
28
29
  "spec/bitset_spec.rb"
29
30
  ]
30
- s.homepage = %q{http://github.com/tyler/bitset}
31
+ s.homepage = %q{http://github.com/ericboesch/bitset}
31
32
  s.licenses = ["MIT"]
32
33
  s.require_paths = ["lib"]
33
34
  s.rubygems_version = %q{1.3.7}
@@ -11,16 +11,18 @@ typedef struct {
11
11
  uint64_t * data;
12
12
  } Bitset;
13
13
 
14
- #define BYTES(_bs) (((_bs->len-1) >> 3) + 1)
15
- #define INTS(_bs) (((_bs->len-1) >> 6) + 1)
14
+ // Avoid using (len-1), just in case len == 0.
15
+ #define BYTES(_bs) (((_bs)->len+7) >> 3)
16
+ #define INTS(_bs) (((_bs)->len+63) >> 6)
17
+ // 2^6=64
16
18
 
17
19
  Bitset * bitset_new() {
18
- return (Bitset *) malloc(sizeof(Bitset));
20
+ return (Bitset *) calloc(1, sizeof(Bitset));
19
21
  }
20
22
 
21
23
  void bitset_setup(Bitset * bs, int len) {
22
24
  bs->len = len;
23
- bs->data = (uint64_t *) calloc((((bs->len-1) >> 6) + 1), sizeof(uint64_t)); // 2^6=64
25
+ bs->data = (uint64_t *) calloc(INTS(bs), sizeof(uint64_t));
24
26
  }
25
27
 
26
28
  void bitset_free(Bitset * bs) {
@@ -30,7 +32,7 @@ void bitset_free(Bitset * bs) {
30
32
  }
31
33
 
32
34
 
33
- Bitset * get_bitset(VALUE obj) {
35
+ static Bitset * get_bitset(VALUE obj) {
34
36
  Bitset * bs;
35
37
  Data_Get_Struct(obj, Bitset, bs);
36
38
  return bs;
@@ -53,44 +55,43 @@ static VALUE rb_bitset_size(VALUE self, VALUE len) {
53
55
  return INT2NUM(bs->len);
54
56
  }
55
57
 
56
- void raise_index_error() {
58
+ static void raise_index_error() {
57
59
  VALUE rb_eIndexError = rb_const_get(rb_cObject, rb_intern("IndexError"));
58
60
  rb_raise(rb_eIndexError, "Index out of bounds");
59
61
  }
60
62
 
61
- #define _bit_segment(bit) ((bit) >> 6UL)
62
- #define _bit_mask(bit) (((uint64_t) 1) << ((bit) & 0x3f))
63
+ #define _bit_no(bit) ((bit) & 0x3f)
64
+ #define _bit_segment(bit) ((bit) >> 6)
65
+ #define _bit_mask(bit) (((uint64_t) 1) << _bit_no(bit))
66
+ #define _seg_no_to_bit_no(seg_no) ((seg_no) << 6)
67
+ #define _get_bit(bs, idx) ((bs)->data[_bit_segment(idx)] & _bit_mask(idx))
68
+ #define _set_bit(bs, idx) ((bs)->data[_bit_segment(idx)] |= _bit_mask(idx))
69
+ #define _clear_bit(bs, idx) ((bs)->data[_bit_segment(idx)] &= ~_bit_mask(idx))
63
70
 
64
- void validate_index(Bitset * bs, int idx) {
71
+ static void validate_index(Bitset * bs, int idx) {
65
72
  if(idx < 0 || idx >= bs->len)
66
73
  raise_index_error();
67
74
  }
68
75
 
69
- uint64_t get_bit(Bitset * bs, int idx) {
70
- uint64_t segment = bs->data[_bit_segment(idx)];
71
- return segment & _bit_mask(idx);
72
- }
73
-
74
- void set_bit(Bitset * bs, int idx) {
75
- bs->data[_bit_segment(idx)] |= _bit_mask(idx);
76
- }
77
-
78
- void clear_bit(Bitset * bs, int idx) {
79
- bs->data[_bit_segment(idx)] &= ~_bit_mask(idx);
76
+ static void verify_equal_size(Bitset * bs1, Bitset * bs2) {
77
+ if (bs1->len != bs2->len) {
78
+ VALUE rb_eArgumentError = rb_const_get(rb_cObject, rb_intern("ArgumentError"));
79
+ rb_raise(rb_eArgumentError, "Operands size mismatch");
80
+ }
80
81
  }
81
82
 
82
83
  void assign_bit(Bitset * bs, int idx, VALUE value) {
83
84
  if(NIL_P(value) || value == Qfalse)
84
- clear_bit(bs, idx);
85
+ _clear_bit(bs, idx);
85
86
  else
86
- set_bit(bs, idx);
87
+ _set_bit(bs, idx);
87
88
  }
88
89
 
89
90
  static VALUE rb_bitset_aref(VALUE self, VALUE index) {
90
91
  Bitset * bs = get_bitset(self);
91
92
  int idx = NUM2INT(index);
92
93
  validate_index(bs, idx);
93
- return get_bit(bs, idx) > 0 ? Qtrue : Qfalse;
94
+ return _get_bit(bs, idx) > 0 ? Qtrue : Qfalse;
94
95
  }
95
96
 
96
97
  static VALUE rb_bitset_aset(VALUE self, VALUE index, VALUE value) {
@@ -108,7 +109,7 @@ static VALUE rb_bitset_set(int argc, VALUE * argv, VALUE self) {
108
109
  VALUE index = argv[i];
109
110
  int idx = NUM2INT(index);
110
111
  validate_index(bs, idx);
111
- set_bit(bs, idx);
112
+ _set_bit(bs, idx);
112
113
  }
113
114
  return Qtrue;
114
115
  }
@@ -120,7 +121,7 @@ static VALUE rb_bitset_clear(int argc, VALUE * argv, VALUE self) {
120
121
  VALUE index = argv[i];
121
122
  int idx = NUM2INT(index);
122
123
  validate_index(bs, idx);
123
- clear_bit(bs, idx);
124
+ _clear_bit(bs, idx);
124
125
  }
125
126
  return Qtrue;
126
127
  }
@@ -132,7 +133,7 @@ static VALUE rb_bitset_clear_p(int argc, VALUE * argv, VALUE self) {
132
133
  VALUE index = argv[i];
133
134
  int idx = NUM2INT(index);
134
135
  validate_index(bs, idx);
135
- if(get_bit(bs, idx) > 0)
136
+ if(_get_bit(bs, idx) > 0)
136
137
  return Qfalse;
137
138
  }
138
139
  return Qtrue;
@@ -145,7 +146,7 @@ static VALUE rb_bitset_set_p(int argc, VALUE * argv, VALUE self) {
145
146
  VALUE index = argv[i];
146
147
  int idx = NUM2INT(index);
147
148
  validate_index(bs, idx);
148
- if(get_bit(bs, idx) == 0)
149
+ if(_get_bit(bs, idx) == 0)
149
150
  return Qfalse;
150
151
  }
151
152
  return Qtrue;
@@ -154,13 +155,10 @@ static VALUE rb_bitset_set_p(int argc, VALUE * argv, VALUE self) {
154
155
  static VALUE rb_bitset_cardinality(VALUE self) {
155
156
  Bitset * bs = get_bitset(self);
156
157
  int i;
157
- int max = ((bs->len-1) >> 6) + 1;
158
+ int max = INTS(bs);
158
159
  int count = 0;
159
160
  for(i = 0; i < max; i++) {
160
- uint64_t segment = bs->data[i];
161
- if(i+1 == max)
162
- segment &= ((((uint64_t) 1) << (bs->len & 0x3F)) - 1);
163
- count += __builtin_popcountll(segment);
161
+ count += __builtin_popcountll(bs->data[i]);
164
162
  }
165
163
  return INT2NUM(count);
166
164
  }
@@ -168,11 +166,12 @@ static VALUE rb_bitset_cardinality(VALUE self) {
168
166
  static VALUE rb_bitset_intersect(VALUE self, VALUE other) {
169
167
  Bitset * bs = get_bitset(self);
170
168
  Bitset * other_bs = get_bitset(other);
169
+ verify_equal_size(bs, other_bs);
171
170
 
172
171
  Bitset * new_bs = bitset_new();
173
172
  bitset_setup(new_bs, bs->len);
174
173
 
175
- int max = ((bs->len-1) >> 6) + 1;
174
+ int max = INTS(bs);
176
175
  int i;
177
176
  for(i = 0; i < max; i++) {
178
177
  uint64_t segment = bs->data[i];
@@ -186,11 +185,12 @@ static VALUE rb_bitset_intersect(VALUE self, VALUE other) {
186
185
  static VALUE rb_bitset_union(VALUE self, VALUE other) {
187
186
  Bitset * bs = get_bitset(self);
188
187
  Bitset * other_bs = get_bitset(other);
188
+ verify_equal_size(bs, other_bs);
189
189
 
190
190
  Bitset * new_bs = bitset_new();
191
191
  bitset_setup(new_bs, bs->len);
192
192
 
193
- int max = ((bs->len-1) >> 6) + 1;
193
+ int max = INTS(bs);
194
194
  int i;
195
195
  for(i = 0; i < max; i++) {
196
196
  uint64_t segment = bs->data[i];
@@ -204,11 +204,12 @@ static VALUE rb_bitset_union(VALUE self, VALUE other) {
204
204
  static VALUE rb_bitset_difference(VALUE self, VALUE other) {
205
205
  Bitset * bs = get_bitset(self);
206
206
  Bitset * other_bs = get_bitset(other);
207
+ verify_equal_size(bs, other_bs);
207
208
 
208
209
  Bitset * new_bs = bitset_new();
209
210
  bitset_setup(new_bs, bs->len);
210
211
 
211
- int max = ((bs->len-1) >> 6) + 1;
212
+ int max = INTS(bs);
212
213
  int i;
213
214
  for(i = 0; i < max; i++) {
214
215
  uint64_t segment = bs->data[i];
@@ -222,11 +223,12 @@ static VALUE rb_bitset_difference(VALUE self, VALUE other) {
222
223
  static VALUE rb_bitset_xor(VALUE self, VALUE other) {
223
224
  Bitset * bs = get_bitset(self);
224
225
  Bitset * other_bs = get_bitset(other);
226
+ verify_equal_size(bs, other_bs);
225
227
 
226
228
  Bitset * new_bs = bitset_new();
227
229
  bitset_setup(new_bs, bs->len);
228
230
 
229
- int max = ((bs->len-1) >> 6) + 1;
231
+ int max = INTS(bs);
230
232
  int i;
231
233
  for(i = 0; i < max; i++) {
232
234
  uint64_t segment = bs->data[i];
@@ -243,12 +245,15 @@ static VALUE rb_bitset_not(VALUE self) {
243
245
  Bitset * new_bs = bitset_new();
244
246
  bitset_setup(new_bs, bs->len);
245
247
 
246
- int max = ((bs->len-1) >> 6) + 1;
248
+ int max = INTS(bs);
249
+
247
250
  int i;
248
251
  for(i = 0; i < max; i++) {
249
252
  uint64_t segment = bs->data[i];
250
253
  new_bs->data[i] = ~segment;
251
254
  }
255
+ if(_bit_no(bs->len) != 0)
256
+ new_bs->data[max-1] &= _bit_mask(bs->len) - 1;
252
257
 
253
258
  return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
254
259
  }
@@ -259,7 +264,7 @@ static VALUE rb_bitset_to_s(VALUE self) {
259
264
  int i;
260
265
  char * data = malloc(bs->len + 1);
261
266
  for(i = 0; i < bs->len; i++) {
262
- data[i] = get_bit(bs, i) ? '1' : '0';
267
+ data[i] = _get_bit(bs, i) ? '1' : '0';
263
268
  }
264
269
  data[bs->len] = 0;
265
270
 
@@ -276,7 +281,7 @@ static VALUE rb_bitset_from_s(VALUE self, VALUE s) {
276
281
  int i;
277
282
  for (i = 0; i < length; i++) {
278
283
  if (data[i] == '1') {
279
- set_bit(new_bs, i);
284
+ _set_bit(new_bs, i);
280
285
  }
281
286
  }
282
287
 
@@ -287,7 +292,7 @@ static VALUE rb_bitset_hamming(VALUE self, VALUE other) {
287
292
  Bitset * bs = get_bitset(self);
288
293
  Bitset * other_bs = get_bitset(other);
289
294
 
290
- int max = ((bs->len-1) >> 6) + 1;
295
+ int max = INTS(bs);
291
296
  int count = 0;
292
297
  int i;
293
298
  for(i = 0; i < max; i++) {
@@ -304,7 +309,7 @@ static VALUE rb_bitset_each(VALUE self) {
304
309
  int i;
305
310
 
306
311
  for(i = 0; i < bs->len; i++) {
307
- rb_yield(get_bit(bs, i) > 0 ? Qtrue : Qfalse);
312
+ rb_yield(_get_bit(bs, i) ? Qtrue : Qfalse);
308
313
  }
309
314
 
310
315
  return self;
@@ -335,11 +340,171 @@ static VALUE rb_bitset_marshall_load(VALUE self, VALUE hash) {
335
340
  return Qnil;
336
341
  }
337
342
 
343
+ static VALUE rb_bitset_dup(VALUE self) {
344
+ Bitset * bs = get_bitset(self);
345
+
346
+ Bitset * new_bs = bitset_new();
347
+ bitset_setup(new_bs, bs->len);
348
+
349
+ int max = INTS(bs);
350
+ memcpy(new_bs->data, bs->data, max * sizeof(bs->data[0]));
351
+ return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
352
+ }
353
+
354
+ /* Yield the bit numbers of each set bit in sequence to a block. If
355
+ there is no block, return an array of those numbers. */
356
+ static VALUE rb_bitset_each_set(VALUE self) {
357
+ Bitset * bs = get_bitset(self);
358
+ int seg_no;
359
+ int max = INTS(bs);
360
+ uint64_t* seg_ptr = bs->data;
361
+ int block_p = rb_block_given_p();
362
+ VALUE ary = Qnil;
363
+
364
+ if (!block_p) {
365
+ ary = rb_ary_new();
366
+ }
367
+
368
+ for (seg_no = 0; seg_no < max; ++seg_no, ++seg_ptr) {
369
+ uint64_t segment = *seg_ptr;
370
+ int bit_position = 0;
371
+ while (segment) {
372
+ VALUE v;
373
+
374
+ if (!(segment & 1)) {
375
+ int shift = __builtin_ctzll(segment);
376
+ bit_position += shift;
377
+ segment >>= shift;
378
+ }
379
+ v = INT2NUM(_seg_no_to_bit_no(seg_no) + bit_position);
380
+ if (block_p) {
381
+ rb_yield(v);
382
+ } else {
383
+ rb_ary_push(ary, v);
384
+ }
385
+ ++bit_position;
386
+ segment >>= 1;
387
+ }
388
+ }
389
+
390
+ return block_p ? self : ary;
391
+ }
392
+
393
+ static VALUE rb_bitset_empty_p(VALUE self) {
394
+ Bitset * bs = get_bitset(self);
395
+ int seg_no;
396
+ int max = INTS(bs);
397
+ uint64_t* seg_ptr = bs->data;
398
+
399
+ for (seg_no = 0; seg_no < max; ++seg_no, ++seg_ptr) {
400
+ if (*seg_ptr) {
401
+ return Qfalse;
402
+ }
403
+ }
404
+ return Qtrue;
405
+ }
406
+
407
+ static VALUE rb_bitset_select_bits(VALUE self, VALUE index_array) {
408
+ int i;
409
+ Bitset * bs = get_bitset(self);
410
+ struct RArray *arr = RARRAY(index_array);
411
+ int blen = bs->len;
412
+ int alen = RARRAY_LEN(index_array);
413
+ VALUE *ptr = RARRAY_PTR(index_array);
414
+ Bitset * new_bs = bitset_new();
415
+ bitset_setup(new_bs, alen);
416
+ for (i = 0; i < alen; ++i) {
417
+ int idx = NUM2INT(ptr[i]);
418
+ if (idx >= 0 && idx < blen && _get_bit(bs, idx)) {
419
+ _set_bit(new_bs, i);
420
+ }
421
+ }
422
+
423
+ return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
424
+ }
425
+
426
+ /** This could run a bit faster if you worked at it. */
427
+ static VALUE rb_bitset_reverse(VALUE self, VALUE index_array) {
428
+ int i;
429
+ Bitset * bs = get_bitset(self);
430
+ int len = bs->len;
431
+ Bitset * new_bs = bitset_new();
432
+ bitset_setup(new_bs, len);
433
+ for (i = 0; i < len; ++i) {
434
+ if (_get_bit(bs, i)) {
435
+ _set_bit(new_bs, len - i - 1);
436
+ }
437
+ }
438
+
439
+ return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
440
+ }
441
+
442
+ static VALUE rb_bitset_equal(VALUE self, VALUE other) {
443
+ int i;
444
+ Bitset * bs = get_bitset(self);
445
+ Bitset * other_bs = get_bitset(other);
446
+
447
+ if (bs->len != other_bs->len)
448
+ return Qfalse;
449
+ int max = INTS(bs);
450
+ for(i = 0; i < max; i++) {
451
+ if (bs->data[i] != other_bs->data[i]) {
452
+ return Qfalse;
453
+ }
454
+ }
455
+ return Qtrue;
456
+ }
457
+
458
+ typedef uint64_t (*bitwise_op)(uint64_t, uint64_t);
459
+ inline uint64_t and(uint64_t a, uint64_t b) { return a & b; }
460
+ inline uint64_t or(uint64_t a, uint64_t b) { return a | b; }
461
+ inline uint64_t xor(uint64_t a, uint64_t b) { return a ^ b; }
462
+ inline uint64_t difference(uint64_t a, uint64_t b) { return a & ~b; }
463
+
464
+ static VALUE mutable(VALUE self, VALUE other, bitwise_op operator) {
465
+ Bitset * bs = get_bitset(self);
466
+ Bitset * other_bs = get_bitset(other);
467
+ verify_equal_size(bs, other_bs);
468
+
469
+ int max = INTS(bs);
470
+ int i;
471
+ for(i = 0; i < max; i++) {
472
+ uint64_t segment = bs->data[i];
473
+ uint64_t other_segment = other_bs->data[i];
474
+ bs->data[i] = operator(segment, other_segment);
475
+ }
476
+
477
+ return self;
478
+ }
479
+
480
+ static VALUE rb_bitset_union_mutable(VALUE self, VALUE other) {
481
+ return mutable(self, other, &or);
482
+ }
483
+
484
+ static VALUE rb_bitset_intersect_mutable(VALUE self, VALUE other) {
485
+ return mutable(self, other, &and);
486
+ }
487
+
488
+ static VALUE rb_bitset_xor_mutable(VALUE self, VALUE other) {
489
+ return mutable(self, other, &xor);
490
+ }
491
+
492
+ static VALUE rb_bitset_difference_mutable(VALUE self, VALUE other) {
493
+ return mutable(self, other, &difference);
494
+ }
495
+
496
+ static VALUE rb_bitset_reset(VALUE self) {
497
+ Bitset * bs = get_bitset(self);
498
+ memset(bs->data, 0, (INTS(bs) * sizeof(uint64_t)) );
499
+ return self;
500
+ }
501
+
338
502
  void Init_bitset() {
339
503
  cBitset = rb_define_class("Bitset", rb_cObject);
340
504
  rb_include_module(cBitset, rb_mEnumerable);
341
505
  rb_define_alloc_func(cBitset, rb_bitset_alloc);
342
506
  rb_define_method(cBitset, "initialize", rb_bitset_initialize, 1);
507
+ rb_define_method(cBitset, "reset!", rb_bitset_reset, 0);
343
508
  rb_define_method(cBitset, "size", rb_bitset_size, 0);
344
509
  rb_define_method(cBitset, "[]", rb_bitset_aref, 1);
345
510
  rb_define_method(cBitset, "[]=", rb_bitset_aset, 2);
@@ -350,13 +515,22 @@ void Init_bitset() {
350
515
  rb_define_method(cBitset, "cardinality", rb_bitset_cardinality, 0);
351
516
  rb_define_method(cBitset, "intersect", rb_bitset_intersect, 1);
352
517
  rb_define_alias(cBitset, "&", "intersect");
518
+ rb_define_alias(cBitset, "and", "intersect");
519
+ rb_define_method(cBitset, "intersect!", rb_bitset_intersect_mutable, 1);
520
+ rb_define_alias(cBitset, "and!", "intersect!");
353
521
  rb_define_method(cBitset, "union", rb_bitset_union, 1);
354
522
  rb_define_alias(cBitset, "|", "union");
523
+ rb_define_alias(cBitset, "or", "union");
524
+ rb_define_method(cBitset, "union!", rb_bitset_union_mutable, 1);
525
+ rb_define_alias(cBitset, "or!", "union!");
355
526
  rb_define_method(cBitset, "difference", rb_bitset_difference, 1);
356
527
  rb_define_alias(cBitset, "-", "difference");
528
+ rb_define_method(cBitset, "difference!", rb_bitset_difference_mutable, 1);
357
529
  rb_define_method(cBitset, "xor", rb_bitset_xor, 1);
358
530
  rb_define_alias(cBitset, "^", "xor");
359
531
  rb_define_alias(cBitset, "symmetric_difference", "xor");
532
+ rb_define_method(cBitset, "xor!", rb_bitset_xor_mutable, 1);
533
+ rb_define_alias(cBitset, "symmetric_difference!", "xor!");
360
534
  rb_define_method(cBitset, "not", rb_bitset_not, 0);
361
535
  rb_define_alias(cBitset, "~", "not");
362
536
  rb_define_method(cBitset, "hamming", rb_bitset_hamming, 1);
@@ -365,4 +539,11 @@ void Init_bitset() {
365
539
  rb_define_singleton_method(cBitset, "from_s", rb_bitset_from_s, 1);
366
540
  rb_define_method(cBitset, "marshal_dump", rb_bitset_marshall_dump, 0);
367
541
  rb_define_method(cBitset, "marshal_load", rb_bitset_marshall_load, 1);
542
+ rb_define_method(cBitset, "dup", rb_bitset_dup, 0);
543
+ rb_define_alias(cBitset, "clone", "dup");
544
+ rb_define_method(cBitset, "each_set", rb_bitset_each_set, 0);
545
+ rb_define_method(cBitset, "empty?", rb_bitset_empty_p, 0);
546
+ rb_define_method(cBitset, "select_bits", rb_bitset_select_bits, 1);
547
+ rb_define_method(cBitset, "reverse", rb_bitset_reverse, 0);
548
+ rb_define_method(cBitset, "==", rb_bitset_equal, 1);
368
549
  }
@@ -0,0 +1,23 @@
1
+ class Bitset
2
+
3
+ # Return a string that represents this bitset packed into 8-bit
4
+ # characters. The first 3 bits represent the number of padding bits
5
+ # in the final byte of the string.
6
+
7
+ # You could make a good case that this is redundant with
8
+ # Marshal.dump and Marshal.load, but it does save a few bytes.
9
+ def pack
10
+ # Number of bits of zero padding in this representation.
11
+ padding_bits = (size+3) & 7
12
+ padding_bits = (padding_bits == 0) ? 0 : (8 - padding_bits)
13
+ [("%03b" % padding_bits) + self.to_s].pack("b*")
14
+ end
15
+
16
+ # Convert a string created using the pack method back into a bitset.
17
+ def self.unpack str
18
+ bits = str.unpack("b*")[0]
19
+ padding_bits = bits[0...3].to_i(2)
20
+ from_s(bits[3 .. -1 - padding_bits])
21
+ end
22
+
23
+ end
@@ -5,10 +5,14 @@ describe Bitset do
5
5
  Bitset.new(64)
6
6
  end
7
7
 
8
+ it 'raises ArgumentError wihen initialized with no argument' do
9
+ expect { Bitset.new }.to raise_error(ArgumentError)
10
+ end
11
+
8
12
  describe :size do
9
13
  it 'returns the correct size' do
10
- Bitset.new(64).size.should == 64
11
- Bitset.new(73).size.should == 73
14
+ expect(Bitset.new(64).size).to eq(64)
15
+ expect(Bitset.new(73).size).to eq(73)
12
16
  end
13
17
  end
14
18
 
@@ -16,17 +20,18 @@ describe Bitset do
16
20
  it 'returns True for set bits' do
17
21
  bs = Bitset.new(8)
18
22
  bs[0] = true
19
- bs[0].should == true
23
+ expect(bs[0]).to be true
20
24
  end
21
25
 
22
26
  it 'returns False for unset bits' do
23
27
  bs = Bitset.new(8)
24
- bs[0].should == false
28
+ expect(bs[0]).to be false
25
29
  end
26
30
 
27
31
  it 'raises an error when accessing out of bound indexes' do
28
32
  bs = Bitset.new(8)
29
33
  expect { bs[8] }.to raise_error(IndexError)
34
+ expect { bs[-1] }.to raise_error(IndexError)
30
35
  end
31
36
  end
32
37
 
@@ -35,23 +40,23 @@ describe Bitset do
35
40
  bs = Bitset.new(8)
36
41
 
37
42
  bs[0] = true
38
- bs[0].should == true
43
+ expect(bs[0]).to be true
39
44
 
40
45
  bs[1] = 123
41
- bs[1].should == true
46
+ expect(bs[1]).to be true
42
47
 
43
48
  bs[2] = "woo"
44
- bs[2].should == true
49
+ expect(bs[2]).to be true
45
50
  end
46
51
 
47
52
  it 'sets False for falsey values' do
48
53
  bs = Bitset.new(8)
49
54
 
50
55
  bs[0] = false
51
- bs[0].should == false
56
+ expect(bs[0]).to be false
52
57
 
53
58
  bs[1] = nil
54
- bs[1].should == false
59
+ expect(bs[1]).to be false
55
60
  end
56
61
 
57
62
  it 'raises an error when setting out of bound indexes' do
@@ -65,9 +70,10 @@ describe Bitset do
65
70
  bs = Bitset.new(8)
66
71
  bs.set 1,2,3
67
72
 
68
- bs[1].should == true
69
- bs[2].should == true
70
- bs[3].should == true
73
+ expect(bs[1]).to be true
74
+ expect(bs[0]).to be false
75
+ expect(bs[4]).to be false
76
+ expect(bs[3]).to be true
71
77
  end
72
78
  end
73
79
 
@@ -77,9 +83,9 @@ describe Bitset do
77
83
  bs.set 1,2,3
78
84
  bs.clear 1,3
79
85
 
80
- bs[1].should == false
81
- bs[2].should == true
82
- bs[3].should == false
86
+ expect(bs[1]).to be false
87
+ expect(bs[2]).to be true
88
+ expect(bs[3]).to be false
83
89
  end
84
90
  end
85
91
 
@@ -87,13 +93,13 @@ describe Bitset do
87
93
  it 'returns True if all bits indexed are set' do
88
94
  bs = Bitset.new(8)
89
95
  bs.set 1, 4, 5
90
- bs.set?(1,4,5).should == true
96
+ expect(bs.set?(1,4,5)).to be true
91
97
  end
92
98
 
93
99
  it 'returns False if not all bits indexed are set' do
94
100
  bs = Bitset.new(8)
95
101
  bs.set 1, 4
96
- bs.set?(1,4,5).should == false
102
+ expect(bs.set?(1,4,5)).to be false
97
103
  end
98
104
  end
99
105
 
@@ -101,44 +107,48 @@ describe Bitset do
101
107
  it 'returns True if all bits indexed are clear' do
102
108
  bs = Bitset.new(8)
103
109
  bs.set 1, 4, 5
104
- bs.clear?(0,2,3,6).should == true
110
+ expect(bs.clear?(0,2,3,6)).to be true
105
111
  end
106
112
 
107
113
  it 'returns works with the full range of 64 bit values' do
108
114
  bs = Bitset.new(68)
109
115
  bs.set 0, 2, 66
110
- bs.clear?(32, 33, 34).should == true
116
+ expect(bs.clear?(32, 33, 34)).to be true
111
117
  end
112
118
 
113
119
  it 'returns False if not all bits indexed are clear' do
114
120
  bs = Bitset.new(8)
115
121
  bs.set 1, 4
116
- bs.clear?(1,2,6).should == false
122
+ expect(bs.clear?(1,2,6)).to be false
117
123
  end
118
124
  end
119
125
 
120
126
  describe :cardinality do
121
127
  it 'returns the number of bits set' do
122
- bs = Bitset.new(8)
123
- bs.cardinality.should == 0
128
+ bs = Bitset.new(64)
129
+ expect(bs.cardinality).to eq(0)
124
130
 
125
131
  bs[0] = true
126
- bs.cardinality.should == 1
132
+ expect(bs.cardinality).to eq(1)
127
133
 
128
134
  bs[1] = true
129
- bs.cardinality.should == 2
135
+ expect(bs.cardinality).to eq(2)
130
136
 
131
137
  bs[2] = true
132
- bs.cardinality.should == 3
138
+ expect(bs.cardinality).to eq(3)
139
+
140
+ expect(bs.not.cardinality).to eq(bs.size - bs.cardinality)
133
141
  end
134
142
 
135
143
  it '... even for large numbers of bits' do
136
144
  bs = Bitset.new(10_000)
137
- bs.set(*(0...5000).to_a)
138
- bs.cardinality.should == 5000
145
+ size = 5000
146
+ bs.set(*(0...size).to_a)
147
+ expect(bs.cardinality).to eq(size)
139
148
 
140
149
  bs = Bitset.from_s "01001101000000000000000000000011000010100100000000000000010000101000000000000000100000000100000000000010100100010000000010000100000100000001001000110000000000100010000000010100000000000000110000000000000000000000000100000000100010010000000000000000000001000000000000000000000000000001000000000000000000000000000100000000010010000000000000000000100100000000000000001000000010000001000000000000001000001100010001000000000000001000001000001000000000000001100010000010010001000000010000100000000000110000"
141
- bs.cardinality.should == 63
150
+ expect(bs.cardinality).to eq(63)
151
+ expect(bs.not.cardinality).to eq(bs.size - bs.cardinality)
142
152
  end
143
153
  end
144
154
 
@@ -151,8 +161,8 @@ describe Bitset do
151
161
  bs2.set 1, 2, 4, 6
152
162
 
153
163
  bs3 = bs1 & bs2
154
- bs3.set?(1,4).should == true
155
- bs3.clear?(0,2,3,5,6,7).should == true
164
+ expect(bs3.set?(1,4)).to be true
165
+ expect(bs3.clear?(0,2,3,5,6,7)).to be true
156
166
  end
157
167
  end
158
168
 
@@ -165,8 +175,11 @@ describe Bitset do
165
175
  bs2.set 1, 2, 4, 6
166
176
 
167
177
  bs3 = bs1 | bs2
168
- bs3.set?(1,2,4,6,7).should == true
169
- bs3.clear?(0,3,5).should == true
178
+ expect(bs3.set?(1,2,4,6,7)).to be true
179
+ expect(bs3.clear?(0,3,5)).to be true
180
+ end
181
+ it 'throws if size mismatch' do
182
+ expect { Bitset.new(3) | Bitset.new(7) }.to raise_error(ArgumentError)
170
183
  end
171
184
  end
172
185
 
@@ -179,8 +192,11 @@ describe Bitset do
179
192
  bs2.set 1, 2, 4, 6
180
193
 
181
194
  bs3 = bs1 - bs2
182
- bs3.set?(7).should == true
183
- bs3.clear?(0,1,2,3,4,5,6).should == true
195
+ expect(bs3.set?(7)).to be true
196
+ expect(bs3.clear?(0,1,2,3,4,5,6)).to be true
197
+ end
198
+ it 'throws if size mismatch' do
199
+ expect { Bitset.new(3) - Bitset.new(7) }.to raise_error(ArgumentError)
184
200
  end
185
201
  end
186
202
 
@@ -193,19 +209,23 @@ describe Bitset do
193
209
  bs2.set 1, 2, 4, 6
194
210
 
195
211
  bs3 = bs1 ^ bs2
196
- bs3.set?(2,6,7).should == true
197
- bs3.clear?(0,1,3,4,5).should == true
212
+ expect(bs3.set?(2,6,7)).to be true
213
+ expect(bs3.clear?(0,1,3,4,5)).to be true
214
+ end
215
+
216
+ it 'throws if size mismatch' do
217
+ expect { Bitset.new(3) ^ Bitset.new(7) }.to raise_error(ArgumentError)
198
218
  end
199
219
  end
200
220
 
201
221
  describe :not do
202
- it "returns a new Bitset with is the not of one Bitset" do
222
+ it "returns a new Bitset which is the not of one Bitset" do
203
223
  bs1 = Bitset.new(8)
204
224
  bs1.set 1, 4, 7
205
225
 
206
226
  bs2 = bs1.not
207
- bs2.set?(0, 2, 3, 5, 6).should == true
208
- bs2.clear?(1, 4, 7).should == true
227
+ expect(bs2.set?(0, 2, 3, 5, 6)).to be true
228
+ expect(bs2.clear?(1, 4, 7)).to be true
209
229
  end
210
230
  end
211
231
 
@@ -217,7 +237,7 @@ describe Bitset do
217
237
  bs2 = Bitset.new(8)
218
238
  bs2.set 1, 2, 4, 6
219
239
 
220
- bs1.hamming(bs2).should == 3
240
+ expect(bs1.hamming(bs2)).to eq(3)
221
241
  end
222
242
  end
223
243
 
@@ -228,10 +248,50 @@ describe Bitset do
228
248
 
229
249
  i = 0
230
250
  bs.each do |bit|
231
- bit.should == bs[i]
251
+ expect(bit).to be bs[i]
232
252
  i += 1
233
253
  end
234
- i.should == 4
254
+ expect(i).to eq(4)
255
+ end
256
+ end
257
+
258
+ describe :each_set do
259
+ it 'iterates over each set bit in the Bitset' do
260
+ bs = Bitset.new(4)
261
+ sets = [0,3]
262
+ bs.set(*sets)
263
+ sets2 = []
264
+ bs.each_set { |bit| sets2 << bit }
265
+ expect(sets2).to eq(sets)
266
+ end
267
+
268
+ it 'without a block, it returns an array of set bits' do
269
+ bs = Bitset.new(4)
270
+ sets = [0,3]
271
+ bs.set(*sets)
272
+ expect(bs.each_set).to eq(sets)
273
+ end
274
+ end
275
+
276
+ describe :empty? do
277
+ it 'returns empty only if all zeroes' do
278
+ expect(Bitset.new(225).tap { |bs| bs[133] = true }.empty?).to be false
279
+ expect(Bitset.new(0).empty?).to be true
280
+ expect(Bitset.new(225).empty?).to be true
281
+ end
282
+ end
283
+
284
+ describe :dup do
285
+ it "returns a duplicate" do
286
+ bs = Bitset.from_s("11011")
287
+ expect(bs.dup.tap { |bs| bs.clear 1,3 }.to_s).to eq("10001")
288
+ expect(bs.to_s).to eq("11011")
289
+ end
290
+ end
291
+
292
+ describe :clone do
293
+ it "works" do
294
+ expect(Bitset.new(0).clone.to_s).to eq("")
235
295
  end
236
296
  end
237
297
 
@@ -239,18 +299,18 @@ describe Bitset do
239
299
  it 'correctly prints out a binary string' do
240
300
  bs = Bitset.new(4)
241
301
  bs.set 0, 2
242
- bs.to_s.should == "1010"
302
+ expect(bs.to_s).to eq("1010")
243
303
 
244
304
  bs = Bitset.new(68)
245
305
  bs.set 0, 2, 66
246
- bs.to_s.should == "101" + ("0" * 63) + "10"
306
+ expect(bs.to_s).to eq("101" + ("0" * 63) + "10")
247
307
  end
248
308
  end
249
309
 
250
310
  describe :from_s do
251
311
  it 'correctly creates a bitmap from a binary string' do
252
312
  bs = Bitset.from_s("10101")
253
- bs.set?(0, 2, 4).should == true
313
+ expect(bs.set?(0, 2, 4)).to be true
254
314
  end
255
315
  end
256
316
 
@@ -260,8 +320,65 @@ describe Bitset do
260
320
  bs.set 1, 65
261
321
 
262
322
  serialized = Marshal.load(Marshal.dump(bs))
263
- serialized.set?(1, 65).should == true
264
- serialized.cardinality.should == 2
323
+ expect(serialized.set?(1, 65)).to be true
324
+ expect(serialized.cardinality).to eq(2)
325
+ end
326
+ end
327
+
328
+ describe :union! do
329
+ it 'acts like |=' do
330
+ bs = Bitset.from_s "11011"
331
+ bs2 = Bitset.from_s "01111"
332
+ bs3 = bs.dup
333
+ bs.union!(bs2)
334
+ expect(bs).to eq(bs3 | bs2)
335
+ end
336
+
337
+ it 'throws if size mismatch' do
338
+ expect { Bitset.new(3).union!(Bitset.new(7)) }.to raise_error(ArgumentError)
339
+ end
340
+ end
341
+
342
+ describe :intersect! do
343
+ it 'acts like &=' do
344
+ bs = Bitset.from_s "11011"
345
+ bs2 = Bitset.from_s "01111"
346
+ bs3 = bs.dup
347
+ bs.intersect!(bs2)
348
+ expect(bs).to eq(bs3 & bs2)
349
+ end
350
+ end
351
+
352
+ describe :xor! do
353
+ it 'acts like ^=' do
354
+ bs = Bitset.from_s "11011"
355
+ bs2 = Bitset.from_s "01111"
356
+ bs3 = bs.dup
357
+ bs.xor!(bs2)
358
+ expect(bs).to eq(bs3 ^ bs2)
359
+ end
360
+
361
+ it 'throws if size mismatch' do
362
+ expect { Bitset.new(3).xor!(Bitset.new(7)) }.to raise_error(ArgumentError)
265
363
  end
266
364
  end
365
+
366
+ describe :difference! do
367
+ it 'acts like -=' do
368
+ bs = Bitset.from_s "11011"
369
+ bs2 = Bitset.from_s "01111"
370
+ bs3 = bs.dup
371
+ bs.difference!(bs2)
372
+ expect(bs).to eq(bs3 - bs2)
373
+ end
374
+ end
375
+
376
+ describe :reset! do
377
+ it 'causes empty? to become true' do
378
+ bs = Bitset.from_s "11011"
379
+ bs.reset!
380
+ expect(bs.empty?).to be true
381
+ end
382
+ end
383
+
267
384
  end
metadata CHANGED
@@ -1,72 +1,56 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: bitset
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 1
8
- - 0
9
- version: 0.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Tyler McMullen
13
8
  autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
-
17
- date: 2011-03-03 00:00:00 -08:00
18
- default_executable:
11
+ date: 2017-05-15 00:00:00.000000000 Z
19
12
  dependencies: []
20
-
21
- description: A fast C-based Bitset. It supports the standard set operations as well as operations you may expect on bit arrays. (popcount, for instance)
22
- email: tbmcmullen@gmail.com
13
+ description: A fast C-based Bitset. It supports the standard set operations as well
14
+ as operations you may expect on bit arrays. (popcount, for instance)
15
+ email: eric.boesch@nist.gov
23
16
  executables: []
24
-
25
- extensions:
17
+ extensions:
26
18
  - ext/bitset/extconf.rb
27
- extra_rdoc_files:
19
+ extra_rdoc_files:
28
20
  - LICENSE.txt
29
- - README.rdoc
30
- files:
21
+ - README.markdown
22
+ files:
31
23
  - LICENSE.txt
32
- - README.rdoc
24
+ - README.markdown
33
25
  - Rakefile
34
26
  - VERSION
35
27
  - bitset.gemspec
36
28
  - ext/bitset/bitset.c
37
29
  - ext/bitset/extconf.rb
30
+ - lib/bitset/bitset.rb
38
31
  - spec/bitset_spec.rb
39
- has_rdoc: true
40
- homepage: http://github.com/tyler/bitset
41
- licenses:
32
+ homepage: http://github.com/ericboesch/bitset
33
+ licenses:
42
34
  - MIT
35
+ metadata: {}
43
36
  post_install_message:
44
37
  rdoc_options: []
45
-
46
- require_paths:
38
+ require_paths:
47
39
  - lib
48
- required_ruby_version: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
51
42
  - - ">="
52
- - !ruby/object:Gem::Version
53
- segments:
54
- - 0
55
- version: "0"
56
- required_rubygems_version: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
59
47
  - - ">="
60
- - !ruby/object:Gem::Version
61
- segments:
62
- - 0
63
- version: "0"
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
64
50
  requirements: []
65
-
66
51
  rubyforge_project:
67
- rubygems_version: 1.3.7
52
+ rubygems_version: 2.6.12
68
53
  signing_key:
69
- specification_version: 3
54
+ specification_version: 4
70
55
  summary: Bitset implementation.
71
- test_files:
72
- - spec/bitset_spec.rb
56
+ test_files: []
@@ -1,3 +0,0 @@
1
- = Bitset
2
-
3
- A fast Bitset implementation for Ruby. Available as the 'bitset' gem.