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 +19 -3
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bitarray.gemspec +3 -3
- data/ext/bitarray.c +55 -51
- data/test/bm.rb +5 -1
- data/test/test.rb +12 -0
- metadata +3 -3
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
|
9
|
-
|
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
|
-
|
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.
|
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.
|
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.
|
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-
|
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.
|
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
|
-
|
17
|
-
|
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,
|
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,
|
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,
|
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
|
-
|
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,
|
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,
|
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
|
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
|
-
|
138
|
-
|
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
|
-
|
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
|
-
|
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,
|
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
|
-
*
|
249
|
-
*
|
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
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
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
|
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
|
-
|
296
|
-
return
|
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
|
-
|
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",
|
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
|
-
|
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",
|
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
|
-
|
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",
|
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,
|
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",
|
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,
|
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,
|
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
|
-
|
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
|
-
|
513
|
-
|
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,
|
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
|
-
|
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",
|
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
|
-
|
599
|
+
long cstr_size = ba->bits + 1;
|
596
600
|
char cstr[cstr_size];
|
597
601
|
|
598
|
-
|
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
|
-
|
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
|
-
|
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.
|
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-
|
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.
|
53
|
+
version: 1.8.6
|
54
54
|
version:
|
55
55
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|