bitset 1.0.1 → 1.1.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 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.