ingramj-bitarray 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -15,8 +15,7 @@ Example usage:
15
15
  bm.clear_bit 0
16
16
 
17
17
 
18
- The test/ directory has a unit test file. It also has a benchmark utility for
19
- comparison with Peter Cooper's pure Ruby BitField class.
18
+ The test/ directory has a unit test file, and benchmarking utility.
20
19
 
21
20
  The examples/ directory has bloom filter dictionary-lookup demonstration.
22
21
 
@@ -43,9 +42,8 @@ See the LICENSE file for copyright and license information.
43
42
 
44
43
  Some inspiration was taken from Peter Cooper's BitField class, and various Open
45
44
  Source bitarray implementations found online, but this implementation contains
46
- only original code, except for test/bitfield.rb, which is Peter Cooper's
47
- BitField class, and test/test.rb, which was modified from the BitField test
48
- code.
45
+ only original code, except for some parts for test.rb, which were modified from
46
+ BitField's unit test file.
49
47
 
50
48
  BitField: http://snippets.dzone.com/posts/show/4234
51
49
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.5.1
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{bitarray}
5
- s.version = "0.5.0"
5
+ s.version = "0.5.1"
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-06-01}
9
+ s.date = %q{2009-06-02}
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"]
@@ -26,7 +26,6 @@ Gem::Specification.new do |s|
26
26
  "examples/boolnet.rb",
27
27
  "ext/bitarray.c",
28
28
  "ext/extconf.rb",
29
- "test/bitfield.rb",
30
29
  "test/bm.rb",
31
30
  "test/test.rb"
32
31
  ]
@@ -38,8 +37,7 @@ Gem::Specification.new do |s|
38
37
  s.rubygems_version = %q{1.3.1}
39
38
  s.summary = %q{A bitarray class for Ruby, implemented as a C extension.}
40
39
  s.test_files = [
41
- "test/bitfield.rb",
42
- "test/test.rb",
40
+ "test/test.rb",
43
41
  "test/bm.rb",
44
42
  "examples/bloomfilter.rb",
45
43
  "examples/boolnet.rb"
@@ -2,122 +2,135 @@
2
2
  #include <limits.h>
3
3
  #include <string.h>
4
4
 
5
- /* Bits are stored in an array of unsigned ints. We'll use a couple of defines
6
- * for getting the size of unsigned ints in bytes and bits.
7
- */
8
5
  #define UINT_BYTES (sizeof(unsigned int))
9
6
  #define UINT_BITS (UINT_BYTES * CHAR_BIT)
10
7
 
11
- /* bitmask macro for accessing a particular bit inside an array element. */
12
- #define bitmask(bit) (1 << (bit % UINT_BITS))
8
+ /* Accessing a particular bit within a word. */
9
+ #define bitmask(bit) (1 << ((bit) % UINT_BITS))
10
+
11
+ /* Determining how many unsigned ints we need to store a given number of bits.
12
+ * We check if (bits - 1) is negative because the C standard helpfully
13
+ * specifies that in an arithmetic expression "... if either operand is
14
+ * unsigned long int, the other is converted to unsigned long int", causing
15
+ * large amounts of hilarity when one of the operands is negative.
16
+ */
17
+ #define uint_array_size(bits) (bits <= 0 ? 0 : (((bits) - 1) / UINT_BITS + 1))
18
+
19
+ /* Get the number of bits stored in a bitarray. */
20
+ #define bitarray_size(ba) (ba->bits)
13
21
 
14
- /* Bit Array structure. */
15
- struct bit_array {
16
- long bits; /* Number of bits. */
17
- long array_size; /* Size of the storage array. */
22
+ struct bitarray {
23
+ long bits; /* Number of bits. */
24
+ long array_size; /* Size of the storage array. */
18
25
  unsigned int *array; /* Array of unsigned ints, used for bit storage. */
19
26
  };
20
27
 
21
28
 
22
- /* Bit Array manipulation functions. */
29
+ /* Low-level bit-manipulation functions.
30
+ *
31
+ * These function are used by the Ruby interface functions to modify
32
+ * bitarray structures.
33
+ *
34
+ * Functions that take an index will raise an IndexError if it is out of range.
35
+ * Negative indices count from the end of the array.
36
+ */
23
37
 
24
- /* Set the specified bit to 1. Return 1 on success, 0 on failure. */
25
- static inline int
26
- set_bit(struct bit_array *ba, long bit)
38
+
39
+ /* This function is used by all of the bit-manipulation functions to check
40
+ * indices. It handles negative-index conversion and bounds checking.
41
+ */
42
+ static inline long
43
+ check_index(struct bitarray *ba, long index)
27
44
  {
28
- if (bit < 0) bit += ba->bits;
29
- if (bit >= ba->bits) {
30
- return 0;
45
+ if (index < 0) index += ba->bits;
46
+ if (index >= ba->bits) {
47
+ rb_raise(rb_eIndexError, "index %ld out of bit array", index);
31
48
  }
32
49
 
33
- ba->array[bit / UINT_BITS] |= bitmask(bit);
34
- return 1;
50
+ return index;
51
+ }
52
+
53
+
54
+ /* Set the specified bit to 1. */
55
+ static inline void
56
+ set_bit(struct bitarray *ba, long index)
57
+ {
58
+ index = check_index(ba, index);
59
+ ba->array[index / UINT_BITS] |= bitmask(index);
35
60
  }
36
61
 
37
62
 
38
63
  /* Set all bits to 1. */
39
- static inline int
40
- set_all_bits(struct bit_array *ba)
64
+ static inline void
65
+ set_all_bits(struct bitarray *ba)
41
66
  {
42
67
  memset(ba->array, 0xff, (ba->array_size * UINT_BYTES));
43
- return 1;
44
68
  }
45
69
 
46
70
 
47
- /* Clear the specified bit to 0. Return 1 on success, 0 on failure. */
48
- static inline int
49
- clear_bit(struct bit_array *ba, long bit)
71
+ /* Clear the specified bit to 0. */
72
+ static inline void
73
+ clear_bit(struct bitarray *ba, long index)
50
74
  {
51
- if (bit < 0) bit += ba->bits;
52
- if (bit >= ba->bits) {
53
- return 0;
54
- }
55
-
56
- ba->array[bit / UINT_BITS] &= ~bitmask(bit);
57
- return 1;
75
+ index = check_index(ba, index);
76
+ ba->array[index / UINT_BITS] &= ~bitmask(index);
58
77
  }
59
78
 
60
79
 
61
80
  /* Clear all bits to 0. */
62
- static inline int
63
- clear_all_bits(struct bit_array *ba)
81
+ static inline void
82
+ clear_all_bits(struct bitarray *ba)
64
83
  {
65
84
  memset(ba->array, 0x00, (ba->array_size * UINT_BYTES));
66
- return 1;
67
85
  }
68
86
 
69
87
 
70
- /* Toggle the state of the specified bit. Return 1 on success, 0 on failure. */
71
- static inline int
72
- toggle_bit(struct bit_array *ba, long bit)
88
+ /* Toggle the state of the specified bit. */
89
+ static inline void
90
+ toggle_bit(struct bitarray *ba, long index)
73
91
  {
74
- if (bit < 0) bit += ba->bits;
75
- if (bit >= ba->bits) {
76
- return 0;
77
- }
78
-
79
- ba->array[bit / UINT_BITS] ^= bitmask(bit);
80
- return 1;
92
+ index = check_index(ba, index);
93
+ ba->array[index / UINT_BITS] ^= bitmask(index);
81
94
  }
82
95
 
83
96
 
84
97
  /* Toggle the state of all bits. */
85
- static inline int
86
- toggle_all_bits(struct bit_array *ba)
98
+ static inline void
99
+ toggle_all_bits(struct bitarray *ba)
87
100
  {
88
101
  long i;
89
102
  for(i = 0; i < ba->array_size; i++) {
90
103
  ba->array[i] ^= ~0ul; /* ~0 = all bits set. */
91
104
  }
92
- return 1;
93
105
  }
94
106
 
95
107
 
96
- /* Assign the specified value to a bit. Return 1 on success, 0 on invalid bit
97
- * index, and -1 on invalid value. */
98
- static inline int
99
- assign_bit(struct bit_array *ba, long bit, int value)
108
+ /* Assign the specified value to a bit. If the specified value is invalid,
109
+ * raises an ArgumentError.
110
+ */
111
+ static inline void
112
+ assign_bit(struct bitarray *ba, long index, int value)
100
113
  {
101
114
  if (value == 0) {
102
- return clear_bit(ba, bit);
115
+ clear_bit(ba, index);
103
116
  } else if (value == 1) {
104
- return set_bit(ba, bit);
117
+ set_bit(ba, index);
105
118
  } else {
106
- return -1;
119
+ rb_raise(rb_eArgError, "bit value %d out of range", value);
107
120
  }
108
121
  }
109
122
 
110
123
 
111
- /* Get the state of the specified bit. Return -1 on failure. */
124
+ /* Get the state of the specified bit. */
112
125
  static inline int
113
- get_bit(struct bit_array *ba, long bit)
126
+ get_bit(struct bitarray *ba, long index)
114
127
  {
115
- if (bit < 0) bit += ba->bits;
116
- if (bit >= ba->bits) {
117
- return -1;
118
- }
128
+ index = check_index(ba, index);
119
129
 
120
- unsigned int b = (ba->array[bit / UINT_BITS] & bitmask(bit));
130
+ /* We could shift the bit down, but this is easier. We need an unsigned int
131
+ * to prevent overflow.
132
+ */
133
+ unsigned int b = (ba->array[index / UINT_BITS] & bitmask(index));
121
134
  if (b > 0) {
122
135
  return 1;
123
136
  } else {
@@ -128,7 +141,7 @@ get_bit(struct bit_array *ba, long bit)
128
141
 
129
142
  /* Return the number of set bits in the array. */
130
143
  static inline long
131
- total_set(struct bit_array *ba)
144
+ total_set(struct bitarray *ba)
132
145
  {
133
146
  /* This is basically the algorithm from K&R, with a running total for all
134
147
  * array elements. There are faster algorithms, but this one is simpler to
@@ -148,13 +161,110 @@ total_set(struct bit_array *ba)
148
161
  }
149
162
 
150
163
 
151
- /* Ruby Interface Functions. */
164
+ /* Initialize an already-allocated bitarray structure. The array is initialized
165
+ * to all zeros.
166
+ */
167
+ static inline void
168
+ initialize_bitarray(struct bitarray *ba, long size)
169
+ {
170
+ if (size <= 0) {
171
+ ba->bits = 0;
172
+ ba->array_size = 0;
173
+ ba->array = NULL;
174
+ return;
175
+ }
176
+
177
+ ba->bits = size;
178
+ ba->array_size = uint_array_size(size);
179
+ ba->array = ruby_xcalloc(ba->array_size, UINT_BYTES);
180
+ }
181
+
182
+
183
+ /* Initialize an already-allocated bitarray structure as a copy of another
184
+ * bitarray structure.
185
+ */
186
+ static inline void
187
+ initialize_bitarray_copy(struct bitarray *new_ba, struct bitarray *orig_ba)
188
+ {
189
+ new_ba->bits = orig_ba->bits;
190
+ new_ba->array_size = orig_ba->array_size;
191
+ new_ba->array = ruby_xmalloc2(new_ba->array_size, UINT_BYTES);
152
192
 
193
+ memcpy(new_ba->array, orig_ba->array, new_ba->array_size * UINT_BYTES);
194
+ }
195
+
196
+
197
+ /* Initialize an already-allocated bitarray structure as the concatenation of
198
+ * two other bitarrays structures.
199
+ */
200
+ static void
201
+ initialize_bitarray_concat(struct bitarray *new_ba, struct bitarray *x_ba,
202
+ struct bitarray *y_ba)
203
+ {
204
+ new_ba->bits = x_ba->bits + y_ba->bits;
205
+ new_ba->array_size = uint_array_size(new_ba->bits);
206
+ new_ba->array = ruby_xmalloc2(new_ba->array_size, UINT_BYTES);
207
+
208
+
209
+ /* For each bit set in x_ba and y_ba, set the corresponding bit in new_ba.
210
+ *
211
+ * First, copy x_ba->array to the beginning of new_ba->array.
212
+ */
213
+ memcpy(new_ba->array, x_ba->array, x_ba->array_size * UINT_BYTES);
214
+
215
+ /* Then, if x_ba->bits is a multiple of UINT_BITS, we can just copy
216
+ * y_ba->array onto the end of new_ba->array.
217
+ *
218
+ * Otherwise, we need to go through y_ba->array bit-by-bit and set the
219
+ * appropriate bits in new_ba->array.
220
+ */
221
+ if ((x_ba->bits % UINT_BITS) == 0) {
222
+ unsigned int *start = new_ba->array + x_ba->array_size;
223
+ memcpy(start, y_ba->array, y_ba->array_size * UINT_BYTES);
224
+ } else {
225
+ long y_index, new_index;
226
+ for (y_index = 0, new_index = x_ba->bits;
227
+ y_index < y_ba->bits;
228
+ y_index++, new_index++)
229
+ {
230
+ if (get_bit(y_ba, y_index) == 1) {
231
+ set_bit(new_ba, new_index);
232
+ } else {
233
+ clear_bit(new_ba, new_index);
234
+ }
235
+ }
236
+ }
237
+
238
+ }
239
+
240
+
241
+
242
+ /* Ruby Interface Functions.
243
+ *
244
+ * These functions put a Ruby face on top of the lower-level functions. With
245
+ * very few exceptions, they should not access the bitarray structs' members
246
+ * directly.
247
+ *
248
+ * "bitarray" refers to the C structure. "BitArray" refers to the Ruby class.
249
+ *
250
+ * All publicly-accessible functions (those with an rb_define_method call in
251
+ * Init_bitarray) should have RDoc comment headers.
252
+ *
253
+ * When in doubt, see how array.c does things.
254
+ */
255
+
256
+
257
+ /* Our BitArray class. This is initialized in Init_bitarray, but we declare it
258
+ * here because a few functions need it.
259
+ */
153
260
  static VALUE rb_bitarray_class;
154
261
 
155
262
 
263
+ /* This gets called when a BitArray is garbage collected. It frees the memory
264
+ * used by the bitarray struct.
265
+ */
156
266
  static void
157
- rb_bitarray_free(struct bit_array *ba)
267
+ rb_bitarray_free(struct bitarray *ba)
158
268
  {
159
269
  if (ba && ba->array) {
160
270
  ruby_xfree(ba->array);
@@ -163,33 +273,96 @@ rb_bitarray_free(struct bit_array *ba)
163
273
  }
164
274
 
165
275
 
276
+ /* This function is called by BitArray.new to allocate a new BitArray.
277
+ * Initialization is done in a seperate function.
278
+ *
279
+ * This function can be called directly with BitArray.allocate, but that is not
280
+ * very useful.
281
+ */
166
282
  static VALUE
167
283
  rb_bitarray_alloc(VALUE klass)
168
284
  {
169
- struct bit_array *ba;
170
- return Data_Make_Struct(rb_bitarray_class, struct bit_array, NULL,
285
+ struct bitarray *ba;
286
+ return Data_Make_Struct(rb_bitarray_class, struct bitarray, NULL,
171
287
  rb_bitarray_free, ba);
172
288
  }
173
289
 
174
290
 
291
+ /* Initialization helper-function prototypes. These functions are defined after
292
+ * rb_bitarray_initialize.
293
+ */
294
+ static VALUE rb_bitarray_from_string(VALUE self, VALUE string);
295
+ static VALUE rb_bitarray_from_array(VALUE self, VALUE array);
296
+
297
+
298
+ /* call-seq:
299
+ * BitArray.new(size)
300
+ * BitArray.new(string)
301
+ * BitArray.new(array)
302
+ *
303
+ * When called with a size, creates a new BitArray of the specified size, with
304
+ * all bits cleared. When called with a string or an array, creates a new
305
+ * BitArray from the argument.
306
+ *
307
+ * If a string is given, it should consist of ones and zeroes. If there are
308
+ * any other characters in the string, the first invalid character and all
309
+ * following characters will be ignored.
310
+ *
311
+ * b = BitArray.new("10101010") => 10101010
312
+ * b = BitArray.new("1010abcd") => 1010
313
+ * b = BitArray.new("abcd") =>
314
+ *
315
+ * If an array is given, the BitArray is initialized from its elements using
316
+ * the following rules:
317
+ *
318
+ * 1. 0, false, or nil => 0
319
+ * 2. anything else => 1
320
+ *
321
+ * Note that the 0 is a number, not a string. "Anything else" means strings,
322
+ * symbols, non-zero numbers, subarrays, etc.
323
+ *
324
+ * b = BitArray.new([0,0,0,1,1,0]) => 000110
325
+ * b = BitArray.new([false, true, false]) => 010
326
+ * b = BitArray.new([:a, :b, :c, [:d, :e]]) => 1111
327
+ */
328
+ static VALUE
329
+ rb_bitarray_initialize(VALUE self, VALUE arg)
330
+ {
331
+ if (TYPE(arg) == T_FIXNUM || TYPE(arg) == T_BIGNUM) {
332
+ struct bitarray *ba;
333
+ Data_Get_Struct(self, struct bitarray, ba);
334
+
335
+ initialize_bitarray(ba, NUM2LONG(arg));
336
+
337
+ return self;
338
+
339
+ } else if (TYPE(arg) == T_STRING) {
340
+ return rb_bitarray_from_string(self, arg);
341
+ } else if (TYPE(arg) == T_ARRAY) {
342
+ return rb_bitarray_from_array(self, arg);
343
+ } else {
344
+ rb_raise(rb_eArgError, "must be size, string, or array");
345
+ }
346
+ }
347
+
348
+
175
349
  /* Create a new BitArray from a string. Called by rb_bitarray_initialize. */
176
350
  static VALUE
177
- rb_bitarray_from_string(VALUE self, VALUE arg)
351
+ rb_bitarray_from_string(VALUE self, VALUE string)
178
352
  {
179
- struct bit_array *ba;
180
- Data_Get_Struct(self, struct bit_array, ba);
353
+ struct bitarray *ba;
354
+ Data_Get_Struct(self, struct bitarray, ba);
181
355
 
182
356
  /* Extract a C-string from arg. */
183
- long str_len = RSTRING_LEN(arg) + 1;
357
+ long str_len = RSTRING_LEN(string) + 1;
184
358
  char cstr[str_len];
185
- strncpy(cstr, StringValueCStr(arg), str_len);
359
+ strncpy(cstr, StringValueCStr(string), str_len);
186
360
 
187
361
  /* If the string doesn't begin with a '1' or '0', return an empty
188
362
  * BitArray.
189
363
  */
190
364
  if (cstr[0] != '0' && cstr[0] != '1') {
191
- ba->bits = 0;
192
- ba->array_size = 0;
365
+ initialize_bitarray(ba, 0);
193
366
  return self;
194
367
  }
195
368
 
@@ -205,9 +378,7 @@ rb_bitarray_from_string(VALUE self, VALUE arg)
205
378
  }
206
379
 
207
380
  /* Setup the BitArray structure. */
208
- ba->bits = strlen(cstr);
209
- ba->array_size = ((ba->bits - 1) / UINT_BITS) + 1;
210
- ba->array = ruby_xmalloc(ba->array_size * UINT_BYTES);
381
+ initialize_bitarray(ba, strlen(cstr));
211
382
 
212
383
  /* Initialize the bit array with the string. */
213
384
  for (i = 0; i < ba->bits; i++) {
@@ -224,19 +395,18 @@ rb_bitarray_from_string(VALUE self, VALUE arg)
224
395
 
225
396
  /* Create a new BitArray from an Array. Called by rb_bitarray_initialize */
226
397
  static VALUE
227
- rb_bitarray_from_array(VALUE self, VALUE arg)
398
+ rb_bitarray_from_array(VALUE self, VALUE array)
228
399
  {
229
- struct bit_array *ba;
230
- Data_Get_Struct(self, struct bit_array, ba);
400
+ struct bitarray *ba;
401
+ Data_Get_Struct(self, struct bitarray, ba);
231
402
 
232
- ba->bits = RARRAY_LEN(arg);
233
- ba->array_size = ((ba->bits - 1) / UINT_BITS) + 1;
234
- ba->array = ruby_xmalloc(ba->array_size * UINT_BYTES);
403
+ long size = RARRAY_LEN(array);
404
+ initialize_bitarray(ba, size);
235
405
 
236
406
  VALUE e;
237
407
  long i;
238
- for (i = 0; i < ba->bits; i++) {
239
- e = rb_ary_entry(arg, i);
408
+ for (i = 0; i < size; i++) {
409
+ e = rb_ary_entry(array, i);
240
410
 
241
411
  switch (TYPE(e)) {
242
412
  case T_FIXNUM: /* fixnums and bignums treated the same. */
@@ -256,66 +426,6 @@ rb_bitarray_from_array(VALUE self, VALUE arg)
256
426
  }
257
427
 
258
428
 
259
- /* call-seq:
260
- * BitArray.new(size)
261
- * BitArray.new(string)
262
- * BitArray.new(array)
263
- *
264
- * When called with a size, creates a new BitArray of the specified size, with
265
- * all bits cleared. When called with a string or an array, creates a new
266
- * BitArray from the argument.
267
- *
268
- * If a string is given, it should consist of ones and zeroes. If there are
269
- * any other characters in the string, the first invalid character and all
270
- * following characters will be ignored.
271
- *
272
- * b = BitArray.new("10101010") => 10101010
273
- * b = BitArray.new("1010abcd") => 1010
274
- * b = BitArray.new("abcd") =>
275
- *
276
- * If an array is given, the BitArray is initialized from its elements using
277
- * the following rules:
278
- *
279
- * 1. 0, false, or nil => 0
280
- * 2. anything else => 1
281
- *
282
- * Note that the 0 is a number, not a string. "Anything else" means strings,
283
- * symbols, non-zero numbers, subarrays, etc.
284
- *
285
- * b = BitArray.new([0,0,0,1,1,0]) => 000110
286
- * b = BitArray.new([false, true, false]) => 010
287
- * b = BitArray.new([:a, :b, :c, [:d, :e]]) => 1111
288
- */
289
- static VALUE
290
- rb_bitarray_initialize(VALUE self, VALUE arg)
291
- {
292
- if (TYPE(arg) == T_FIXNUM || TYPE(arg) == T_BIGNUM) {
293
- struct bit_array *ba;
294
- Data_Get_Struct(self, struct bit_array, ba);
295
-
296
- long bits = NUM2LONG(arg);
297
- if (bits <= 0) {
298
- ba->bits = 0;
299
- ba->array_size = 0;
300
- return self;
301
- }
302
-
303
- ba->bits = bits;
304
- ba->array_size = ((bits - 1) / UINT_BITS) + 1;
305
- ba->array = ruby_xcalloc(ba->array_size, UINT_BYTES);
306
-
307
- return self;
308
-
309
- } else if (TYPE(arg) == T_STRING) {
310
- return rb_bitarray_from_string(self, arg);
311
- } else if (TYPE(arg) == T_ARRAY) {
312
- return rb_bitarray_from_array(self, arg);
313
- } else {
314
- rb_raise(rb_eArgError, "must be size, string, or array");
315
- }
316
- }
317
-
318
-
319
429
  /* call-seq:
320
430
  * bitarray.clone -> a_bitarray
321
431
  * bitarray.dup -> a_bitarray
@@ -325,15 +435,11 @@ rb_bitarray_initialize(VALUE self, VALUE arg)
325
435
  static VALUE
326
436
  rb_bitarray_initialize_copy(VALUE self, VALUE orig)
327
437
  {
328
- struct bit_array *new_ba, *orig_ba;
329
- Data_Get_Struct(self, struct bit_array, new_ba);
330
- Data_Get_Struct(orig, struct bit_array, orig_ba);
438
+ struct bitarray *new_ba, *orig_ba;
439
+ Data_Get_Struct(self, struct bitarray, new_ba);
440
+ Data_Get_Struct(orig, struct bitarray, orig_ba);
331
441
 
332
- new_ba->bits = orig_ba->bits;
333
- new_ba->array_size = orig_ba->array_size;
334
- new_ba->array = ruby_xcalloc(new_ba->array_size, UINT_BYTES);
335
-
336
- memcpy(new_ba->array, orig_ba->array, (new_ba->array_size * UINT_BYTES));
442
+ initialize_bitarray_copy(new_ba, orig_ba);
337
443
 
338
444
  return self;
339
445
  }
@@ -348,40 +454,18 @@ rb_bitarray_initialize_copy(VALUE self, VALUE orig)
348
454
  static VALUE
349
455
  rb_bitarray_concat(VALUE x, VALUE y)
350
456
  {
351
- /* Get the bit_arrays from x and y */
352
- struct bit_array *x_ba, *y_ba;
353
- Data_Get_Struct(x, struct bit_array, x_ba);
354
- Data_Get_Struct(y, struct bit_array, y_ba);
355
-
356
- /* Create a new BitArray, and its bit_array */
357
- VALUE z;
358
- struct bit_array *z_ba;
359
- z = rb_bitarray_alloc(rb_bitarray_class);
360
- rb_bitarray_initialize(z, LONG2NUM(x_ba->bits + y_ba->bits));
361
- Data_Get_Struct(z, struct bit_array, z_ba);
362
-
363
- /* For each bit set in x and y, set the corresponding bit in z. First, copy
364
- * x to the beginning of z. Then, if x->bits is a multiple of UINT_BITS, we
365
- * can just copy y onto the end of z. Otherwise, we need to go through y
366
- * bit-by-bit and set the appropriate bits in z.
367
- */
368
- memcpy(z_ba->array, x_ba->array, (x_ba->array_size * UINT_BYTES));
369
- if ((x_ba->bits % UINT_BITS) == 0) {
370
- unsigned int *start = z_ba->array + x_ba->array_size;
371
- memcpy(start, y_ba->array, (y_ba->array_size * UINT_BYTES));
372
- } else {
373
- long y_index, z_index;
374
- for (y_index = 0, z_index = x_ba->bits;
375
- y_index < y_ba->bits;
376
- y_index++, z_index++)
377
- {
378
- if (get_bit(y_ba, y_index) == 1) {
379
- set_bit(z_ba, z_index);
380
- } else {
381
- clear_bit(z_ba, z_index);
382
- }
383
- }
384
- }
457
+ /* Get the bitarrays from x and y */
458
+ struct bitarray *x_ba, *y_ba;
459
+ Data_Get_Struct(x, struct bitarray, x_ba);
460
+ Data_Get_Struct(y, struct bitarray, y_ba);
461
+
462
+ /* Create a new BitArray, and its bitarray structure*/
463
+ VALUE z = rb_bitarray_alloc(rb_bitarray_class);
464
+ struct bitarray *z_ba;
465
+ Data_Get_Struct(z, struct bitarray, z_ba);
466
+
467
+ initialize_bitarray_concat(z_ba, x_ba, y_ba);
468
+
385
469
  return z;
386
470
  }
387
471
 
@@ -395,10 +479,10 @@ rb_bitarray_concat(VALUE x, VALUE y)
395
479
  static VALUE
396
480
  rb_bitarray_size(VALUE self)
397
481
  {
398
- struct bit_array *ba;
399
- Data_Get_Struct(self, struct bit_array, ba);
482
+ struct bitarray *ba;
483
+ Data_Get_Struct(self, struct bitarray, ba);
400
484
 
401
- return LONG2NUM(ba->bits);
485
+ return LONG2NUM(bitarray_size(ba));
402
486
  }
403
487
 
404
488
 
@@ -410,11 +494,10 @@ rb_bitarray_size(VALUE self)
410
494
  static VALUE
411
495
  rb_bitarray_total_set(VALUE self)
412
496
  {
413
- struct bit_array *ba;
414
- Data_Get_Struct(self, struct bit_array, ba);
497
+ struct bitarray *ba;
498
+ Data_Get_Struct(self, struct bitarray, ba);
415
499
 
416
- long count = total_set(ba);
417
- return LONG2NUM(count);
500
+ return LONG2NUM(total_set(ba));
418
501
  }
419
502
 
420
503
 
@@ -426,18 +509,13 @@ rb_bitarray_total_set(VALUE self)
426
509
  * +IndexError+ is raised.
427
510
  */
428
511
  static VALUE
429
- rb_bitarray_set_bit(VALUE self, VALUE bit)
512
+ rb_bitarray_set_bit(VALUE self, VALUE index)
430
513
  {
431
- struct bit_array *ba;
432
- Data_Get_Struct(self, struct bit_array, ba);
433
-
434
- long index = NUM2LONG(bit);
435
-
436
- if (set_bit(ba, index)) {
437
- return self;
438
- } else {
439
- rb_raise(rb_eIndexError, "index %ld out of bit array", index);
440
- }
514
+ struct bitarray *ba;
515
+ Data_Get_Struct(self, struct bitarray, ba);
516
+
517
+ set_bit(ba, NUM2LONG(index));
518
+ return self;
441
519
  }
442
520
 
443
521
 
@@ -449,14 +527,11 @@ rb_bitarray_set_bit(VALUE self, VALUE bit)
449
527
  static VALUE
450
528
  rb_bitarray_set_all_bits(VALUE self)
451
529
  {
452
- struct bit_array *ba;
453
- Data_Get_Struct(self, struct bit_array, ba);
530
+ struct bitarray *ba;
531
+ Data_Get_Struct(self, struct bitarray, ba);
454
532
 
455
- if(set_all_bits(ba)) {
456
- return self;
457
- } else {
458
- rb_bug("BitArray#set_all_bits failed. This should not occur.");
459
- }
533
+ set_all_bits(ba);
534
+ return self;
460
535
  }
461
536
 
462
537
 
@@ -468,18 +543,13 @@ rb_bitarray_set_all_bits(VALUE self)
468
543
  * +IndexError+ is raised.
469
544
  */
470
545
  static VALUE
471
- rb_bitarray_clear_bit(VALUE self, VALUE bit)
546
+ rb_bitarray_clear_bit(VALUE self, VALUE index)
472
547
  {
473
- struct bit_array *ba;
474
- Data_Get_Struct(self, struct bit_array, ba);
548
+ struct bitarray *ba;
549
+ Data_Get_Struct(self, struct bitarray, ba);
475
550
 
476
- long index = NUM2LONG(bit);
477
-
478
- if (clear_bit(ba, index)) {
479
- return self;
480
- } else {
481
- rb_raise(rb_eIndexError, "index %ld out of bit array", index);
482
- }
551
+ clear_bit(ba, NUM2LONG(index));
552
+ return self;
483
553
  }
484
554
 
485
555
 
@@ -491,14 +561,11 @@ rb_bitarray_clear_bit(VALUE self, VALUE bit)
491
561
  static VALUE
492
562
  rb_bitarray_clear_all_bits(VALUE self)
493
563
  {
494
- struct bit_array *ba;
495
- Data_Get_Struct(self, struct bit_array, ba);
564
+ struct bitarray *ba;
565
+ Data_Get_Struct(self, struct bitarray, ba);
496
566
 
497
- if(clear_all_bits(ba)) {
498
- return self;
499
- } else {
500
- rb_bug("BitArray#clear_all_bits failed. This should not occur.");
501
- }
567
+ clear_all_bits(ba);
568
+ return self;
502
569
  }
503
570
 
504
571
 
@@ -510,18 +577,13 @@ rb_bitarray_clear_all_bits(VALUE self)
510
577
  * +IndexError+ is raised.
511
578
  */
512
579
  static VALUE
513
- rb_bitarray_toggle_bit(VALUE self, VALUE bit)
580
+ rb_bitarray_toggle_bit(VALUE self, VALUE index)
514
581
  {
515
- struct bit_array *ba;
516
- Data_Get_Struct(self, struct bit_array, ba);
517
-
518
- long index = NUM2LONG(bit);
582
+ struct bitarray *ba;
583
+ Data_Get_Struct(self, struct bitarray, ba);
519
584
 
520
- if (toggle_bit(ba, index)) {
521
- return self;
522
- } else {
523
- rb_raise(rb_eIndexError, "index %ld out of bit array", index);
524
- }
585
+ toggle_bit(ba, NUM2LONG(index));
586
+ return self;
525
587
  }
526
588
 
527
589
 
@@ -533,82 +595,19 @@ rb_bitarray_toggle_bit(VALUE self, VALUE bit)
533
595
  static VALUE
534
596
  rb_bitarray_toggle_all_bits(VALUE self)
535
597
  {
536
- struct bit_array *ba;
537
- Data_Get_Struct(self, struct bit_array, ba);
538
-
539
- if(toggle_all_bits(ba)) {
540
- return self;
541
- } else {
542
- rb_bug("BitArray#clear_all_bits failed. This should not occur.");
543
- }
544
- }
598
+ struct bitarray *ba;
599
+ Data_Get_Struct(self, struct bitarray, ba);
545
600
 
546
- /* Return an individual bit. */
547
- static VALUE
548
- rb_bitarray_get_bit(VALUE self, long index)
549
- {
550
- struct bit_array *ba;
551
- Data_Get_Struct(self, struct bit_array, ba);
552
-
553
- int bit_value = get_bit(ba, index);
554
-
555
- if (bit_value >= 0) {
556
- return INT2NUM(bit_value);
557
- } else {
558
- rb_raise(rb_eIndexError, "index %ld out of bit array", index);
559
- }
601
+ toggle_all_bits(ba);
602
+ return self;
560
603
  }
561
604
 
562
605
 
563
- /* Create a new BitArray from a subsequence of x. */
564
- static VALUE
565
- rb_bitarray_subseq(VALUE x, long beg, long len)
566
- {
567
-
568
- struct bit_array *x_ba;
569
- Data_Get_Struct(x, struct bit_array, x_ba);
570
-
571
- /* Quick exit - a negative length, or a beginning past the end of the
572
- * array returns nil.
573
- */
574
- if (beg < 0) {
575
- beg += x_ba->bits;
576
- }
577
- if (len < 0 || beg > x_ba->bits) {
578
- return Qnil;
579
- }
580
-
581
- /* Make sure that we don't try getting more bits than x has. We handle this
582
- * the same way as Array; if beg+len is past the end of x, shorten len.
583
- */
584
- if (x_ba->bits < len || x_ba->bits < (beg + len)) {
585
- len = x_ba->bits - beg;
586
- }
587
-
588
- /* Create a new BitArray of the appropriate size. */
589
- VALUE y;
590
- y = rb_bitarray_alloc(rb_bitarray_class);
591
- rb_bitarray_initialize(y, LONG2NUM(len));
592
- /* If our length is 0, we can just return now. */
593
- if (len == 0) {
594
- return y;
595
- }
596
- struct bit_array *y_ba;
597
- Data_Get_Struct(y, struct bit_array, y_ba);
598
-
599
- /* For each set bit in x[beg..len], set the corresponding bit in y. */
600
- long x_index, y_index;
601
- for (x_index = beg, y_index = 0;
602
- x_index < beg + len;
603
- x_index++, y_index++)
604
- {
605
- if (get_bit(x_ba, x_index) == 1) {
606
- set_bit(y_ba, y_index);
607
- }
608
- }
609
-
610
- return y;
611
- }
606
+ /* Bit-reference helper-function prototypes. These are defined after
607
+ * rb_bitarray_bitref.
608
+ */
609
+ static inline VALUE rb_bitarray_get_bit(VALUE self, long index);
610
+ static VALUE rb_bitarray_subseq(VALUE self, long beg, long len);
612
611
 
613
612
 
614
613
  /* call-seq:
@@ -622,7 +621,6 @@ rb_bitarray_subseq(VALUE x, long beg, long len)
622
621
  * _index_ is greater than the capacity of _bitarray_, an +IndexError+ is
623
622
  * raised.
624
623
  */
625
-
626
624
  static VALUE
627
625
  rb_bitarray_bitref(int argc, VALUE *argv, VALUE self)
628
626
  {
@@ -650,8 +648,8 @@ rb_bitarray_bitref(int argc, VALUE *argv, VALUE self)
650
648
  return rb_bitarray_get_bit(self, FIX2LONG(arg));
651
649
  }
652
650
 
653
- struct bit_array *ba;
654
- Data_Get_Struct(self, struct bit_array, ba);
651
+ struct bitarray *ba;
652
+ Data_Get_Struct(self, struct bitarray, ba);
655
653
  /* Next we see if arg is a range. rb_range_beg_len is defined in range.c
656
654
  * If arg is not a range, it returns Qfalse. If arg is a range, but it
657
655
  * refers to invalid indices, it returns Qnil. Otherwise, it sets beg and
@@ -671,6 +669,67 @@ rb_bitarray_bitref(int argc, VALUE *argv, VALUE self)
671
669
  }
672
670
 
673
671
 
672
+ /* Return an individual bit. */
673
+ static inline VALUE
674
+ rb_bitarray_get_bit(VALUE self, long index)
675
+ {
676
+ struct bitarray *ba;
677
+ Data_Get_Struct(self, struct bitarray, ba);
678
+
679
+ return INT2NUM(get_bit(ba, index));
680
+ }
681
+
682
+
683
+ /* Create a new BitArray from a subsequence of x. */
684
+ static VALUE
685
+ rb_bitarray_subseq(VALUE x, long beg, long len)
686
+ {
687
+
688
+ struct bitarray *x_ba;
689
+ Data_Get_Struct(x, struct bitarray, x_ba);
690
+
691
+ /* Quick exit - a negative length, or a beginning past the end of the
692
+ * array returns nil.
693
+ */
694
+ if (beg < 0) {
695
+ beg += bitarray_size(x_ba);
696
+ }
697
+ if (len < 0 || beg > bitarray_size(x_ba)) {
698
+ return Qnil;
699
+ }
700
+
701
+ /* Make sure that we don't try getting more bits than x has. We handle this
702
+ * the same way as Array; if beg+len is past the end of x, shorten len.
703
+ */
704
+ if (bitarray_size(x_ba) < len || bitarray_size(x_ba) < (beg + len)) {
705
+ len = bitarray_size(x_ba) - beg;
706
+ }
707
+
708
+ /* Create a new BitArray of the appropriate size. */
709
+ VALUE y = rb_bitarray_alloc(rb_bitarray_class);
710
+ rb_bitarray_initialize(y, LONG2NUM(len));
711
+ /* If our length is 0, we can just return now. */
712
+ if (len == 0) {
713
+ return y;
714
+ }
715
+ struct bitarray *y_ba;
716
+ Data_Get_Struct(y, struct bitarray, y_ba);
717
+
718
+ /* For each set bit in x[beg..len], set the corresponding bit in y. */
719
+ long x_index, y_index;
720
+ for (x_index = beg, y_index = 0;
721
+ x_index < beg + len;
722
+ x_index++, y_index++)
723
+ {
724
+ if (get_bit(x_ba, x_index) == 1) {
725
+ set_bit(y_ba, y_index);
726
+ }
727
+ }
728
+
729
+ return y;
730
+ }
731
+
732
+
674
733
  /* call-seq:
675
734
  * bitarray[index] = value -> value
676
735
  *
@@ -682,22 +741,13 @@ rb_bitarray_bitref(int argc, VALUE *argv, VALUE self)
682
741
  * raised.
683
742
  */
684
743
  static VALUE
685
- rb_bitarray_assign_bit(VALUE self, VALUE bit, VALUE value)
744
+ rb_bitarray_assign_bit(VALUE self, VALUE index, VALUE value)
686
745
  {
687
- struct bit_array *ba;
688
- Data_Get_Struct(self, struct bit_array, ba);
689
-
690
- long index = NUM2LONG(bit);
691
- int bit_value = NUM2INT(value);
746
+ struct bitarray *ba;
747
+ Data_Get_Struct(self, struct bitarray, ba);
692
748
 
693
- int result = assign_bit(ba, index, bit_value);
694
- if (result == 1) {
695
- return value;
696
- } else if (result == 0) {
697
- rb_raise(rb_eIndexError, "index %ld out of bit array", index);
698
- } else {
699
- rb_raise(rb_eRuntimeError, "bit value %d out of range", bit_value);
700
- }
749
+ assign_bit(ba, NUM2LONG(index), NUM2INT(value));
750
+ return value;
701
751
  }
702
752
 
703
753
 
@@ -710,17 +760,17 @@ rb_bitarray_assign_bit(VALUE self, VALUE bit, VALUE value)
710
760
  static VALUE
711
761
  rb_bitarray_inspect(VALUE self)
712
762
  {
713
- struct bit_array *ba;
714
- Data_Get_Struct(self, struct bit_array, ba);
763
+ struct bitarray *ba;
764
+ Data_Get_Struct(self, struct bitarray, ba);
715
765
 
716
- long cstr_size = ba->bits + 1;
766
+ long cstr_size = bitarray_size(ba) + 1;
717
767
  char cstr[cstr_size];
718
768
 
719
769
  long i;
720
- for (i = 0; i < ba->bits; i++) {
770
+ for (i = 0; i < bitarray_size(ba); i++) {
721
771
  cstr[i] = get_bit(ba, i) + '0';
722
772
  }
723
- cstr[ba->bits] = '\0';
773
+ cstr[cstr_size - 1] = '\0';
724
774
 
725
775
  VALUE str = rb_str_new2(cstr);
726
776
  return str;
@@ -735,10 +785,10 @@ rb_bitarray_inspect(VALUE self)
735
785
  static VALUE
736
786
  rb_bitarray_to_a(VALUE self)
737
787
  {
738
- struct bit_array *ba;
739
- Data_Get_Struct(self, struct bit_array, ba);
788
+ struct bitarray *ba;
789
+ Data_Get_Struct(self, struct bitarray, ba);
740
790
 
741
- long array_size = ba->bits;
791
+ long array_size = bitarray_size(ba);
742
792
  VALUE c_array[array_size];
743
793
 
744
794
  int i;
@@ -766,13 +816,13 @@ rb_bitarray_to_a(VALUE self)
766
816
  static VALUE
767
817
  rb_bitarray_each(VALUE self)
768
818
  {
769
- struct bit_array *ba;
770
- Data_Get_Struct(self, struct bit_array, ba);
819
+ struct bitarray *ba;
820
+ Data_Get_Struct(self, struct bitarray, ba);
771
821
 
772
822
  long i;
773
823
 
774
824
  RETURN_ENUMERATOR(self, 0, 0);
775
- for (i = 0; i < ba->bits; i++) {
825
+ for (i = 0; i < bitarray_size(ba); i++) {
776
826
  int bit_value = get_bit(ba, i);
777
827
  rb_yield(INT2NUM(bit_value));
778
828
  }
data/test/bm.rb CHANGED
@@ -1,61 +1,37 @@
1
- require 'bitfield'
2
1
  require 'bitarray'
3
2
  require 'benchmark'
4
3
 
5
4
  Benchmark.bm(28) { |bm|
6
- puts "---------------------------- Object instantiation (10,000 iterations)"
7
- bm.report("BitField initialize") { 10000.times { BitField.new(256) } }
8
5
  bm.report("BitArray initialize") { 10000.times { BitArray.new(256) } }
9
6
  s = "0"*256
10
7
  bm.report("BitArray init from string") { 10000.times { BitArray.new(s) } }
11
8
  a = [0]*256
12
9
  bm.report("BitArray init from array") { 10000.times { BitArray.new(a) } }
13
10
 
14
- bf = BitField.new(256)
15
11
  ba = BitArray.new(256)
16
12
 
17
- puts "---------------------------- Element Reading (10,000 iterations)"
18
- bm.report("BitField []") { 10000.times { bf[rand(256)] } }
19
13
  bm.report("BitArray []") { 10000.times { ba[rand(256)] } }
20
-
21
- puts "---------------------------- Element Writing (10,000 iterations)"
22
- bm.report("BitField []=") { 10000.times { bf[rand(256)] = [0,1][rand(2)] } }
23
14
  bm.report("BitArray []=") { 10000.times { ba[rand(256)] = [0,1][rand(2)] } }
24
-
25
- puts "---------------------------- Element Enumeration (10,000 iterations)"
26
- bm.report("BitField each") { 10000.times { bf.each {|b| b } } }
27
15
  bm.report("BitArray each") { 10000.times { ba.each {|b| b } } }
28
-
29
- puts "---------------------------- To String (10,000 iterations)"
30
- bm.report("BitField to_s") { 10000.times { bf.to_s } }
31
16
  bm.report("BitArray to_s") { 10000.times { ba.to_s } }
32
-
33
- puts "---------------------------- To Array (10,000 iterations)"
34
- bm.report("BitField to_a") { 10000.times { bf.to_a } }
35
17
  bm.report("BitArray to_a") { 10000.times { ba.to_a } }
36
-
37
- puts "---------------------------- Total Set (100,000 iterations)"
38
- bf = BitField.new(256)
18
+
39
19
  ba = BitArray.new(256)
40
- bm.report("BitField total_set (none)") { 100000.times { bf.total_set } }
41
- bm.report("BitArray total_set (none)") { 100000.times { ba.total_set } }
42
- bf.each {|b| b = 1}
20
+ bm.report("BitArray total_set (none)") { 10000.times { ba.total_set } }
43
21
  ba.set_all_bits
44
- bm.report("BitField total_set (all)") { 100000.times { bf.total_set } }
45
- bm.report("BitArray total_set (all)") { 100000.times { ba.total_set } }
46
-
47
- puts "---------------------------- BitArray methods (100,000 iterations)"
48
- bm.report("BitArray set_all_bits") { 100000.times { ba.set_all_bits} }
49
- bm.report("BitArray clear_all_bits") { 100000.times { ba.clear_all_bits } }
50
- bm.report("BitArray toggle_bit") { 100000.times { ba.toggle_bit(1) } }
51
- bm.report("BitArray toggle_all_bits") { 100000.times { ba.toggle_all_bits } }
52
- bm.report("BitArray clone") { 100000.times { ba.clone } }
53
- bm.report("BitArray slice (beg,len)") { 100000.times { ba[17, 230] } }
54
- bm.report("BitArray slice (range)") { 100000.times { ba[17..247] } }
22
+ bm.report("BitArray total_set (all)") { 10000.times { ba.total_set } }
23
+
24
+ bm.report("BitArray set_all_bits") { 10000.times { ba.set_all_bits} }
25
+ bm.report("BitArray clear_all_bits") { 10000.times { ba.clear_all_bits } }
26
+ bm.report("BitArray toggle_bit") { 10000.times { ba.toggle_bit(1) } }
27
+ bm.report("BitArray toggle_all_bits") { 10000.times { ba.toggle_all_bits } }
28
+ bm.report("BitArray clone") { 10000.times { ba.clone } }
29
+ bm.report("BitArray slice (beg,len)") { 10000.times { ba[17, 230] } }
30
+ bm.report("BitArray slice (range)") { 10000.times { ba[17..247] } }
55
31
  ba.set_all_bits
56
- bm.report("BitArray + (256, all set)") { 100000.times { ba + ba } }
32
+ bm.report("BitArray + (256, all set)") { 10000.times { ba + ba } }
57
33
  ba2 = BitArray.new(240)
58
34
  ba2.set_all_bits
59
- bm.report("BitArray + (240, all set)") { 100000.times { ba2 + ba2 } }
35
+ bm.report("BitArray + (240, all set)") { 10000.times { ba2 + ba2 } }
60
36
  }
61
37
 
@@ -33,14 +33,16 @@ class TestLibraryFileName < Test::Unit::TestCase
33
33
 
34
34
  def test_multiple_setting
35
35
  1.upto(999) do |pos|
36
- 2.times { @public_ba[pos] = 1 }
36
+ @public_ba[pos] = 1
37
+ @public_ba[pos] = 1
37
38
  assert_equal 1, @public_ba[pos]
38
39
  end
39
40
  end
40
41
 
41
42
  def test_multiple_unsetting
42
43
  1.upto(999) do |pos|
43
- 2.times { @public_ba[pos] = 0 }
44
+ @public_ba[pos] = 0
45
+ @public_ba[pos] = 0
44
46
  assert_equal 0, @public_ba[pos]
45
47
  end
46
48
  end
@@ -135,6 +137,13 @@ class TestLibraryFileName < Test::Unit::TestCase
135
137
  assert_equal "111111100000000000000000000000000000000", ba3.to_s
136
138
  end
137
139
 
140
+ def test_concatenation3
141
+ ba1 = BitArray.new(0)
142
+ ba2 = BitArray.new(0)
143
+ ba3 = ba1 + ba2
144
+ assert_equal "", ba3.to_s
145
+ end
146
+
138
147
  def test_to_a
139
148
  ba = BitArray.new(16)
140
149
  ba[1] = 1
@@ -149,6 +158,8 @@ class TestLibraryFileName < Test::Unit::TestCase
149
158
  assert_equal "00011", ba.to_s
150
159
  ba = BitArray.new("abcd0101")
151
160
  assert_equal "", ba.to_s
161
+ ba = BitArray.new("")
162
+ assert_equal "", ba.to_s
152
163
  end
153
164
 
154
165
 
@@ -159,6 +170,8 @@ class TestLibraryFileName < Test::Unit::TestCase
159
170
  assert_equal "11001", ba.to_s
160
171
  ba = BitArray.new([nil, nil, :a, nil, [:b, :c]])
161
172
  assert_equal "00101", ba.to_s
173
+ ba = BitArray.new([])
174
+ assert_equal "", ba.to_s
162
175
  end
163
176
  end
164
177
 
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.5.0
4
+ version: 0.5.1
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-06-01 00:00:00 -07:00
12
+ date: 2009-06-02 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -34,7 +34,6 @@ files:
34
34
  - examples/boolnet.rb
35
35
  - ext/bitarray.c
36
36
  - ext/extconf.rb
37
- - test/bitfield.rb
38
37
  - test/bm.rb
39
38
  - test/test.rb
40
39
  has_rdoc: true
@@ -68,7 +67,6 @@ signing_key:
68
67
  specification_version: 2
69
68
  summary: A bitarray class for Ruby, implemented as a C extension.
70
69
  test_files:
71
- - test/bitfield.rb
72
70
  - test/test.rb
73
71
  - test/bm.rb
74
72
  - examples/bloomfilter.rb
@@ -1,67 +0,0 @@
1
- # NAME: BitField
2
- # AUTHOR: Peter Cooper
3
- # LICENSE: MIT ( http://www.opensource.org/licenses/mit-license.php )
4
- # COPYRIGHT: (c) 2007 Peter Cooper (http://www.petercooper.co.uk/)
5
- # VERSION: v4
6
- # HISTORY: v4 (fixed bug where setting 0 bits to 0 caused a set to 1)
7
- # v3 (supports dynamic bitwidths for array elements.. now doing 32 bit widths default)
8
- # v2 (now uses 1 << y, rather than 2 ** y .. it's 21.8 times faster!)
9
- # v1 (first release)
10
- #
11
- # DESCRIPTION: Basic, pure Ruby bit field. Pretty fast (for what it is) and memory efficient.
12
- # I've written a pretty intensive test suite for it and it passes great.
13
- # Works well for Bloom filters (the reason I wrote it).
14
- #
15
- # Create a bit field 1000 bits wide
16
- # bf = BitField.new(1000)
17
- #
18
- # Setting and reading bits
19
- # bf[100] = 1
20
- # bf[100] .. => 1
21
- # bf[100] = 0
22
- #
23
- # More
24
- # bf.to_s = "10101000101010101" (example)
25
- # bf.total_set .. => 10 (example - 10 bits are set to "1")
26
-
27
- class BitField
28
- attr_reader :size
29
- include Enumerable
30
-
31
- ELEMENT_WIDTH = 32
32
-
33
- def initialize(size)
34
- @size = size
35
- @field = Array.new(((size - 1) / ELEMENT_WIDTH) + 1, 0)
36
- end
37
-
38
- # Set a bit (1/0)
39
- def []=(position, value)
40
- if value == 1
41
- @field[position / ELEMENT_WIDTH] |= 1 << (position % ELEMENT_WIDTH)
42
- elsif (@field[position / ELEMENT_WIDTH]) & (1 << (position % ELEMENT_WIDTH)) != 0
43
- @field[position / ELEMENT_WIDTH] ^= 1 << (position % ELEMENT_WIDTH)
44
- end
45
- end
46
-
47
- # Read a bit (1/0)
48
- def [](position)
49
- @field[position / ELEMENT_WIDTH] & 1 << (position % ELEMENT_WIDTH) > 0 ? 1 : 0
50
- end
51
-
52
- # Iterate over each bit
53
- def each(&block)
54
- @size.times { |position| yield self[position] }
55
- end
56
-
57
- # Returns the field as a string like "0101010100111100," etc.
58
- def to_s
59
- inject("") { |a, b| a + b.to_s }
60
- end
61
-
62
- # Returns the total number of bits that are set
63
- # (The technique used here is about 6 times faster than using each or inject direct on the bitfield)
64
- def total_set
65
- @field.inject(0) { |a, byte| a += byte & 1 and byte >>= 1 until byte == 0; a }
66
- end
67
- end