ingramj-bitarray 0.1.1 → 0.2.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.
Files changed (7) hide show
  1. data/TODO +2 -2
  2. data/VERSION +1 -1
  3. data/bitarray.gemspec +1 -1
  4. data/ext/bitarray.c +98 -1
  5. data/test/bm.rb +19 -11
  6. data/test/test.rb +20 -10
  7. metadata +1 -1
data/TODO CHANGED
@@ -1,7 +1,7 @@
1
1
  * Comment code. I'd like for it to be useful as a tutorial for extension
2
2
  writing, especially with regards to implementing new types.
3
- * Implement some more methods, like Hamming weight, and slice, and in-place
4
- enumerator methods (map!, reverse!, etc).
3
+ * Implement some more methods, like slice, and in-place enumerator methods
4
+ (map!, reverse!, etc).
5
5
  * Maybe allow resizing.
6
6
  * Write more tests
7
7
  * Ruby 1.8 compatibility. This will probably involve just changing some of the
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
data/bitarray.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{bitarray}
5
- s.version = "0.1.1"
5
+ s.version = "0.2.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["James E. Ingram"]
data/ext/bitarray.c CHANGED
@@ -81,6 +81,18 @@ toggle_bit(struct bit_array *ba, ptrdiff_t bit)
81
81
  }
82
82
 
83
83
 
84
+ /* Toggle the state of all bits. */
85
+ static int
86
+ toggle_all_bits(struct bit_array *ba)
87
+ {
88
+ int i;
89
+ for(i = 0; i < ba->array_size; i++) {
90
+ ba->array[i] ^= ~0ul; /* ~0 = all bits set. */
91
+ }
92
+ return 1;
93
+ }
94
+
95
+
84
96
  /* Assign the specified value to a bit. Return 1 on success, 0 on invalid bit
85
97
  * index, and -1 on invalid value. */
86
98
  static int
@@ -114,7 +126,29 @@ get_bit(struct bit_array *ba, ptrdiff_t bit)
114
126
  }
115
127
 
116
128
 
117
- /* Ruby Interface Functions. These aren't documented yet. */
129
+ /* Return the number of set bits in the array. */
130
+ static size_t
131
+ total_set(struct bit_array *ba)
132
+ {
133
+ /* This is basically the algorithm from K&R, with a running total for all
134
+ * array elements. There are faster algorithms, but this one is simpler to
135
+ * implement. The running time is proportionate to the number of set bits.
136
+ */
137
+ size_t count = 0;
138
+ int i;
139
+ unsigned x;
140
+ for (i = 0; i < ba->array_size; i++) {
141
+ x = ba->array[i];
142
+ while (x) {
143
+ x &= x - 1;
144
+ count++;
145
+ }
146
+ }
147
+ return count;
148
+ }
149
+
150
+
151
+ /* Ruby Interface Functions. */
118
152
 
119
153
  static VALUE rb_bitarray_class;
120
154
 
@@ -201,6 +235,22 @@ rb_bitarray_size(VALUE self)
201
235
  }
202
236
 
203
237
 
238
+ /* call-seq:
239
+ * bitarray.total_set -> int
240
+ *
241
+ * Return the number of set (1) bits in _bitarray_.
242
+ */
243
+ static VALUE
244
+ rb_bitarray_total_set(VALUE self)
245
+ {
246
+ struct bit_array *ba;
247
+ Data_Get_Struct(self, struct bit_array, ba);
248
+
249
+ size_t count = total_set(ba);
250
+ return SIZET2NUM(count);
251
+ }
252
+
253
+
204
254
  /* call-seq:
205
255
  * bitarray.set_bit(index) -> bitarray
206
256
  *
@@ -285,6 +335,48 @@ rb_bitarray_clear_all_bits(VALUE self)
285
335
  }
286
336
 
287
337
 
338
+ /* call-seq:
339
+ * bitarray.toggle_bit(index) -> bitarray
340
+ *
341
+ * Toggles the bit at _index_ to 0. Negative indices count backwards from the
342
+ * end of _bitarray_. If _index_ is greater than the capacity of _bitarray_, an
343
+ * +IndexError+ is raised.
344
+ */
345
+ static VALUE
346
+ rb_bitarray_toggle_bit(VALUE self, VALUE bit)
347
+ {
348
+ struct bit_array *ba;
349
+ Data_Get_Struct(self, struct bit_array, ba);
350
+
351
+ ptrdiff_t index = NUM2SSIZET(bit);
352
+
353
+ if (toggle_bit(ba, index)) {
354
+ return self;
355
+ } else {
356
+ rb_raise(rb_eIndexError, "index %ld out of bit array", (long)index);
357
+ }
358
+ }
359
+
360
+
361
+ /* call-seq:
362
+ * bitarray.toggle_all_bits -> bitarray
363
+ *
364
+ * Toggle all bits.
365
+ */
366
+ static VALUE
367
+ rb_bitarray_toggle_all_bits(VALUE self)
368
+ {
369
+ struct bit_array *ba;
370
+ Data_Get_Struct(self, struct bit_array, ba);
371
+
372
+ if(toggle_all_bits(ba)) {
373
+ return self;
374
+ } else {
375
+ rb_bug("BitArray#clear_all_bits failed. This should not occur.");
376
+ }
377
+ }
378
+
379
+
288
380
  /* call-seq:
289
381
  * bitarray[index] -> value
290
382
  *
@@ -417,12 +509,17 @@ Init_bitarray()
417
509
  rb_define_alias(rb_bitarray_class, "dup", "clone");
418
510
  rb_define_method(rb_bitarray_class, "size", rb_bitarray_size, 0);
419
511
  rb_define_alias(rb_bitarray_class, "length", "size");
512
+ rb_define_method(rb_bitarray_class, "total_set", rb_bitarray_total_set, 0);
420
513
  rb_define_method(rb_bitarray_class, "set_bit", rb_bitarray_set_bit, 1);
421
514
  rb_define_method(rb_bitarray_class, "set_all_bits",
422
515
  rb_bitarray_set_all_bits, 0);
423
516
  rb_define_method(rb_bitarray_class, "clear_bit", rb_bitarray_clear_bit, 1);
424
517
  rb_define_method(rb_bitarray_class, "clear_all_bits",
425
518
  rb_bitarray_clear_all_bits, 0);
519
+ rb_define_method(rb_bitarray_class, "toggle_bit",
520
+ rb_bitarray_toggle_bit, 1);
521
+ rb_define_method(rb_bitarray_class, "toggle_all_bits",
522
+ rb_bitarray_toggle_all_bits, 0);
426
523
  rb_define_method(rb_bitarray_class, "[]", rb_bitarray_get_bit, 1);
427
524
  rb_define_method(rb_bitarray_class, "[]=", rb_bitarray_assign_bit, 2);
428
525
  rb_define_method(rb_bitarray_class, "inspect", rb_bitarray_inspect, 0);
data/test/bm.rb CHANGED
@@ -2,37 +2,45 @@ require 'bitfield'
2
2
  require 'bitarray'
3
3
  require 'benchmark'
4
4
 
5
- Benchmark.bm(24) { |bm|
6
- puts "------------------------ Object instantiation."
5
+ Benchmark.bm(28) { |bm|
6
+ puts "---------------------------- Object instantiation."
7
7
  bm.report("BitField initialize") { 10000.times { BitField.new(256) } }
8
8
  bm.report("BitArray initialize") { 10000.times { BitArray.new(256) } }
9
9
 
10
10
  bf = BitField.new(256)
11
11
  ba = BitArray.new(256)
12
12
 
13
- puts "------------------------ Element Reading"
13
+ puts "---------------------------- Element Reading"
14
14
  bm.report("BitField []") { 10000.times { bf[rand(256)] } }
15
15
  bm.report("BitArray []") { 10000.times { ba[rand(256)] } }
16
16
 
17
- puts "------------------------ Element Writing"
17
+ puts "---------------------------- Element Writing"
18
18
  bm.report("BitField []=") { 10000.times { bf[rand(256)] = [0,1][rand(2)] } }
19
19
  bm.report("BitArray []=") { 10000.times { ba[rand(256)] = [0,1][rand(2)] } }
20
20
 
21
- puts "------------------------ Element Enumeration"
21
+ puts "---------------------------- Element Enumeration"
22
22
  bm.report("BitField each") { 10000.times { bf.each {|b| b } } }
23
23
  bm.report("BitArray each") { 10000.times { ba.each {|b| b } } }
24
24
 
25
- puts "------------------------ To String"
25
+ puts "---------------------------- To String"
26
26
  bm.report("BitField to_s") { 10000.times { bf.to_s } }
27
27
  bm.report("BitArray to_s") { 10000.times { ba.to_s } }
28
28
 
29
- puts "------------------------ Set All"
29
+ puts "---------------------------- Total Set"
30
+ bf = BitField.new(256)
31
+ ba = BitArray.new(256)
32
+ bm.report("BitField total_set (none)") { 10000.times { bf.total_set } }
33
+ bm.report("BitArray total_set (none)") { 10000.times { ba.total_set } }
34
+ bf.each {|b| b = 1}
35
+ ba.set_all_bits
36
+ bm.report("BitField total_set (all)") { 10000.times { bf.total_set } }
37
+ bm.report("BitArray total_set (all)") { 10000.times { ba.total_set } }
38
+
39
+ puts "---------------------------- BitArray methods"
30
40
  bm.report("BitArray set_all_bits") { 10000.times { ba.set_all_bits} }
31
-
32
- puts "------------------------ Clear All"
33
41
  bm.report("BitArray clear_all_bits") { 10000.times { ba.clear_all_bits } }
34
-
35
- puts "------------------------ Clone"
42
+ bm.report("BitArray toggle_bit") { 10000.times { ba.toggle_bit(1) } }
43
+ bm.report("BitArray toggle_all_bits") { 10000.times { ba.toggle_all_bits } }
36
44
  bm.report("BitArray clone") { 10000.times { ba.clone } }
37
45
  }
38
46
 
data/test/test.rb CHANGED
@@ -47,7 +47,6 @@ class TestLibraryFileName < Test::Unit::TestCase
47
47
  def test_size
48
48
  assert_equal 1000, @public_ba.size
49
49
  end
50
-
51
50
 
52
51
  def test_to_s
53
52
  ba = BitArray.new(10)
@@ -56,7 +55,6 @@ class TestLibraryFileName < Test::Unit::TestCase
56
55
  assert_equal "0100010000", ba.to_s
57
56
  end
58
57
 
59
-
60
58
  def test_set_all_bits
61
59
  ba = BitArray.new(10)
62
60
  ba.set_all_bits
@@ -78,14 +76,26 @@ class TestLibraryFileName < Test::Unit::TestCase
78
76
  ba_clone = ba.clone
79
77
  assert_equal ba_clone.to_s, ba.to_s
80
78
  end
81
-
82
- # This method is not implemented yet.
83
79
 
84
- #def test_total_set
85
- # bf = BitArray.new(10)
86
- # bf[1] = 1
87
- # bf[5] = 1
88
- # assert_equal 2, bf.total_set
89
- #end
80
+ def test_toggle_bit
81
+ ba = BitArray.new(10)
82
+ ba.toggle_bit 5
83
+ assert_equal 1, ba[5]
84
+ end
85
+
86
+ def test_toggle_all_bits
87
+ ba = BitArray.new(10)
88
+ ba[1] = 1
89
+ ba[5] = 1
90
+ ba.toggle_all_bits
91
+ assert_equal "1011101111", ba.to_s
92
+ end
93
+
94
+ def test_total_set
95
+ bf = BitArray.new(10)
96
+ bf[1] = 1
97
+ bf[5] = 1
98
+ assert_equal 2, bf.total_set
99
+ end
90
100
  end
91
101
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ingramj-bitarray
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James E. Ingram