ingramj-bitarray 0.1.1 → 0.2.0

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