bitset 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.markdown +22 -13
- data/VERSION +1 -1
- data/bitset.gemspec +4 -4
- data/ext/bitset/bitset.c +57 -8
- data/spec/bitset_spec.rb +7 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c14192c25ee30542e0317d9866aae505540db2d
|
4
|
+
data.tar.gz: 3ca3e7cdd173f8f45785f80925afc31960236200
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c811e6e8fc572c7efd0338e4b249189542be2c8e533cc672166cd22e2113b4d1ed10c28a5ea1587492c38d26787700dd45fa3d705badf6273014ecde1fa64b8
|
7
|
+
data.tar.gz: 5f602be6047488f9f1ba99f168b98050f3479fba816032bdeb7a4873786f9e8de9fd6b076c0ad29d3ac39c5818a7977a72209c19f2acdad637a735e5c7f966a7
|
data/README.markdown
CHANGED
@@ -39,16 +39,16 @@ Obviously you can also set and clear bits...
|
|
39
39
|
|
40
40
|
>> bitset = Bitset.new(8)
|
41
41
|
=> 00000000
|
42
|
-
|
42
|
+
|
43
43
|
>> bitset[3] = true
|
44
44
|
=> 00010000
|
45
|
-
|
45
|
+
|
46
46
|
>> bitset[3] = false
|
47
47
|
=> 00000000
|
48
|
-
|
48
|
+
|
49
49
|
>> bitset.set(1, 3, 5, 7)
|
50
50
|
=> 01010101
|
51
|
-
|
51
|
+
|
52
52
|
>> bitset.clear(1, 5)
|
53
53
|
=> 00010001
|
54
54
|
|
@@ -59,31 +59,31 @@ support basic set and bitwise operations. So, let's look at a few of those.
|
|
59
59
|
|
60
60
|
>> a = Bitset.from_s('00001111')
|
61
61
|
=> 00001111
|
62
|
-
|
62
|
+
|
63
63
|
>> b = Bitset.from_s('01010101')
|
64
64
|
=> 01010101
|
65
|
-
|
65
|
+
|
66
66
|
>> a & b
|
67
67
|
=> 00000101
|
68
|
-
|
68
|
+
|
69
69
|
>> a | b
|
70
70
|
=> 01011111
|
71
|
-
|
71
|
+
|
72
72
|
>> b - a
|
73
73
|
=> 01010000
|
74
|
-
|
74
|
+
|
75
75
|
>> a ^ b
|
76
76
|
=> 01011010
|
77
|
-
|
77
|
+
|
78
78
|
>> ~a
|
79
79
|
=> 11110000
|
80
|
-
|
80
|
+
|
81
81
|
>> a.hamming(b)
|
82
82
|
=> 4
|
83
|
-
|
83
|
+
|
84
84
|
>> a.cardinality
|
85
85
|
=> 4
|
86
|
-
|
86
|
+
|
87
87
|
>> a.reverse
|
88
88
|
=> 11110000
|
89
89
|
|
@@ -123,6 +123,15 @@ support basic set and bitwise operations. So, let's look at a few of those.
|
|
123
123
|
>> b.each_set # AKA b.to_a
|
124
124
|
=> [1, 3, 5, 7]
|
125
125
|
|
126
|
+
# b.each_set(index) == b.each_set[index], but faster.
|
127
|
+
>> b.each_set(-3) # Negative index wraps around.
|
128
|
+
=> 3
|
129
|
+
|
130
|
+
# b.each_set(index, len) == b.each_set[index, len], but faster.
|
131
|
+
>> b.each_set(2,2) # Block is also allowed
|
132
|
+
=> [5,7]
|
133
|
+
|
134
|
+
|
126
135
|
# The following methods modify a Bitset in place very quickly:
|
127
136
|
>> a.intersect!(b) # like a &= b
|
128
137
|
>> a.union!(b) # like a |= b
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.1.0
|
data/bitset.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: bitset 1.0
|
5
|
+
# stub: bitset 1.1.0 ruby lib
|
6
6
|
# stub: ext/bitset/extconf.rb
|
7
7
|
|
8
8
|
Gem::Specification.new do |s|
|
9
9
|
s.name = "bitset".freeze
|
10
|
-
s.version = "1.0
|
10
|
+
s.version = "1.1.0"
|
11
11
|
|
12
12
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
13
13
|
s.require_paths = ["lib".freeze]
|
14
14
|
s.authors = ["Tyler McMullen".freeze]
|
15
|
-
s.date = "
|
15
|
+
s.date = "2018-01-06"
|
16
16
|
s.description = "A fast C-based Bitset. It supports the standard set operations as well as operations you may expect on bit arrays,such as popcount.".freeze
|
17
17
|
s.email = "eric.boesch@nist.gov".freeze
|
18
18
|
s.extensions = ["ext/bitset/extconf.rb".freeze]
|
@@ -35,7 +35,7 @@ Gem::Specification.new do |s|
|
|
35
35
|
]
|
36
36
|
s.homepage = "http://github.com/ericboesch/bitset".freeze
|
37
37
|
s.licenses = ["MIT".freeze]
|
38
|
-
s.rubygems_version = "2.6.
|
38
|
+
s.rubygems_version = "2.6.14".freeze
|
39
39
|
s.summary = "Bitset implementation.".freeze
|
40
40
|
end
|
41
41
|
|
data/ext/bitset/bitset.c
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
#include "builtin.h"
|
3
3
|
|
4
4
|
#include <stdint.h>
|
5
|
+
#include <stdbool.h>
|
5
6
|
#include <string.h>
|
6
7
|
#include <stdio.h>
|
8
|
+
#include <limits.h>
|
7
9
|
|
8
10
|
VALUE cBitset;
|
9
11
|
|
@@ -173,15 +175,19 @@ static VALUE rb_bitset_set_p(int argc, VALUE * argv, VALUE self) {
|
|
173
175
|
return Qtrue;
|
174
176
|
}
|
175
177
|
|
176
|
-
static
|
177
|
-
Bitset * bs = get_bitset(self);
|
178
|
+
static int cardinality(Bitset * bs) {
|
178
179
|
int i;
|
179
180
|
int max = INTS(bs);
|
180
181
|
int count = 0;
|
181
182
|
for(i = 0; i < max; i++) {
|
182
183
|
count += psnip_builtin_popcount64(bs->data[i]);
|
183
184
|
}
|
184
|
-
return
|
185
|
+
return count;
|
186
|
+
}
|
187
|
+
|
188
|
+
static VALUE rb_bitset_cardinality(VALUE self) {
|
189
|
+
Bitset * bs = get_bitset(self);
|
190
|
+
return INT2NUM(cardinality(bs));
|
185
191
|
}
|
186
192
|
|
187
193
|
static VALUE rb_bitset_intersect(VALUE self, VALUE other) {
|
@@ -388,21 +394,51 @@ static VALUE rb_bitset_dup(VALUE self) {
|
|
388
394
|
|
389
395
|
/* Yield the bit numbers of each set bit in sequence to a block. If
|
390
396
|
there is no block, return an array of those numbers. */
|
391
|
-
static VALUE rb_bitset_each_set(VALUE self) {
|
397
|
+
static VALUE rb_bitset_each_set(int argc, VALUE * argv, VALUE self) {
|
392
398
|
Bitset * bs = get_bitset(self);
|
393
399
|
int seg_no;
|
394
400
|
int max = INTS(bs);
|
395
401
|
uint64_t* seg_ptr = bs->data;
|
396
402
|
int block_p = rb_block_given_p();
|
397
403
|
VALUE ary = Qnil;
|
404
|
+
int set_bit_no = -1;
|
405
|
+
|
406
|
+
/* If there is one argument, it is an index into the notional
|
407
|
+
output array, and return an int. If there are two arguments,
|
408
|
+
return up to <n> arguments where is the second argument. */
|
409
|
+
int min_set_bit_no = (argc > 0) ? NUM2INT(argv[0]) : 0;
|
410
|
+
int max_set_bit_no;
|
411
|
+
|
412
|
+
if (argc > 2) {
|
413
|
+
VALUE error = rb_const_get(rb_cObject, rb_intern("ArgumentError"));
|
414
|
+
rb_raise(error, "wrong number of arguments (given %d, expected 0..2)",
|
415
|
+
argc);
|
416
|
+
}
|
417
|
+
|
418
|
+
if (min_set_bit_no < 0) {
|
419
|
+
/* Convert negative numbers into offsets from the end of the array. */
|
420
|
+
min_set_bit_no = cardinality(bs) + min_set_bit_no;
|
421
|
+
}
|
398
422
|
|
399
|
-
|
423
|
+
max_set_bit_no = (argc == 0)
|
424
|
+
? INT_MAX
|
425
|
+
: (argc == 1)
|
426
|
+
? (min_set_bit_no + 1)
|
427
|
+
: (min_set_bit_no + NUM2INT(argv[1]));
|
428
|
+
|
429
|
+
if (min_set_bit_no < 0 || max_set_bit_no < min_set_bit_no)
|
430
|
+
return Qnil;
|
431
|
+
|
432
|
+
if (argc != 1 && !block_p) {
|
400
433
|
ary = rb_ary_new();
|
401
434
|
}
|
435
|
+
if (min_set_bit_no < 0 || max_set_bit_no < min_set_bit_no)
|
436
|
+
return Qnil;
|
402
437
|
|
403
438
|
for (seg_no = 0; seg_no < max; ++seg_no, ++seg_ptr) {
|
404
439
|
uint64_t segment = *seg_ptr;
|
405
440
|
int bit_position = 0;
|
441
|
+
bool finished = false;
|
406
442
|
while (segment) {
|
407
443
|
VALUE v;
|
408
444
|
|
@@ -412,13 +448,26 @@ static VALUE rb_bitset_each_set(VALUE self) {
|
|
412
448
|
segment >>= shift;
|
413
449
|
}
|
414
450
|
v = INT2NUM(_seg_no_to_bit_no(seg_no) + bit_position);
|
451
|
+
++bit_position;
|
452
|
+
segment >>= 1;
|
453
|
+
++set_bit_no;
|
454
|
+
if (set_bit_no < min_set_bit_no) {
|
455
|
+
continue;
|
456
|
+
}
|
457
|
+
if (set_bit_no >= max_set_bit_no) {
|
458
|
+
finished = true;
|
459
|
+
break;
|
460
|
+
}
|
415
461
|
if (block_p) {
|
416
462
|
rb_yield(v);
|
463
|
+
} else if (argc == 1) {
|
464
|
+
return v;
|
417
465
|
} else {
|
418
466
|
rb_ary_push(ary, v);
|
419
467
|
}
|
420
|
-
|
421
|
-
|
468
|
+
}
|
469
|
+
if (finished) {
|
470
|
+
break;
|
422
471
|
}
|
423
472
|
}
|
424
473
|
|
@@ -576,7 +625,7 @@ void Init_bitset() {
|
|
576
625
|
rb_define_method(cBitset, "to_binary_array", rb_bitset_to_binary_array, 0);
|
577
626
|
rb_define_method(cBitset, "dup", rb_bitset_dup, 0);
|
578
627
|
rb_define_alias(cBitset, "clone", "dup");
|
579
|
-
rb_define_method(cBitset, "each_set", rb_bitset_each_set,
|
628
|
+
rb_define_method(cBitset, "each_set", rb_bitset_each_set, -1);
|
580
629
|
rb_define_alias(cBitset, "to_a", "each_set");
|
581
630
|
/* #each_set allows an optional block, and #to_a normally doesn't.
|
582
631
|
But an alias is simpler than having two different functions. */
|
data/spec/bitset_spec.rb
CHANGED
@@ -271,6 +271,13 @@ describe Bitset do
|
|
271
271
|
bs.set(*sets)
|
272
272
|
expect(bs.each_set).to eq(sets)
|
273
273
|
end
|
274
|
+
|
275
|
+
it 'behaves properly with arguments' do
|
276
|
+
bs = Bitset.from_s "110110011"
|
277
|
+
expect { bs.each_set 1, 2, 3 }.to raise_error(ArgumentError)
|
278
|
+
expect(bs.each_set 2).to eq(3)
|
279
|
+
expect(bs.each_set -3, 2).to eq([4,7])
|
280
|
+
end
|
274
281
|
end
|
275
282
|
|
276
283
|
describe :empty? do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitset
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tyler McMullen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A fast C-based Bitset. It supports the standard set operations as well
|
14
14
|
as operations you may expect on bit arrays,such as popcount.
|
@@ -51,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
51
51
|
version: '0'
|
52
52
|
requirements: []
|
53
53
|
rubyforge_project:
|
54
|
-
rubygems_version: 2.6.
|
54
|
+
rubygems_version: 2.6.14
|
55
55
|
signing_key:
|
56
56
|
specification_version: 4
|
57
57
|
summary: Bitset implementation.
|