ingramj-bitarray 0.3.1 → 0.4.0

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