Fredrik said:
ts said:
Well, in ruby
[snip solution in ruby]
I had to interface with a C-library that took, among other things, an
array of bitmaps as input. Otherwise, I would have done it in Ruby, of
course.
I assumed it was mainly for experimentation until you said that.
Your example showed the first mutable Fixnum object that I've seen
and you must have wondered why a simple task was so tough to get
right in an extension.
Have a look at the same thing implemented (for amusement only) as an
extension to the Integer class (Fixnum/Bignum's parent). Notice how
the input array is created from a sequence of parameters in both the
Ruby and C versions, so you call with (1,2,3) instead of ([1,2,3]).
(Method Bitmask#add_bits is defined with "-1" arguments.)
Method Bitmask#add_bit in Ruby is now:
bitmask | 1 << bit
not:
bitmask |= 1 << bit
which means that you would need bitmask = bitmask.add_bit(...) when
accumulating single results. Apart from this "new" problem, you
should find that things look simpler (e.g. no Bitmask.new).
As for the solution, Tim was correct in that rb_iterate wasn't what I
neded. The for loop solved the problem I had.
OK, I saw that, but you may be tempted to try another approach.
A similar loop to Tim's is still there.
It's a kind of "Hello bit-World" extension if anyone needs one
Thanks everyone,
//Fredrik
and thank you,
:daz
-------8<------ Bitmask.c
#include "ruby.h"
static ID id_lshift, id_or;
static VALUE
add_bit(VALUE obj, VALUE bit) /* OK with Fixnum or Bignum */
{
VALUE bit_or = rb_funcall(INT2FIX(1), id_lshift, 1, bit);
return rb_funcall(obj, id_or, 1, bit_or);
}
static VALUE
bm_add_bit(VALUE self, VALUE bit)
{
return add_bit(self, bit);
}
static VALUE
bm_add_bits(int argc, VALUE *argv, VALUE self)
{
VALUE arr_bits, result = self;
int x;
rb_scan_args(argc, argv, "0*", &arr_bits);
for (x = 0; x < RARRAY(arr_bits)->len; x++)
result = add_bit(result, RARRAY(arr_bits)->ptr[x]);
return result;
}
void Init_Bitmask() {
rb_define_method(rb_cInteger, "add_bit", bm_add_bit, 1);
rb_define_method(rb_cInteger, "add_bits", bm_add_bits, -1);
id_lshift = rb_intern("<<");
id_or = rb_intern("|");
}
/* E N D */
/***
###----- extconf.rb
require 'mkmf'
create_makefile('Bitmask')
# - to build ...
# make
# - then ...
# make install
###----- test_Bitmask.rb
require 'Bitmask'
class Integer
def add_rubits(*args) ### Ruby add_bits
res = self
args.each {|bx| res = res.add_bit(bx)}
res
end
end
show = lambda{ |res| puts 'value: 0x%03x [%08b]' % [res, res] }
bm = 0
show[ bm = bm.add_bit(2) ]
show[ bm = bm.add_bit(4) ]
puts '------------'
show[ 0.add_bits(2, 4) ]
puts '------------'
MSK1 = 0b11110011
bm = MSK1; show[ bm.add_bits( 31, 33) ]
bm = MSK1; show[ bm.add_rubits(31, 33) ] # Ruby
bit_arr = [31, 33]
bm = MSK1; show[ bm.add_bits(*bit_arr) ]
puts '------------'
MSK2 = 2**41
bm = MSK2; show[ bm.add_bits( 19, 3, 9, 17, 6, 18) ]
bm = MSK2; show[ bm.add_rubits(19, 3, 9, 17, 6, 18) ] # Ruby
***/