Permalink
Browse files

Merge branch 'master' of https://github.com/aaronjg/rsruby into aaron…

…jg-master

Merging significant modernisations.
  • Loading branch information...
alexgutteridge committed Jan 24, 2017
2 parents 6a51ee7 + 3538223 commit e0ba4dcd864d210cfaa60146a956b1244f1471fa
Showing with 211 additions and 44 deletions.
  1. +37 −13 ext/Converters.c
  2. +3 −2 ext/Converters.h
  3. BIN ext/Converters.o
  4. +1 −1 ext/extconf.rb
  5. +12 −14 ext/rsruby.c
  6. +4 −6 ext/rsruby.h
  7. +23 −5 lib/rsruby.rb
  8. +89 −0 lib/rsruby/rarray.rb
  9. +2 −2 rsruby.gemspec
  10. +35 −0 test/tc_mem.rb
  11. +4 −1 test/tc_robj.rb
  12. +1 −0 test/test_memory_usage.rb
View
@@ -36,6 +36,14 @@
// ************** Converters from Ruby to R *********//
VALUE ruby_to_Robj(VALUE self, VALUE args){
SEXP robj;
VALUE val;
robj = ruby_to_R(args);
val = to_ruby_with_mode(robj,NO_CONVERSION);
return val;
}
SEXP ruby_to_R(VALUE obj)
{
SEXP robj;
@@ -352,11 +360,11 @@ to_ruby_vector(SEXP robj, VALUE *obj, int mode)
if(isFactor(robj)) {
/* Watch for NA's! */
if(integers[i]==NA_INTEGER)
it = rb_str_new2(CHAR(NA_STRING));
it = rb_external_str_new_cstr(CHAR(NA_STRING));
else
{
thislevel = CHAR(STRING_ELT(GET_LEVELS(robj), integers[i]-1));
if (!(it = rb_str_new2(thislevel)))
if (!(it = rb_external_str_new_cstr(thislevel)))
return -1;
}
}
@@ -380,11 +388,11 @@ to_ruby_vector(SEXP robj, VALUE *obj, int mode)
break;
case STRSXP:
if(STRING_ELT(robj, i)==R_NaString)
it = rb_str_new2(CHAR(NA_STRING));
it = rb_external_str_new_cstr(CHAR(NA_STRING));
else
{
strings = CHAR(STRING_ELT(robj, i));
if (!(it = rb_str_new2(strings)))
if (!(it = rb_external_str_new_cstr(strings)))
return -1;
}
break;
@@ -404,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;
}
@@ -545,7 +552,7 @@ VALUE from_class_table(SEXP robj)
for (i=0; i<GET_LENGTH(rclass); i++){
fun = rb_hash_aref(class_table,
rb_str_new2(CHAR(STRING_ELT(rclass, i))));
rb_external_str_new_cstr(CHAR(STRING_ELT(rclass, i))));
if (fun != Qnil){
break;
}
@@ -601,7 +608,7 @@ VALUE to_ruby_hash(VALUE obj, SEXP names)
for (i=0; i<len; i++) {
it = rb_ary_entry(obj, i);
name = CHAR(STRING_ELT(names, i));
rb_hash_aset(hash, rb_str_new2(name), it);
rb_hash_aset(hash, rb_external_str_new_cstr(name), it);
}
return hash;
@@ -639,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)
@@ -654,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;
}
View
@@ -36,6 +36,7 @@
//Converters for Ruby to R
SEXP ruby_to_R(VALUE val);
VALUE ruby_to_Robj(VALUE self,VALUE args);
SEXP array_to_R(VALUE obj);
SEXP hash_to_R(VALUE obj);
@@ -55,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"))))
View
BIN +60.8 KB ext/Converters.o
Binary file not shown.
View
@@ -18,7 +18,7 @@
exit 1
end
some_include_paths = some_paths.map{|dir| File.join(dir, 'include') } + %w[/usr/include/R]
some_include_paths = some_paths.map{|dir| File.join(dir, 'include') } + %w[/usr/include/R] + %w[/usr/share/R/include]
find_header('R.h', nil, *some_include_paths)
unless have_header("R.h")
View
@@ -37,8 +37,7 @@
/* This is inspired in $R_SRC/src/main/memory.c */
static SEXP R_References;
void protect_robj(SEXP robj){
R_References = CONS(robj, R_References);
SET_SYMVALUE(install("R.References"), R_References);
R_PreserveObject(robj);
}
SEXP
@@ -55,16 +54,10 @@ RecursiveRelease(SEXP obj, SEXP list)
/* TODO: This needs implementing as a Ruby destructor for each RObj */
void
Robj_dealloc(VALUE self)
Robj_dealloc(SEXP robj)
{
SEXP robj;
Data_Get_Struct(self, struct SEXPREC, robj);
R_References = RecursiveRelease(robj, R_References);
SET_SYMVALUE(install("R.References"), R_References);
return;
R_ReleaseObject(robj);
}
@@ -124,7 +117,7 @@ VALUE rs_shutdown(VALUE self){
*/
VALUE rr_init(VALUE self){
init_R(0,NULL);
// Initialize the list of protected objects
R_References = R_NilValue;
@@ -144,7 +137,11 @@ void init_R(int argc, char **argv){
if (RSRUBY_R_HOME) {
setenv("R_HOME", RSRUBY_R_HOME, 0);
}
Rf_initEmbeddedR(sizeof(defaultArgv) / sizeof(defaultArgv[0]), defaultArgv);
// Rf_initEmbeddedR(sizeof(defaultArgv) / sizeof(defaultArgv[0]), defaultArgv);
Rf_initialize_R(sizeof(defaultArgv) / sizeof(defaultArgv[0]), defaultArgv);
R_Interactive = TRUE;
R_CStackLimit = (uintptr_t)-1; //disable stack limit checking
setup_Rmainloop();
R_Interactive = FALSE; //Remove crash menu (and other interactive R features)
}
@@ -170,13 +167,14 @@ void Init_rsruby_c(){
rb_define_method(cRRuby, "shutdown", rs_shutdown, 0);
rb_define_method(cRRuby, "crash", crash, 0);
rb_define_method(cRRuby, "to_R", ruby_to_Robj, 1);
//Add the lcall method to RObj
cRObj = rb_const_get(rb_cObject,rb_intern("RObj"));
rb_define_method(cRObj, "lcall", RObj_lcall, 1);
rb_define_method(cRObj, "__init_lcall__", RObj_init_lcall, 1);
rb_define_method(cRObj, "to_ruby", RObj_to_ruby, -2);
rb_define_method(cRObj, "to_R", ruby_to_R, 1);
}
View
@@ -31,14 +31,14 @@
#ifndef R_RUBY_MAIN
#define R_RUBY_MAIN
#define CSTACK_DEFNS
#include "ruby.h"
#include "R.h"
#include "Rdefines.h"
#include "Rinternals.h"
#include "Rdefines.h"
#include "Rinterface.h"
#include "Rembedded.h"
#include "signal.h"
#include "R_eval.h"
@@ -58,8 +58,6 @@
/* Missing definitions from Rinterface.h or RStartup.h */
# define CleanEd Rf_CleanEd
extern int Rf_initEmbeddedR(int argc, char **argv);
extern int R_Interactive;
extern void CleanEd(void);
extern int R_CollectWarnings;
# define PrintWarnings Rf_PrintWarnings
@@ -84,6 +82,6 @@ VALUE RObj_init_lcall(VALUE self, VALUE args);
VALUE RObj_to_ruby(VALUE self, VALUE args);
int make_argl(VALUE args, SEXP *e);
void protect_robj(SEXP robj);
void Robj_dealloc(VALUE self);
void Robj_dealloc(SEXP robj);
#endif
View
@@ -1,4 +1,5 @@
require 'rsruby/robj'
require 'rsruby/rarray'
require 'rsruby_c'
require 'singleton'
@@ -133,8 +134,7 @@ def method_missing(r_id,*args)
#Translate Ruby method call to R
robj_name = RSRuby.convert_method_name(r_id.to_s)
#Retrieve it
robj = self.__getitem__(robj_name)
robj = robj_name =~ /(.+)::(.+)/ ? self.send('::',$1,$2) : self.__getitem__(robj_name)
#TODO perhaps this is not neccessary - always call these methods
#use the [] syntax for variables etc...
@@ -181,9 +181,9 @@ def RSRuby.convert_method_name(name)
if name.length > 1 and name[-1].chr == '_' and name[-2].chr != '_'
name = name[0..-2]
end
name.gsub!(/__/,'<-')
name.gsub!(/_/, '.')
return name
newname = name.gsub(/__/,'<-')
newname = name.gsub(/_/, '.')
return newname
end
#Converts an Array of function arguments into lcall format. If the last
@@ -299,4 +299,22 @@ def __getitem__(name,init=false)
end
class RException < RuntimeError
def initialize(_msg)
e = RSRuby.get_default_mode
RSRuby.set_default_mode(RSRuby::VECTOR_CONVERSION )
if RSRuby.instance.exists('traceback.character')[0]
@r_traceback = RSRuby.instance.traceback_character('max.lines'=>10)
else
r_full_traceback = RSRuby.instance.get(".Traceback")
r_shortened_traceback = r_full_traceback.map{|x| x.first(10)}
@r_traceback = r_shortened_traceback.flatten
end
RSRuby.set_default_mode(e)
super
end
def backtrace
x = super
return x if x.nil?
@r_traceback +x
end
end
View
@@ -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_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|
x.nil? ? nil : _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)
return nil unless d
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
Oops, something went wrong.

0 comments on commit e0ba4dc

Please sign in to comment.