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 +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:
|