bitset_bm 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZTlmMTRmMmFiYjI4NGJlY2RjZWJlMzA1MTYzZGRiZTg4MDQ3NjQxOA==
5
+ data.tar.gz: !binary |-
6
+ NDMxOTEyNzgxODUwYjA5ZTMxY2MwYzIwMzMwZmFkNzgzOWI5ODUyNg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZWI3Mzc4ZjM0MGZjMTE3ZjUyNzI5NWIyYTMyNmQxYWZmMGZjYWZkYjU3MDYz
10
+ ZmU4MmIzMTU2NDA4MTM2MzFlMjc5YTE2MjE4MDQxNWZhMjhhMjNmMTFlMzQ3
11
+ ODQzNTA1MDlkMjM4OGFiN2EyOTliNzExMTk4MWY1ODdmYTk0YmU=
12
+ data.tar.gz: !binary |-
13
+ NDNjZjJlMzFlMmE4MWEyNDZkYWNiMzhiNTZiZmE3OTlkNDU1Mjg1MzE3N2U1
14
+ NTU0YzI5YWFjMzE2MjYxZmE3MTc2MTlhNTAzNjJiOGRiNWMxNDkwN2NlOGY2
15
+ NzliOWQwY2Y1MTAwYjk3YWY4ZGZmZTU3ZTU1YzRiM2E1YjRiMWE=
data/.gitignore ADDED
@@ -0,0 +1,46 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # Rubymine
15
+ .idea
16
+
17
+ # Compiler artifacts
18
+ tmp
19
+ lib/bitset.bundle
20
+
21
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
22
+ #
23
+ # * Create a file at ~/.gitignore
24
+ # * Include files you want ignored
25
+ # * Run: git config --global core.excludesfile ~/.gitignore
26
+ #
27
+ # After doing this, these files will be ignored in all your git projects,
28
+ # saving you from having to 'pollute' every project you touch with them
29
+ #
30
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
31
+ #
32
+ # For MacOS:
33
+ #
34
+ #.DS_Store
35
+ #
36
+ # For TextMate
37
+ #*.tmproj
38
+ #tmtags
39
+ #
40
+ # For emacs:
41
+ #*~
42
+ #\#*
43
+ #.\#*
44
+ #
45
+ # For vim:
46
+ #*.swp
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ - "2.1.1"
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,29 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bitset_bm (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.5)
10
+ rake (10.3.2)
11
+ rake-compiler (0.9.2)
12
+ rake
13
+ rspec (2.99.0)
14
+ rspec-core (~> 2.99.0)
15
+ rspec-expectations (~> 2.99.0)
16
+ rspec-mocks (~> 2.99.0)
17
+ rspec-core (2.99.1)
18
+ rspec-expectations (2.99.2)
19
+ diff-lcs (>= 1.1.3, < 2.0)
20
+ rspec-mocks (2.99.2)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ bitset_bm!
27
+ rake (~> 10.1)
28
+ rake-compiler (~> 0.9, >= 0.9.2)
29
+ rspec (~> 2.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Tyler McMullen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,108 @@
1
+ Bitset [![Build Status](https://travis-ci.org/brendon9x/bitset.svg?branch=master)](https://travis-ci.org/brendon9x/bitset)
2
+ ======
3
+
4
+ A fast Bitset implementation for Ruby. Available as the 'bitset' gem. This is a fork of tyler/bitset which adds the
5
+ following functionality:
6
+
7
+ * Switch to Bundler's Gemspec defaults
8
+ * Bug fix for a 64 bit cardinality bug
9
+ * Adds a to_a method which returns on positions
10
+ * Adds a to_binary_array which returns fixnum 1s and 0s
11
+ * Other fixes and features are merged upstream
12
+
13
+
14
+ Installation
15
+ ------------
16
+
17
+ Usually you want to do this:
18
+
19
+ gem install bitset
20
+
21
+ But if you want the latest patches or want to work on it yourself, you may want
22
+ to do this:
23
+
24
+ git clone git://github.com/brendon9x/bitset.git
25
+ cd bitset
26
+ rake build
27
+ gem install pkg/bitset-<version>.gem
28
+
29
+
30
+ Usage
31
+ -----
32
+
33
+ You create a bitset like this:
34
+
35
+ >> Bitset.new(8)
36
+ => 00000000
37
+
38
+ Here we created an 8-bit bitset. All bits are initialized to 0.
39
+
40
+ We can also create a bitset based on a string of ones and zeros.
41
+
42
+ >> Bitset.from_s('00010001')
43
+ => 00010001
44
+
45
+ Obviously you can also set and clear bits...
46
+
47
+ >> bitset = Bitset.new(8)
48
+ => 00000000
49
+
50
+ >> bitset[3] = true
51
+ => 00010000
52
+
53
+ >> bitset[3] = false
54
+ => 00000000
55
+
56
+ >> bitset.set(1, 3, 5, 7)
57
+ => 01010101
58
+
59
+ >> bitset.clear(1, 5)
60
+ => 00010001
61
+
62
+ The point of a bitset is to be, effectively, an array of single bits. It should
63
+ support basic set and bitwise operations. So, let's look at a few of those.
64
+
65
+ >> a = Bitset.from_s('00001111')
66
+ => 00001111
67
+
68
+ >> b = Bitset.from_s('01010101')
69
+ => 01010101
70
+
71
+ >> a & b
72
+ => 00000101
73
+
74
+ >> a | b
75
+ => 01011111
76
+
77
+ >> b - a
78
+ => 01010000
79
+
80
+ >> a ^ b
81
+ => 01011010
82
+
83
+ >> ~a
84
+ => 11110000
85
+
86
+ >> a.hamming(b)
87
+ => 4
88
+
89
+ >> a.cardinality
90
+ => 4
91
+
92
+
93
+ Contributing
94
+ ------------
95
+
96
+ The best way to contribute is to fork the project on GitHub, make your changes,
97
+ and send a pull request. This is always much appreciated. If you want to mess
98
+ around with the version numbers, gemspec, or anything like that feel free... But
99
+ do it in separate commits so I can easily ignore them.
100
+
101
+
102
+ License
103
+ -------
104
+
105
+ See LICENSE.txt.
106
+
107
+
108
+ ### Thanks for using Bitset!
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ require 'rake/extensiontask'
4
+
5
+ gemspec = Gem::Specification.load('bitset.gemspec')
6
+ Rake::ExtensionTask.new do |ext|
7
+ ext.name = 'bitset'
8
+ ext.source_pattern = "*.{c}"
9
+ ext.ext_dir = 'ext/bitset'
10
+ ext.gem_spec = gemspec
11
+ end
12
+
13
+ desc "Run specs"
14
+ RSpec::Core::RakeTask.new do |t|
15
+ t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
16
+ # Put spec opts in a file named .rspec in root
17
+ end
18
+
19
+ task :default => [:compile, :spec]
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.3
data/bitset.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'bitset/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "bitset_bm"
9
+ s.version = BitsetVersion::VERSION
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.authors = ["Tyler McMullen", "Brendon McLean"]
13
+ s.date = %q{2011-10-06}
14
+ 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)}
15
+ s.email = %q{tbmcmullen@gmail.com}
16
+ s.extensions = ["ext/bitset/extconf.rb"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.markdown"
20
+ ]
21
+ s.files = `git ls-files`.split($/)
22
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
23
+ s.homepage = %q{http://github.com/brendon9x/bitset}
24
+ s.licenses = ["MIT"]
25
+ s.require_paths = ["lib"]
26
+ s.rubygems_version = %q{1.6.2}
27
+ s.summary = %q{Bitset implementation.}
28
+
29
+ s.add_development_dependency "rspec", "~> 2.0"
30
+ s.add_development_dependency "rake", "~> 10.1"
31
+ s.add_development_dependency 'rake-compiler', '~> 0.9', '>= 0.9.2'
32
+ end
33
+
@@ -0,0 +1,396 @@
1
+ #include "ruby.h"
2
+
3
+ #include <stdint.h>
4
+ #include <string.h>
5
+ #include <stdio.h>
6
+
7
+ VALUE cBitset;
8
+
9
+ typedef struct {
10
+ int len;
11
+ uint64_t * data;
12
+ } Bitset;
13
+
14
+ #define BYTES(_bs) (((_bs->len-1) >> 3) + 1)
15
+ #define INTS(_bs) (((_bs->len-1) >> 6) + 1)
16
+
17
+ Bitset * bitset_new() {
18
+ return (Bitset *) malloc(sizeof(Bitset));
19
+ }
20
+
21
+ void bitset_setup(Bitset * bs, int len) {
22
+ bs->len = len;
23
+ bs->data = (uint64_t *) calloc((((bs->len-1) >> 6) + 1), sizeof(uint64_t)); // 2^6=64
24
+ }
25
+
26
+ void bitset_free(Bitset * bs) {
27
+ if(bs->data)
28
+ free(bs->data);
29
+ free(bs);
30
+ }
31
+
32
+
33
+ Bitset * get_bitset(VALUE obj) {
34
+ Bitset * bs;
35
+ Data_Get_Struct(obj, Bitset, bs);
36
+ return bs;
37
+ }
38
+
39
+ static VALUE rb_bitset_alloc(VALUE klass) {
40
+ VALUE obj;
41
+ obj = Data_Wrap_Struct(klass, 0, bitset_free, bitset_new());
42
+ return obj;
43
+ }
44
+
45
+ static VALUE rb_bitset_initialize(VALUE self, VALUE len) {
46
+ Bitset * bs = get_bitset(self);
47
+ bitset_setup(bs, NUM2INT(len));
48
+ return self;
49
+ }
50
+
51
+ static VALUE rb_bitset_size(VALUE self, VALUE len) {
52
+ Bitset * bs = get_bitset(self);
53
+ return INT2NUM(bs->len);
54
+ }
55
+
56
+ void raise_index_error() {
57
+ VALUE rb_eIndexError = rb_const_get(rb_cObject, rb_intern("IndexError"));
58
+ rb_raise(rb_eIndexError, "Index out of bounds");
59
+ }
60
+
61
+ #define _bit_segment(bit) ((bit) >> 6UL)
62
+ #define _bit_mask(bit) (((uint64_t) 1) << ((bit) & 0x3f))
63
+
64
+ void validate_index(Bitset * bs, int idx) {
65
+ if(idx < 0 || idx >= bs->len)
66
+ raise_index_error();
67
+ }
68
+
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);
80
+ }
81
+
82
+ void assign_bit(Bitset * bs, int idx, VALUE value) {
83
+ if(NIL_P(value) || value == Qfalse)
84
+ clear_bit(bs, idx);
85
+ else
86
+ set_bit(bs, idx);
87
+ }
88
+
89
+ static VALUE rb_bitset_aref(VALUE self, VALUE index) {
90
+ Bitset * bs = get_bitset(self);
91
+ int idx = NUM2INT(index);
92
+ validate_index(bs, idx);
93
+ return get_bit(bs, idx) > 0 ? Qtrue : Qfalse;
94
+ }
95
+
96
+ static VALUE rb_bitset_aset(VALUE self, VALUE index, VALUE value) {
97
+ Bitset * bs = get_bitset(self);
98
+ int idx = NUM2INT(index);
99
+ validate_index(bs, idx);
100
+ assign_bit(bs, idx, value);
101
+ return Qtrue;
102
+ }
103
+
104
+ static VALUE rb_bitset_set(int argc, VALUE * argv, VALUE self) {
105
+ int i;
106
+ Bitset * bs = get_bitset(self);
107
+ for(i = 0; i < argc; i++) {
108
+ VALUE index = argv[i];
109
+ int idx = NUM2INT(index);
110
+ validate_index(bs, idx);
111
+ set_bit(bs, idx);
112
+ }
113
+ return Qtrue;
114
+ }
115
+
116
+ static VALUE rb_bitset_clear(int argc, VALUE * argv, VALUE self) {
117
+ int i;
118
+ Bitset * bs = get_bitset(self);
119
+ for(i = 0; i < argc; i++) {
120
+ VALUE index = argv[i];
121
+ int idx = NUM2INT(index);
122
+ validate_index(bs, idx);
123
+ clear_bit(bs, idx);
124
+ }
125
+ return Qtrue;
126
+ }
127
+
128
+ static VALUE rb_bitset_clear_p(int argc, VALUE * argv, VALUE self) {
129
+ int i;
130
+ Bitset * bs = get_bitset(self);
131
+ for(i = 0; i < argc; i++) {
132
+ VALUE index = argv[i];
133
+ int idx = NUM2INT(index);
134
+ validate_index(bs, idx);
135
+ if(get_bit(bs, idx) > 0)
136
+ return Qfalse;
137
+ }
138
+ return Qtrue;
139
+ }
140
+
141
+ static VALUE rb_bitset_set_p(int argc, VALUE * argv, VALUE self) {
142
+ int i;
143
+ Bitset * bs = get_bitset(self);
144
+ for(i = 0; i < argc; i++) {
145
+ VALUE index = argv[i];
146
+ int idx = NUM2INT(index);
147
+ validate_index(bs, idx);
148
+ if(get_bit(bs, idx) == 0)
149
+ return Qfalse;
150
+ }
151
+ return Qtrue;
152
+ }
153
+
154
+ static VALUE rb_bitset_cardinality(VALUE self) {
155
+ Bitset * bs = get_bitset(self);
156
+ int i;
157
+ int max = ((bs->len-1) >> 6) + 1;
158
+ int count = 0;
159
+ for(i = 0; i < max; i++) {
160
+ uint64_t segment = bs->data[i];
161
+ if(i+1 == max && (bs->len & 0x3F))
162
+ segment &= ((((uint64_t) 1) << (bs->len & 0x3F)) - 1);
163
+ count += __builtin_popcountll(segment);
164
+ }
165
+ return INT2NUM(count);
166
+ }
167
+
168
+ static VALUE rb_bitset_intersect(VALUE self, VALUE other) {
169
+ Bitset * bs = get_bitset(self);
170
+ Bitset * other_bs = get_bitset(other);
171
+
172
+ Bitset * new_bs = bitset_new();
173
+ bitset_setup(new_bs, bs->len);
174
+
175
+ int max = ((bs->len-1) >> 6) + 1;
176
+ int i;
177
+ for(i = 0; i < max; i++) {
178
+ uint64_t segment = bs->data[i];
179
+ uint64_t other_segment = other_bs->data[i];
180
+ new_bs->data[i] = segment & other_segment;
181
+ }
182
+
183
+ return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
184
+ }
185
+
186
+ static VALUE rb_bitset_union(VALUE self, VALUE other) {
187
+ Bitset * bs = get_bitset(self);
188
+ Bitset * other_bs = get_bitset(other);
189
+
190
+ Bitset * new_bs = bitset_new();
191
+ bitset_setup(new_bs, bs->len);
192
+
193
+ int max = ((bs->len-1) >> 6) + 1;
194
+ int i;
195
+ for(i = 0; i < max; i++) {
196
+ uint64_t segment = bs->data[i];
197
+ uint64_t other_segment = other_bs->data[i];
198
+ new_bs->data[i] = segment | other_segment;
199
+ }
200
+
201
+ return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
202
+ }
203
+
204
+ static VALUE rb_bitset_difference(VALUE self, VALUE other) {
205
+ Bitset * bs = get_bitset(self);
206
+ Bitset * other_bs = get_bitset(other);
207
+
208
+ Bitset * new_bs = bitset_new();
209
+ bitset_setup(new_bs, bs->len);
210
+
211
+ int max = ((bs->len-1) >> 6) + 1;
212
+ int i;
213
+ for(i = 0; i < max; i++) {
214
+ uint64_t segment = bs->data[i];
215
+ uint64_t other_segment = other_bs->data[i];
216
+ new_bs->data[i] = segment & ~other_segment;
217
+ }
218
+
219
+ return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
220
+ }
221
+
222
+ static VALUE rb_bitset_xor(VALUE self, VALUE other) {
223
+ Bitset * bs = get_bitset(self);
224
+ Bitset * other_bs = get_bitset(other);
225
+
226
+ Bitset * new_bs = bitset_new();
227
+ bitset_setup(new_bs, bs->len);
228
+
229
+ int max = ((bs->len-1) >> 6) + 1;
230
+ int i;
231
+ for(i = 0; i < max; i++) {
232
+ uint64_t segment = bs->data[i];
233
+ uint64_t other_segment = other_bs->data[i];
234
+ new_bs->data[i] = segment ^ other_segment;
235
+ }
236
+
237
+ return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
238
+ }
239
+
240
+ static VALUE rb_bitset_not(VALUE self) {
241
+ Bitset * bs = get_bitset(self);
242
+
243
+ Bitset * new_bs = bitset_new();
244
+ bitset_setup(new_bs, bs->len);
245
+
246
+ int max = ((bs->len-1) >> 6) + 1;
247
+ int i;
248
+ for(i = 0; i < max; i++) {
249
+ uint64_t segment = bs->data[i];
250
+ new_bs->data[i] = ~segment;
251
+ }
252
+
253
+ return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
254
+ }
255
+
256
+ static VALUE rb_bitset_to_s(VALUE self) {
257
+ Bitset * bs = get_bitset(self);
258
+
259
+ int i;
260
+ char * data = malloc(bs->len + 1);
261
+ for(i = 0; i < bs->len; i++) {
262
+ data[i] = get_bit(bs, i) ? '1' : '0';
263
+ }
264
+ data[bs->len] = 0;
265
+
266
+ return rb_str_new2(data);
267
+ }
268
+
269
+ static VALUE rb_bitset_from_s(VALUE self, VALUE s) {
270
+ int length = RSTRING_LEN(s);
271
+ char* data = StringValuePtr(s);
272
+
273
+ Bitset * new_bs = bitset_new();
274
+ bitset_setup(new_bs, length);
275
+
276
+ int i;
277
+ for (i = 0; i < length; i++) {
278
+ if (data[i] == '1') {
279
+ set_bit(new_bs, i);
280
+ }
281
+ }
282
+
283
+ return Data_Wrap_Struct(cBitset, 0, bitset_free, new_bs);
284
+ }
285
+
286
+ static VALUE rb_bitset_hamming(VALUE self, VALUE other) {
287
+ Bitset * bs = get_bitset(self);
288
+ Bitset * other_bs = get_bitset(other);
289
+
290
+ int max = ((bs->len-1) >> 6) + 1;
291
+ int count = 0;
292
+ int i;
293
+ for(i = 0; i < max; i++) {
294
+ uint64_t segment = bs->data[i];
295
+ uint64_t other_segment = other_bs->data[i];
296
+ count += __builtin_popcountll(segment ^ other_segment);
297
+ }
298
+
299
+ return INT2NUM(count);
300
+ }
301
+
302
+ static VALUE rb_bitset_each(VALUE self) {
303
+ Bitset * bs = get_bitset(self);
304
+ int i;
305
+
306
+ for(i = 0; i < bs->len; i++) {
307
+ rb_yield(get_bit(bs, i) > 0 ? Qtrue : Qfalse);
308
+ }
309
+
310
+ return self;
311
+ }
312
+
313
+ static VALUE rb_bitset_marshall_dump(VALUE self) {
314
+ Bitset * bs = get_bitset(self);
315
+ VALUE hash = rb_hash_new();
316
+ VALUE data = rb_str_new(bs->data, BYTES(bs));
317
+
318
+ rb_hash_aset(hash, ID2SYM(rb_intern("len")), UINT2NUM(bs->len));
319
+ rb_hash_aset(hash, ID2SYM(rb_intern("data")), data);
320
+
321
+ return hash;
322
+ }
323
+
324
+ static VALUE rb_bitset_marshall_load(VALUE self, VALUE hash) {
325
+ Bitset * bs = get_bitset(self);
326
+ int len = NUM2INT(rb_hash_aref(hash, ID2SYM(rb_intern("len"))));
327
+
328
+ VALUE data = rb_hash_aref(hash, ID2SYM(rb_intern("data")));
329
+
330
+ bitset_setup(bs, len);
331
+
332
+ bs->data = (uint64_t *) calloc(INTS(bs), sizeof(uint64_t));
333
+ memcpy(bs->data, RSTRING_PTR(data), BYTES(bs));
334
+
335
+ return Qnil;
336
+ }
337
+
338
+ static VALUE rb_bitset_to_a(VALUE self) {
339
+ Bitset * bs = get_bitset(self);
340
+ int i;
341
+
342
+ VALUE array = rb_ary_new2(bs->len / 2);
343
+ for(i = 0; i < bs->len; i++) {
344
+ if (get_bit(bs, i) > 0) {
345
+ rb_ary_push(array, INT2NUM(i));
346
+ }
347
+ }
348
+
349
+ return array;
350
+ }
351
+
352
+ static VALUE rb_bitset_to_binary_array(VALUE self) {
353
+ Bitset * bs = get_bitset(self);
354
+ int i;
355
+
356
+ VALUE array = rb_ary_new2(bs->len / 2);
357
+ for(i = 0; i < bs->len; i++) {
358
+ rb_ary_push(array, INT2NUM(get_bit(bs, i) > 0 ? 1 : 0));
359
+ }
360
+
361
+ return array;
362
+ }
363
+
364
+ void Init_bitset() {
365
+ cBitset = rb_define_class("Bitset", rb_cObject);
366
+ rb_include_module(cBitset, rb_mEnumerable);
367
+ rb_define_alloc_func(cBitset, rb_bitset_alloc);
368
+ rb_define_method(cBitset, "initialize", rb_bitset_initialize, 1);
369
+ rb_define_method(cBitset, "size", rb_bitset_size, 0);
370
+ rb_define_method(cBitset, "[]", rb_bitset_aref, 1);
371
+ rb_define_method(cBitset, "[]=", rb_bitset_aset, 2);
372
+ rb_define_method(cBitset, "set", rb_bitset_set, -1);
373
+ rb_define_method(cBitset, "clear", rb_bitset_clear, -1);
374
+ rb_define_method(cBitset, "set?", rb_bitset_set_p, -1);
375
+ rb_define_method(cBitset, "clear?", rb_bitset_clear_p, -1);
376
+ rb_define_method(cBitset, "cardinality", rb_bitset_cardinality, 0);
377
+ rb_define_method(cBitset, "intersect", rb_bitset_intersect, 1);
378
+ rb_define_alias(cBitset, "&", "intersect");
379
+ rb_define_method(cBitset, "union", rb_bitset_union, 1);
380
+ rb_define_alias(cBitset, "|", "union");
381
+ rb_define_method(cBitset, "difference", rb_bitset_difference, 1);
382
+ rb_define_alias(cBitset, "-", "difference");
383
+ rb_define_method(cBitset, "xor", rb_bitset_xor, 1);
384
+ rb_define_alias(cBitset, "^", "xor");
385
+ rb_define_alias(cBitset, "symmetric_difference", "xor");
386
+ rb_define_method(cBitset, "not", rb_bitset_not, 0);
387
+ rb_define_alias(cBitset, "~", "not");
388
+ rb_define_method(cBitset, "hamming", rb_bitset_hamming, 1);
389
+ rb_define_method(cBitset, "each", rb_bitset_each, 0);
390
+ rb_define_method(cBitset, "to_s", rb_bitset_to_s, 0);
391
+ rb_define_singleton_method(cBitset, "from_s", rb_bitset_from_s, 1);
392
+ rb_define_method(cBitset, "marshal_dump", rb_bitset_marshall_dump, 0);
393
+ rb_define_method(cBitset, "marshal_load", rb_bitset_marshall_load, 1);
394
+ rb_define_method(cBitset, "to_a", rb_bitset_to_a, 0);
395
+ rb_define_method(cBitset, "to_binary_array", rb_bitset_to_binary_array, 0);
396
+ }
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'bitset'
@@ -0,0 +1,3 @@
1
+ module BitsetVersion
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,290 @@
1
+ require 'bitset'
2
+
3
+ describe Bitset do
4
+ it 'can be initialized' do
5
+ Bitset.new(64)
6
+ end
7
+
8
+ describe :size do
9
+ it 'returns the correct size' do
10
+ Bitset.new(64).size.should == 64
11
+ Bitset.new(73).size.should == 73
12
+ end
13
+ end
14
+
15
+ describe :[] do
16
+ it 'returns True for set bits' do
17
+ bs = Bitset.new(8)
18
+ bs[0] = true
19
+ bs[0].should == true
20
+ end
21
+
22
+ it 'returns False for unset bits' do
23
+ bs = Bitset.new(8)
24
+ bs[0].should == false
25
+ end
26
+
27
+ it 'raises an error when accessing out of bound indexes' do
28
+ bs = Bitset.new(8)
29
+ expect { bs[8] }.to raise_error(IndexError)
30
+ end
31
+ end
32
+
33
+ describe :[]= do
34
+ it 'sets True for truthy values' do
35
+ bs = Bitset.new(8)
36
+
37
+ bs[0] = true
38
+ bs[0].should == true
39
+
40
+ bs[1] = 123
41
+ bs[1].should == true
42
+
43
+ bs[2] = "woo"
44
+ bs[2].should == true
45
+ end
46
+
47
+ it 'sets False for falsey values' do
48
+ bs = Bitset.new(8)
49
+
50
+ bs[0] = false
51
+ bs[0].should == false
52
+
53
+ bs[1] = nil
54
+ bs[1].should == false
55
+ end
56
+
57
+ it 'raises an error when setting out of bound indexes' do
58
+ bs = Bitset.new(8)
59
+ expect { bs[8] = true }.to raise_error(IndexError)
60
+ end
61
+ end
62
+
63
+ describe :set do
64
+ it 'sets True for all given indexes' do
65
+ bs = Bitset.new(8)
66
+ bs.set 1,2,3
67
+
68
+ bs[1].should == true
69
+ bs[2].should == true
70
+ bs[3].should == true
71
+ end
72
+ end
73
+
74
+ describe :clear do
75
+ it 'sets False for all given indexes' do
76
+ bs = Bitset.new(8)
77
+ bs.set 1,2,3
78
+ bs.clear 1,3
79
+
80
+ bs[1].should == false
81
+ bs[2].should == true
82
+ bs[3].should == false
83
+ end
84
+ end
85
+
86
+ describe :set? do
87
+ it 'returns True if all bits indexed are set' do
88
+ bs = Bitset.new(8)
89
+ bs.set 1, 4, 5
90
+ bs.set?(1,4,5).should == true
91
+ end
92
+
93
+ it 'returns False if not all bits indexed are set' do
94
+ bs = Bitset.new(8)
95
+ bs.set 1, 4
96
+ bs.set?(1,4,5).should == false
97
+ end
98
+ end
99
+
100
+ describe :clear? do
101
+ it 'returns True if all bits indexed are clear' do
102
+ bs = Bitset.new(8)
103
+ bs.set 1, 4, 5
104
+ bs.clear?(0,2,3,6).should == true
105
+ end
106
+
107
+ it 'returns works with the full range of 64 bit values' do
108
+ bs = Bitset.new(68)
109
+ bs.set 0, 2, 66
110
+ bs.clear?(32, 33, 34).should == true
111
+ end
112
+
113
+ it 'returns False if not all bits indexed are clear' do
114
+ bs = Bitset.new(8)
115
+ bs.set 1, 4
116
+ bs.clear?(1,2,6).should == false
117
+ end
118
+ end
119
+
120
+ describe :cardinality do
121
+ it 'returns the number of bits set' do
122
+ bs = Bitset.new(8)
123
+ bs.cardinality.should == 0
124
+
125
+ bs[0] = true
126
+ bs.cardinality.should == 1
127
+
128
+ bs[1] = true
129
+ bs.cardinality.should == 2
130
+
131
+ bs[2] = true
132
+ bs.cardinality.should == 3
133
+
134
+ bs = Bitset.new(64)
135
+ bs[0] = 1
136
+
137
+ bs.cardinality.should == 1
138
+ end
139
+
140
+ it '... even for large numbers of bits' do
141
+ bs = Bitset.new(10_000)
142
+ bs.set(*(0...5000).to_a)
143
+ bs.cardinality.should == 5000
144
+
145
+ bs = Bitset.from_s "01001101000000000000000000000011000010100100000000000000010000101000000000000000100000000100000000000010100100010000000010000100000100000001001000110000000000100010000000010100000000000000110000000000000000000000000100000000100010010000000000000000000001000000000000000000000000000001000000000000000000000000000100000000010010000000000000000000100100000000000000001000000010000001000000000000001000001100010001000000000000001000001000001000000000000001100010000010010001000000010000100000000000110000"
146
+ bs.cardinality.should == 63
147
+ end
148
+ end
149
+
150
+ describe :& do
151
+ it 'returns a new Bitset which is the intersection of two Bitsets' do
152
+ bs1 = Bitset.new(8)
153
+ bs1.set 1, 4, 7
154
+
155
+ bs2 = Bitset.new(8)
156
+ bs2.set 1, 2, 4, 6
157
+
158
+ bs3 = bs1 & bs2
159
+ bs3.set?(1,4).should == true
160
+ bs3.clear?(0,2,3,5,6,7).should == true
161
+ end
162
+ end
163
+
164
+ describe :| do
165
+ it 'returns a new Bitset which is the union of two Bitsets' do
166
+ bs1 = Bitset.new(8)
167
+ bs1.set 1, 4, 7
168
+
169
+ bs2 = Bitset.new(8)
170
+ bs2.set 1, 2, 4, 6
171
+
172
+ bs3 = bs1 | bs2
173
+ bs3.set?(1,2,4,6,7).should == true
174
+ bs3.clear?(0,3,5).should == true
175
+ end
176
+ end
177
+
178
+ describe :- do
179
+ it 'returns a new Bitset which is the difference of two Bitsets' do
180
+ bs1 = Bitset.new(8)
181
+ bs1.set 1, 4, 7
182
+
183
+ bs2 = Bitset.new(8)
184
+ bs2.set 1, 2, 4, 6
185
+
186
+ bs3 = bs1 - bs2
187
+ bs3.set?(7).should == true
188
+ bs3.clear?(0,1,2,3,4,5,6).should == true
189
+ end
190
+ end
191
+
192
+ describe :^ do
193
+ it 'returns a new Bitset which is the xor of two Bitsets' do
194
+ bs1 = Bitset.new(8)
195
+ bs1.set 1, 4, 7
196
+
197
+ bs2 = Bitset.new(8)
198
+ bs2.set 1, 2, 4, 6
199
+
200
+ bs3 = bs1 ^ bs2
201
+ bs3.set?(2,6,7).should == true
202
+ bs3.clear?(0,1,3,4,5).should == true
203
+ end
204
+ end
205
+
206
+ describe :not do
207
+ it "returns a new Bitset with is the not of one Bitset" do
208
+ bs1 = Bitset.new(8)
209
+ bs1.set 1, 4, 7
210
+
211
+ bs2 = bs1.not
212
+ bs2.set?(0, 2, 3, 5, 6).should == true
213
+ bs2.clear?(1, 4, 7).should == true
214
+ end
215
+ end
216
+
217
+ describe :hamming do
218
+ it 'returns the hamming distance of two Bitsets' do
219
+ bs1 = Bitset.new(8)
220
+ bs1.set 1, 4, 7
221
+
222
+ bs2 = Bitset.new(8)
223
+ bs2.set 1, 2, 4, 6
224
+
225
+ bs1.hamming(bs2).should == 3
226
+ end
227
+ end
228
+
229
+ describe :each do
230
+ it 'iterates over the bits in the Bitset' do
231
+ bs = Bitset.new(4)
232
+ bs.set 0, 2
233
+
234
+ i = 0
235
+ bs.each do |bit|
236
+ bit.should == bs[i]
237
+ i += 1
238
+ end
239
+ i.should == 4
240
+ end
241
+ end
242
+
243
+ describe :to_s do
244
+ it 'correctly prints out a binary string' do
245
+ bs = Bitset.new(4)
246
+ bs.set 0, 2
247
+ bs.to_s.should == "1010"
248
+
249
+ bs = Bitset.new(68)
250
+ bs.set 0, 2, 66
251
+ bs.to_s.should == "101" + ("0" * 63) + "10"
252
+ end
253
+ end
254
+
255
+ describe :from_s do
256
+ it 'correctly creates a bitmap from a binary string' do
257
+ bs = Bitset.from_s("10101")
258
+ bs.set?(0, 2, 4).should == true
259
+ end
260
+ end
261
+
262
+ describe :marshalling do
263
+ it 'can marshal and load' do
264
+ bs = Bitset.new(68)
265
+ bs.set 1, 65
266
+
267
+ serialized = Marshal.load(Marshal.dump(bs))
268
+ serialized.set?(1, 65).should == true
269
+ serialized.cardinality.should == 2
270
+ end
271
+ end
272
+
273
+ describe :to_a do
274
+ it "can convert to an array of set positions" do
275
+ bs = Bitset.new(68)
276
+ bs.set 1, 64, 65
277
+
278
+ bs.to_a.should == [1, 64, 65]
279
+ end
280
+ end
281
+
282
+ describe :to_binary_array do
283
+ it "can convert to an array of 1s and 0s" do
284
+ bs = Bitset.new(68)
285
+ bs.set 1, 64, 65
286
+
287
+ bs.to_binary_array.values_at(1, 64, 65, 66).should == [1, 1, 1, 0]
288
+ end
289
+ end
290
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bitset_bm
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tyler McMullen
8
+ - Brendon McLean
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '2.0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '2.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: '10.1'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: '10.1'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake-compiler
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: '0.9'
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: 0.9.2
52
+ type: :development
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ version: '0.9'
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
62
+ description: A fast C-based Bitset. It supports the standard set operations as well
63
+ as operations you may expect on bit arrays. (popcount, for instance)
64
+ email: tbmcmullen@gmail.com
65
+ executables: []
66
+ extensions:
67
+ - ext/bitset/extconf.rb
68
+ extra_rdoc_files:
69
+ - LICENSE.txt
70
+ - README.markdown
71
+ files:
72
+ - .gitignore
73
+ - .travis.yml
74
+ - Gemfile
75
+ - Gemfile.lock
76
+ - LICENSE.txt
77
+ - README.markdown
78
+ - Rakefile
79
+ - VERSION
80
+ - bitset.gemspec
81
+ - ext/bitset/bitset.c
82
+ - ext/bitset/extconf.rb
83
+ - lib/bitset/version.rb
84
+ - spec/bitset_spec.rb
85
+ homepage: http://github.com/brendon9x/bitset
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ! '>='
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.2.1
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Bitset implementation.
109
+ test_files:
110
+ - spec/bitset_spec.rb