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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d7264d2aacb2a035cc9d03a759e3d7df802490d7
4
- data.tar.gz: b67c9f93d7b5dc611807cdd148ffdcf871588bbf
3
+ metadata.gz: 4c14192c25ee30542e0317d9866aae505540db2d
4
+ data.tar.gz: 3ca3e7cdd173f8f45785f80925afc31960236200
5
5
  SHA512:
6
- metadata.gz: f5374f4557cf95b59488c7e84f9af6865b8c2b92dc605369e7e756e4be6fc1abfbbbef85f6198fe192ed43a4594bd59519da98bcb8577bd8024961429ac1c6a9
7
- data.tar.gz: 77c7dd54f09f8f7f0e439324a8e01c22959e6d6a7e2d517607eb803724099173012fbd85cf736aef61a8e3519d2ac01fde340e298094e66a917f0418e4f0841a
6
+ metadata.gz: 0c811e6e8fc572c7efd0338e4b249189542be2c8e533cc672166cd22e2113b4d1ed10c28a5ea1587492c38d26787700dd45fa3d705badf6273014ecde1fa64b8
7
+ data.tar.gz: 5f602be6047488f9f1ba99f168b98050f3479fba816032bdeb7a4873786f9e8de9fd6b076c0ad29d3ac39c5818a7977a72209c19f2acdad637a735e5c7f966a7
@@ -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.1.0
@@ -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.1 ruby lib
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.1"
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 = "2017-05-26"
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.12".freeze
38
+ s.rubygems_version = "2.6.14".freeze
39
39
  s.summary = "Bitset implementation.".freeze
40
40
  end
41
41
 
@@ -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 VALUE rb_bitset_cardinality(VALUE self) {
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 INT2NUM(count);
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
- if (!block_p) {
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
- ++bit_position;
421
- segment >>= 1;
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, 0);
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. */
@@ -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.1
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: 2017-05-26 00:00:00.000000000 Z
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.12
54
+ rubygems_version: 2.6.14
55
55
  signing_key:
56
56
  specification_version: 4
57
57
  summary: Bitset implementation.