ingramj-bitarray 0.3.1 → 0.4.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.
data/README CHANGED
@@ -2,13 +2,29 @@ A bit array class for Ruby, implemented as a C extension. Includes methods for
2
2
  setting and clearing individual bits, and all bits at once. Also has the
3
3
  standard array access methods, [] and []=, and it mixes in Enumerable.
4
4
 
5
+ Example usage:
6
+
7
+ require 'bitarray'
8
+ bm = BitArray.new(16)
9
+ bm[5] = 1
10
+ bm.toggle_all_bits
11
+ puts bm
12
+
13
+
5
14
  The test/ directory has a unit test file. It also has a benchmark utility for
6
15
  comparison with Peter Cooper's pure Ruby BitField class.
7
16
 
8
- This extension has only been tested with Ruby 1.9.1 on Ubuntu, and probably
9
- won't compile for Ruby 1.8. Compatibility with Ruby 1.8 is planned.
17
+ This library has been compiled and tested on:
18
+
19
+ ruby 1.9.1p129 (2009-05-12 revision 23412) [i686-linux]
20
+ ruby 1.8.7 (2008-08-11 patchlevel 72) [alpha-netbsd]
21
+
22
+ If you have success using it on any other version/platform combinations, I'd
23
+ like to know. Or if you have problems, I'd like to know that too. Report bugs
24
+ at http://github.com/ingramj/bitarray/issues
25
+
10
26
 
11
- This library is available as a gem. Install it with
27
+ BitArray is available as a gem. Install it with
12
28
 
13
29
  sudo gem install ingramj-bitarray -s http://gems.github.com
14
30
 
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ EOF
13
13
  gem.authors = ["James E. Ingram"]
14
14
  gem.require_paths = ["ext"]
15
15
  gem.extensions = ["ext/extconf.rb"]
16
- gem.required_ruby_version = ">= 1.9.1"
16
+ gem.required_ruby_version = ">= 1.8.6"
17
17
  gem.rdoc_options << '--exclude' << 'ext/Makefile' << '--title' << 'BitArray Documentation'
18
18
  end
19
19
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.4.0
data/bitarray.gemspec CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{bitarray}
5
- s.version = "0.3.1"
5
+ s.version = "0.4.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"]
9
- s.date = %q{2009-05-24}
9
+ s.date = %q{2009-05-25}
10
10
  s.description = %q{A bit array class for Ruby, implemented as a C extension. Includes methods for setting and clearing individual bits, and all bits at once. Also has the standard array access methods, [] and []=, and it mixes in Enumerable.}
11
11
  s.email = %q{ingramj@gmail.com}
12
12
  s.extensions = ["ext/extconf.rb"]
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
32
32
  s.homepage = %q{http://github.com/ingramj/bitarray}
33
33
  s.rdoc_options = ["--charset=UTF-8", "--exclude", "ext/Makefile", "--title", "BitArray Documentation"]
34
34
  s.require_paths = ["ext"]
35
- s.required_ruby_version = Gem::Requirement.new(">= 1.9.1")
35
+ s.required_ruby_version = Gem::Requirement.new(">= 1.8.6")
36
36
  s.rubygems_version = %q{1.3.1}
37
37
  s.summary = %q{A bitarray class for Ruby, implemented as a C extension.}
38
38
  s.test_files = [
data/ext/bitarray.c CHANGED
@@ -13,8 +13,8 @@
13
13
 
14
14
  /* Bit Array structure. */
15
15
  struct bit_array {
16
- size_t bits; /* Number of bits. */
17
- size_t array_size; /* Size of the storage array. */
16
+ long bits; /* Number of bits. */
17
+ long array_size; /* Size of the storage array. */
18
18
  unsigned int *array; /* Array of unsigned ints, used for bit storage. */
19
19
  };
20
20
 
@@ -23,7 +23,7 @@ struct bit_array {
23
23
 
24
24
  /* Set the specified bit to 1. Return 1 on success, 0 on failure. */
25
25
  static int
26
- set_bit(struct bit_array *ba, ptrdiff_t bit)
26
+ set_bit(struct bit_array *ba, long bit)
27
27
  {
28
28
  if (bit < 0) bit += ba->bits;
29
29
  if (bit >= ba->bits) {
@@ -46,7 +46,7 @@ set_all_bits(struct bit_array *ba)
46
46
 
47
47
  /* Clear the specified bit to 0. Return 1 on success, 0 on failure. */
48
48
  static int
49
- clear_bit(struct bit_array *ba, ptrdiff_t bit)
49
+ clear_bit(struct bit_array *ba, long bit)
50
50
  {
51
51
  if (bit < 0) bit += ba->bits;
52
52
  if (bit >= ba->bits) {
@@ -69,7 +69,7 @@ clear_all_bits(struct bit_array *ba)
69
69
 
70
70
  /* Toggle the state of the specified bit. Return 1 on success, 0 on failure. */
71
71
  static int
72
- toggle_bit(struct bit_array *ba, ptrdiff_t bit)
72
+ toggle_bit(struct bit_array *ba, long bit)
73
73
  {
74
74
  if (bit < 0) bit += ba->bits;
75
75
  if (bit >= ba->bits) {
@@ -85,7 +85,7 @@ toggle_bit(struct bit_array *ba, ptrdiff_t bit)
85
85
  static int
86
86
  toggle_all_bits(struct bit_array *ba)
87
87
  {
88
- int i;
88
+ long i;
89
89
  for(i = 0; i < ba->array_size; i++) {
90
90
  ba->array[i] ^= ~0ul; /* ~0 = all bits set. */
91
91
  }
@@ -96,7 +96,7 @@ toggle_all_bits(struct bit_array *ba)
96
96
  /* Assign the specified value to a bit. Return 1 on success, 0 on invalid bit
97
97
  * index, and -1 on invalid value. */
98
98
  static int
99
- assign_bit(struct bit_array *ba, ptrdiff_t bit, int value)
99
+ assign_bit(struct bit_array *ba, long bit, int value)
100
100
  {
101
101
  if (value == 0) {
102
102
  return clear_bit(ba, bit);
@@ -110,7 +110,7 @@ assign_bit(struct bit_array *ba, ptrdiff_t bit, int value)
110
110
 
111
111
  /* Get the state of the specified bit. Return -1 on failure. */
112
112
  static int
113
- get_bit(struct bit_array *ba, ptrdiff_t bit)
113
+ get_bit(struct bit_array *ba, long bit)
114
114
  {
115
115
  if (bit < 0) bit += ba->bits;
116
116
  if (bit >= ba->bits) {
@@ -127,15 +127,15 @@ get_bit(struct bit_array *ba, ptrdiff_t bit)
127
127
 
128
128
 
129
129
  /* Return the number of set bits in the array. */
130
- static size_t
130
+ static long
131
131
  total_set(struct bit_array *ba)
132
132
  {
133
133
  /* This is basically the algorithm from K&R, with a running total for all
134
134
  * array elements. There are faster algorithms, but this one is simpler to
135
135
  * implement. The running time is proportionate to the number of set bits.
136
136
  */
137
- size_t count = 0;
138
- int i;
137
+ long count = 0;
138
+ long i;
139
139
  unsigned x;
140
140
  for (i = 0; i < ba->array_size; i++) {
141
141
  x = ba->array[i];
@@ -183,13 +183,13 @@ rb_bitarray_initialize(VALUE self, VALUE size)
183
183
  struct bit_array *ba;
184
184
  Data_Get_Struct(self, struct bit_array, ba);
185
185
 
186
- ptrdiff_t bits = NUM2SSIZET(size);
186
+ long bits = NUM2LONG(size);
187
187
  if (bits <= 0) {
188
188
  ba->bits = 0;
189
189
  ba->array_size = 0;
190
190
  return self;
191
191
  }
192
- size_t array_size = ((bits - 1) / UINT_BITS) + 1;
192
+ long array_size = ((bits - 1) / UINT_BITS) + 1;
193
193
 
194
194
  ba->bits = bits;
195
195
  ba->array_size = array_size;
@@ -240,27 +240,31 @@ rb_bitarray_concat(VALUE x, VALUE y)
240
240
  VALUE z;
241
241
  struct bit_array *z_ba;
242
242
  z = rb_bitarray_alloc(rb_bitarray_class);
243
- rb_bitarray_initialize(z, SIZET2NUM(x_ba->bits + y_ba->bits));
243
+ rb_bitarray_initialize(z, LONG2NUM(x_ba->bits + y_ba->bits));
244
244
  Data_Get_Struct(z, struct bit_array, z_ba);
245
245
 
246
- /* For each bit set in x and y, set the corresponding bit in z.
247
- *
248
- * It might be faster to memcpy x_ba->array to the beginning of
249
- * z_ba->array, then set the rest of the bits by looping over y...
246
+ /* For each bit set in x and y, set the corresponding bit in z. First, copy
247
+ * x to the beginning of z. Then, if x->bits is a multiple of UINT_BITS, we
248
+ * can just copy y onto the end of z. Otherwise, we need to go through y
249
+ * bit-by-bit and set the appropriate bits in z.
250
250
  */
251
- size_t z_index = 0;
252
- size_t i;
253
- for (i = 0; i < x_ba->bits; i++, z_index++) {
254
- if (get_bit(x_ba, i) == 1) {
255
- set_bit(z_ba, z_index);
256
- }
257
- }
258
- for (i = 0; i < y_ba->bits; i++, z_index++) {
259
- if (get_bit(y_ba, i) == 1) {
260
- set_bit(z_ba, z_index);
251
+ memcpy(z_ba->array, x_ba->array, (x_ba->array_size * UINT_BYTES));
252
+ if ((x_ba->bits % UINT_BITS) == 0) {
253
+ unsigned int *start = z_ba->array + x_ba->array_size;
254
+ memcpy(start, y_ba->array, (y_ba->array_size * UINT_BYTES));
255
+ } else {
256
+ long y_index, z_index;
257
+ for (y_index = 0, z_index = x_ba->bits;
258
+ y_index < y_ba->bits;
259
+ y_index++, z_index++)
260
+ {
261
+ if (get_bit(y_ba, y_index) == 1) {
262
+ set_bit(z_ba, z_index);
263
+ } else {
264
+ clear_bit(z_ba, z_index);
265
+ }
261
266
  }
262
267
  }
263
-
264
268
  return z;
265
269
  }
266
270
 
@@ -277,7 +281,7 @@ rb_bitarray_size(VALUE self)
277
281
  struct bit_array *ba;
278
282
  Data_Get_Struct(self, struct bit_array, ba);
279
283
 
280
- return SIZET2NUM(ba->bits);
284
+ return LONG2NUM(ba->bits);
281
285
  }
282
286
 
283
287
 
@@ -292,8 +296,8 @@ rb_bitarray_total_set(VALUE self)
292
296
  struct bit_array *ba;
293
297
  Data_Get_Struct(self, struct bit_array, ba);
294
298
 
295
- size_t count = total_set(ba);
296
- return SIZET2NUM(count);
299
+ long count = total_set(ba);
300
+ return LONG2NUM(count);
297
301
  }
298
302
 
299
303
 
@@ -310,12 +314,12 @@ rb_bitarray_set_bit(VALUE self, VALUE bit)
310
314
  struct bit_array *ba;
311
315
  Data_Get_Struct(self, struct bit_array, ba);
312
316
 
313
- ptrdiff_t index = NUM2SSIZET(bit);
317
+ long index = NUM2LONG(bit);
314
318
 
315
319
  if (set_bit(ba, index)) {
316
320
  return self;
317
321
  } else {
318
- rb_raise(rb_eIndexError, "index %ld out of bit array", (long)index);
322
+ rb_raise(rb_eIndexError, "index %ld out of bit array", index);
319
323
  }
320
324
  }
321
325
 
@@ -352,12 +356,12 @@ rb_bitarray_clear_bit(VALUE self, VALUE bit)
352
356
  struct bit_array *ba;
353
357
  Data_Get_Struct(self, struct bit_array, ba);
354
358
 
355
- ptrdiff_t index = NUM2SSIZET(bit);
359
+ long index = NUM2LONG(bit);
356
360
 
357
361
  if (clear_bit(ba, index)) {
358
362
  return self;
359
363
  } else {
360
- rb_raise(rb_eIndexError, "index %ld out of bit array", (long)index);
364
+ rb_raise(rb_eIndexError, "index %ld out of bit array", index);
361
365
  }
362
366
  }
363
367
 
@@ -394,12 +398,12 @@ rb_bitarray_toggle_bit(VALUE self, VALUE bit)
394
398
  struct bit_array *ba;
395
399
  Data_Get_Struct(self, struct bit_array, ba);
396
400
 
397
- ptrdiff_t index = NUM2SSIZET(bit);
401
+ long index = NUM2LONG(bit);
398
402
 
399
403
  if (toggle_bit(ba, index)) {
400
404
  return self;
401
405
  } else {
402
- rb_raise(rb_eIndexError, "index %ld out of bit array", (long)index);
406
+ rb_raise(rb_eIndexError, "index %ld out of bit array", index);
403
407
  }
404
408
  }
405
409
 
@@ -424,7 +428,7 @@ rb_bitarray_toggle_all_bits(VALUE self)
424
428
 
425
429
  /* Return an individual bit. */
426
430
  static VALUE
427
- rb_bitarray_get_bit(VALUE self, ptrdiff_t index)
431
+ rb_bitarray_get_bit(VALUE self, long index)
428
432
  {
429
433
  struct bit_array *ba;
430
434
  Data_Get_Struct(self, struct bit_array, ba);
@@ -434,14 +438,14 @@ rb_bitarray_get_bit(VALUE self, ptrdiff_t index)
434
438
  if (bit_value >= 0) {
435
439
  return INT2NUM(bit_value);
436
440
  } else {
437
- rb_raise(rb_eIndexError, "index %ld out of bit array", (long)index);
441
+ rb_raise(rb_eIndexError, "index %ld out of bit array", index);
438
442
  }
439
443
  }
440
444
 
441
445
 
442
446
  /* Create a new BitArray from a subsequence of x. */
443
447
  static VALUE
444
- rb_bitarray_subseq(VALUE x, ptrdiff_t beg, ptrdiff_t len)
448
+ rb_bitarray_subseq(VALUE x, long beg, long len)
445
449
  {
446
450
 
447
451
  struct bit_array *x_ba;
@@ -467,7 +471,7 @@ rb_bitarray_subseq(VALUE x, ptrdiff_t beg, ptrdiff_t len)
467
471
  /* Create a new BitArray of the appropriate size. */
468
472
  VALUE y;
469
473
  y = rb_bitarray_alloc(rb_bitarray_class);
470
- rb_bitarray_initialize(y, SSIZET2NUM(len));
474
+ rb_bitarray_initialize(y, LONG2NUM(len));
471
475
  /* If our length is 0, we can just return now. */
472
476
  if (len == 0) {
473
477
  return y;
@@ -476,7 +480,7 @@ rb_bitarray_subseq(VALUE x, ptrdiff_t beg, ptrdiff_t len)
476
480
  Data_Get_Struct(y, struct bit_array, y_ba);
477
481
 
478
482
  /* For each set bit in x[beg..len], set the corresponding bit in y. */
479
- size_t x_index, y_index;
483
+ long x_index, y_index;
480
484
  for (x_index = beg, y_index = 0;
481
485
  x_index < beg + len;
482
486
  x_index++, y_index++)
@@ -509,8 +513,8 @@ rb_bitarray_bitref(int argc, VALUE *argv, VALUE self)
509
513
 
510
514
  /* Two arguments means we have a beginning and a length */
511
515
  if (argc == 2) {
512
- ptrdiff_t beg = NUM2SSIZET(argv[0]);
513
- ptrdiff_t len = NUM2SSIZET(argv[1]);
516
+ long beg = NUM2LONG(argv[0]);
517
+ long len = NUM2LONG(argv[1]);
514
518
  return rb_bitarray_subseq(self, beg, len);
515
519
  }
516
520
 
@@ -546,7 +550,7 @@ rb_bitarray_bitref(int argc, VALUE *argv, VALUE self)
546
550
  return rb_bitarray_subseq(self, beg, len);
547
551
  }
548
552
 
549
- return rb_bitarray_get_bit(self, NUM2SSIZET(arg));
553
+ return rb_bitarray_get_bit(self, NUM2LONG(arg));
550
554
  }
551
555
 
552
556
 
@@ -566,14 +570,14 @@ rb_bitarray_assign_bit(VALUE self, VALUE bit, VALUE value)
566
570
  struct bit_array *ba;
567
571
  Data_Get_Struct(self, struct bit_array, ba);
568
572
 
569
- ptrdiff_t index = NUM2SSIZET(bit);
573
+ long index = NUM2LONG(bit);
570
574
  int bit_value = NUM2INT(value);
571
575
 
572
576
  int result = assign_bit(ba, index, bit_value);
573
577
  if (result == 1) {
574
578
  return value;
575
579
  } else if (result == 0) {
576
- rb_raise(rb_eIndexError, "index %ld out of bit array", (long)index);
580
+ rb_raise(rb_eIndexError, "index %ld out of bit array", index);
577
581
  } else {
578
582
  rb_raise(rb_eRuntimeError, "bit value %d out of range", bit_value);
579
583
  }
@@ -592,10 +596,10 @@ rb_bitarray_inspect(VALUE self)
592
596
  struct bit_array *ba;
593
597
  Data_Get_Struct(self, struct bit_array, ba);
594
598
 
595
- size_t cstr_size = ba->bits + 1;
599
+ long cstr_size = ba->bits + 1;
596
600
  char cstr[cstr_size];
597
601
 
598
- size_t i;
602
+ long i;
599
603
  for (i = 0; i < ba->bits; i++) {
600
604
  cstr[i] = get_bit(ba, i) + '0';
601
605
  }
@@ -625,7 +629,7 @@ rb_bitarray_each(VALUE self)
625
629
  struct bit_array *ba;
626
630
  Data_Get_Struct(self, struct bit_array, ba);
627
631
 
628
- size_t i;
632
+ long i;
629
633
 
630
634
  RETURN_ENUMERATOR(self, 0, 0);
631
635
  for (i = 0; i < ba->bits; i++) {
data/test/bm.rb CHANGED
@@ -44,6 +44,10 @@ Benchmark.bm(28) { |bm|
44
44
  bm.report("BitArray clone") { 100000.times { ba.clone } }
45
45
  bm.report("BitArray slice (beg,len)") { 100000.times { ba[17, 230] } }
46
46
  bm.report("BitArray slice (range)") { 100000.times { ba[17..247] } }
47
- bm.report("BitArray +") { 100000.times { ba + ba } }
47
+ ba.set_all_bits
48
+ bm.report("BitArray + (256, all set)") { 100000.times { ba + ba } }
49
+ ba2 = BitArray.new(240)
50
+ ba2.set_all_bits
51
+ bm.report("BitArray + (240, all set)") { 100000.times { ba2 + ba2 } }
48
52
  }
49
53
 
data/test/test.rb CHANGED
@@ -120,6 +120,18 @@ class TestLibraryFileName < Test::Unit::TestCase
120
120
  ba2.set_all_bits
121
121
  ba3 = ba1 + ba2
122
122
  assert_equal "0000011111", ba3.to_s
123
+ ba3 = ba2 + ba1
124
+ assert_equal "1111100000", ba3.to_s
125
+ end
126
+
127
+ def test_concatenation2
128
+ ba1 = BitArray.new(32)
129
+ ba2 = BitArray.new(7)
130
+ ba2.set_all_bits
131
+ ba3 = ba1 + ba2
132
+ assert_equal "000000000000000000000000000000001111111", ba3.to_s
133
+ ba3 = ba2 + ba1
134
+ assert_equal "111111100000000000000000000000000000000", ba3.to_s
123
135
  end
124
136
  end
125
137
 
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.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James E. Ingram
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-24 00:00:00 -07:00
12
+ date: 2009-05-25 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -50,7 +50,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 1.9.1
53
+ version: 1.8.6
54
54
  version:
55
55
  required_rubygems_version: !ruby/object:Gem::Requirement
56
56
  requirements: