Skip to content

Commit

Permalink
added rarray to handle r arrays in ruby
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron Goodman committed Jan 12, 2012
1 parent e2787d8 commit e100fcc
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 9 deletions.
30 changes: 23 additions & 7 deletions ext/Converters.c
Expand Up @@ -412,8 +412,7 @@ to_ruby_vector(SEXP robj, VALUE *obj, int mode)

dim = GET_DIM(robj);
if (dim != R_NilValue) {
len = GET_LENGTH(dim);
*obj = to_ruby_array(tmp, INTEGER(dim), len);
*obj = to_ruby_array(tmp, robj);
return 1;
}

Expand Down Expand Up @@ -647,10 +646,24 @@ VALUE ltranspose(VALUE list, int *dims, int *strides,

/* Convert a R Array to a Ruby Array (in the form of
* array of arrays of ...) */
VALUE to_ruby_array(VALUE obj, int *dims, int l)
VALUE to_ruby_array(VALUE obj, SEXP robj)
{
VALUE list;
int i, c, *strides;
VALUE rarrayComponents[3]; //values, dimnames, dimnamesnames
VALUE cRArray;
VALUE rarray;
SEXP dim;
int i, c, *strides,l;
int *dims;
int status;
dim = GET_DIM(robj);
dims = INTEGER(dim);
l = GET_LENGTH(dim);
status = to_ruby_vector(GET_DIMNAMES(robj),&rarrayComponents[1],VECTOR_CONVERSION);
if (!status)
rb_raise(rb_eRuntimeError,"Could not convert dimnames\n");
status = to_ruby_vector(GET_NAMES(GET_DIMNAMES(robj)),&rarrayComponents[2],VECTOR_CONVERSION);
if (!status)
rb_raise(rb_eRuntimeError,"Could not convert dimnames names\n");

strides = (int *)ALLOC_N(int,l);
if (!strides)
Expand All @@ -662,8 +675,11 @@ VALUE to_ruby_array(VALUE obj, int *dims, int l)
c *= dims[i];
}

list = ltranspose(obj, dims, strides, 0, 0, l);
rarrayComponents[0] = ltranspose(obj, dims, strides, 0, 0, l);
free(strides);

return list;
cRArray = rb_const_get(rb_cObject,rb_intern("RArray"));
rarray = rb_class_new_instance(3,rarrayComponents,cRArray);

return rarray;
}
4 changes: 2 additions & 2 deletions ext/Converters.h
Expand Up @@ -56,10 +56,10 @@ VALUE call_proc(VALUE data);
VALUE reset_mode(VALUE mode);

VALUE to_ruby_hash(VALUE obj, SEXP names);
VALUE to_ruby_array(VALUE obj, int *dims, int l);
VALUE to_ruby_array(VALUE obj, SEXP robj);

VALUE ltranspose(VALUE list, int *dims, int *strides,
int pos, int shift, int len);
int pos, int shift, int len);

//Macros for quick checks
#define Robj_Check(v) (rb_obj_is_instance_of(v,rb_const_get(rb_cObject,rb_intern("RObj"))))
Expand Down
Binary file added ext/Converters.o
Binary file not shown.
1 change: 1 addition & 0 deletions lib/rsruby.rb
@@ -1,4 +1,5 @@
require 'rsruby/robj'
require 'rsruby/rarray'
require 'rsruby_c'
require 'singleton'

Expand Down
89 changes: 89 additions & 0 deletions lib/rsruby/rarray.rb
@@ -0,0 +1,89 @@
require 'rsruby'
class RArray
attr_reader :array
def initialize(_array,_dimnames,_dimnamesorder)
@array = _array
@dimnames = _dimnames
@dimnamesorder = _dimnamesorder
end
# def method_missing(m,*args)
# if args.length>0
# @array.send(m,args)
# else
# @array.send(m)
# end
# end
def [](index)
@array[index]
end
# trim the innermost dimension to n
# innermost dimension is outermost dimension in R
def trim(_n)
end
#we must handle either array or hash of dim names
#since we don't know what rsruby is going to give
def dimension_count
@dimnames.length
end
def subset(_keys,_dim)
all_keys = dimnames_along_dimension(_dim)
new_order = _keys.map{|x|
all_keys.index(x)
}
new_order=new_order.compact
new_array = subset_helper(@array,new_order,0,_dim)
if @dimnames.is_a? Array
new_dimnames = @dimnames.dup
new_dimnames[_dim] = _keys
RArray.new(new_array,new_dimnames,nil)
else #hash
new_dimnames = @dimnames.merge({@dimnamesorder[_dim] => _keys})
RArray.new(new_array,new_dimnames,@dimnamesorder.dup)
end
end
def subset_helper(_array,_new_order,_current_depth,_target_depth)
if _current_depth == _target_depth
_new_order.map{|x|
_array.fetch(x)
}
else
_array.map{|x|
subset_helper(x,_new_order,_current_depth+1,_target_depth)
}
end
end
def get(*_args)
indices = _args.each_with_index.map{|x,i|
d = dimnames_along_dimension(i)
j= d.index(x)
return nil unless j
j
}
a=@array
indices.each{|i|
a=a[i]
}
a
end
# def first(_n)
# new_array = @array.first(_n)
# new_dimnames = nil
# if @dimnames.is_a? Array
# new_dimnames = dimnames.dup
# new_dimnames[0] = new_dimnames[0].first(_n)
# else #hash
# new_dimnames = @dimnames.merge ({@dimnamesorder[0] => dimnames(0).first(_n)})
# end
# RArray.new(new_array,new_dimnames,@dimnamesorder)
# end


def dimnames_along_dimension(_index)
return @dimnames[_index] if @dimnames.is_a? Array
return @dimnames[@dimnamesorder[_index]] if @dimnames.is_a? Hash
raise "unsupported dimnames"
end
def dimension_names
return @dimnamesorder
end
end

0 comments on commit e100fcc

Please sign in to comment.