Skip to content

Commit e100fcc

Browse files
author
Aaron Goodman
committed
added rarray to handle r arrays in ruby
1 parent e2787d8 commit e100fcc

File tree

5 files changed

+115
-9
lines changed

5 files changed

+115
-9
lines changed

ext/Converters.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,7 @@ to_ruby_vector(SEXP robj, VALUE *obj, int mode)
412412

413413
dim = GET_DIM(robj);
414414
if (dim != R_NilValue) {
415-
len = GET_LENGTH(dim);
416-
*obj = to_ruby_array(tmp, INTEGER(dim), len);
415+
*obj = to_ruby_array(tmp, robj);
417416
return 1;
418417
}
419418

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

648647
/* Convert a R Array to a Ruby Array (in the form of
649648
* array of arrays of ...) */
650-
VALUE to_ruby_array(VALUE obj, int *dims, int l)
649+
VALUE to_ruby_array(VALUE obj, SEXP robj)
651650
{
652-
VALUE list;
653-
int i, c, *strides;
651+
VALUE rarrayComponents[3]; //values, dimnames, dimnamesnames
652+
VALUE cRArray;
653+
VALUE rarray;
654+
SEXP dim;
655+
int i, c, *strides,l;
656+
int *dims;
657+
int status;
658+
dim = GET_DIM(robj);
659+
dims = INTEGER(dim);
660+
l = GET_LENGTH(dim);
661+
status = to_ruby_vector(GET_DIMNAMES(robj),&rarrayComponents[1],VECTOR_CONVERSION);
662+
if (!status)
663+
rb_raise(rb_eRuntimeError,"Could not convert dimnames\n");
664+
status = to_ruby_vector(GET_NAMES(GET_DIMNAMES(robj)),&rarrayComponents[2],VECTOR_CONVERSION);
665+
if (!status)
666+
rb_raise(rb_eRuntimeError,"Could not convert dimnames names\n");
654667

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

665-
list = ltranspose(obj, dims, strides, 0, 0, l);
678+
rarrayComponents[0] = ltranspose(obj, dims, strides, 0, 0, l);
666679
free(strides);
667680

668-
return list;
681+
cRArray = rb_const_get(rb_cObject,rb_intern("RArray"));
682+
rarray = rb_class_new_instance(3,rarrayComponents,cRArray);
683+
684+
return rarray;
669685
}

ext/Converters.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ VALUE call_proc(VALUE data);
5656
VALUE reset_mode(VALUE mode);
5757

5858
VALUE to_ruby_hash(VALUE obj, SEXP names);
59-
VALUE to_ruby_array(VALUE obj, int *dims, int l);
59+
VALUE to_ruby_array(VALUE obj, SEXP robj);
6060

6161
VALUE ltranspose(VALUE list, int *dims, int *strides,
62-
int pos, int shift, int len);
62+
int pos, int shift, int len);
6363

6464
//Macros for quick checks
6565
#define Robj_Check(v) (rb_obj_is_instance_of(v,rb_const_get(rb_cObject,rb_intern("RObj"))))

ext/Converters.o

60.8 KB
Binary file not shown.

lib/rsruby.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'rsruby/robj'
2+
require 'rsruby/rarray'
23
require 'rsruby_c'
34
require 'singleton'
45

lib/rsruby/rarray.rb

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
require 'rsruby'
2+
class RArray
3+
attr_reader :array
4+
def initialize(_array,_dimnames,_dimnamesorder)
5+
@array = _array
6+
@dimnames = _dimnames
7+
@dimnamesorder = _dimnamesorder
8+
end
9+
# def method_missing(m,*args)
10+
# if args.length>0
11+
# @array.send(m,args)
12+
# else
13+
# @array.send(m)
14+
# end
15+
# end
16+
def [](index)
17+
@array[index]
18+
end
19+
# trim the innermost dimension to n
20+
# innermost dimension is outermost dimension in R
21+
def trim(_n)
22+
end
23+
#we must handle either array or hash of dim names
24+
#since we don't know what rsruby is going to give
25+
def dimension_count
26+
@dimnames.length
27+
end
28+
def subset(_keys,_dim)
29+
all_keys = dimnames_along_dimension(_dim)
30+
new_order = _keys.map{|x|
31+
all_keys.index(x)
32+
}
33+
new_order=new_order.compact
34+
new_array = subset_helper(@array,new_order,0,_dim)
35+
if @dimnames.is_a? Array
36+
new_dimnames = @dimnames.dup
37+
new_dimnames[_dim] = _keys
38+
RArray.new(new_array,new_dimnames,nil)
39+
else #hash
40+
new_dimnames = @dimnames.merge({@dimnamesorder[_dim] => _keys})
41+
RArray.new(new_array,new_dimnames,@dimnamesorder.dup)
42+
end
43+
end
44+
def subset_helper(_array,_new_order,_current_depth,_target_depth)
45+
if _current_depth == _target_depth
46+
_new_order.map{|x|
47+
_array.fetch(x)
48+
}
49+
else
50+
_array.map{|x|
51+
subset_helper(x,_new_order,_current_depth+1,_target_depth)
52+
}
53+
end
54+
end
55+
def get(*_args)
56+
indices = _args.each_with_index.map{|x,i|
57+
d = dimnames_along_dimension(i)
58+
j= d.index(x)
59+
return nil unless j
60+
j
61+
}
62+
a=@array
63+
indices.each{|i|
64+
a=a[i]
65+
}
66+
a
67+
end
68+
# def first(_n)
69+
# new_array = @array.first(_n)
70+
# new_dimnames = nil
71+
# if @dimnames.is_a? Array
72+
# new_dimnames = dimnames.dup
73+
# new_dimnames[0] = new_dimnames[0].first(_n)
74+
# else #hash
75+
# new_dimnames = @dimnames.merge ({@dimnamesorder[0] => dimnames(0).first(_n)})
76+
# end
77+
# RArray.new(new_array,new_dimnames,@dimnamesorder)
78+
# end
79+
80+
81+
def dimnames_along_dimension(_index)
82+
return @dimnames[_index] if @dimnames.is_a? Array
83+
return @dimnames[@dimnamesorder[_index]] if @dimnames.is_a? Hash
84+
raise "unsupported dimnames"
85+
end
86+
def dimension_names
87+
return @dimnamesorder
88+
end
89+
end

0 commit comments

Comments
 (0)