bitset_bm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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