[Rcpp-commits] r2469 - in pkg/Rcpp: . R inst/include/Rcpp inst/include/Rcpp/vector src

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Sat Nov 20 13:34:23 CET 2010


Author: romain
Date: 2010-11-20 13:34:22 +0100 (Sat, 20 Nov 2010)
New Revision: 2469

Modified:
   pkg/Rcpp/ChangeLog
   pkg/Rcpp/NAMESPACE
   pkg/Rcpp/R/00_classes.R
   pkg/Rcpp/R/Module.R
   pkg/Rcpp/inst/include/Rcpp/Module.h
   pkg/Rcpp/inst/include/Rcpp/routines.h
   pkg/Rcpp/inst/include/Rcpp/vector/MatrixRow.h
   pkg/Rcpp/src/Module.cpp
   pkg/Rcpp/src/Rcpp_init.c
Log:
optimization in method dispatch related to void-ness of methods

Modified: pkg/Rcpp/ChangeLog
===================================================================
--- pkg/Rcpp/ChangeLog	2010-11-20 11:47:09 UTC (rev 2468)
+++ pkg/Rcpp/ChangeLog	2010-11-20 12:34:22 UTC (rev 2469)
@@ -1,3 +1,19 @@
+2010-11-20  Romain Francois <romain at r-enthusiasts.com>
+
+    * inst/include/Rcpp/vector/MatrixRow.h: added missing return *this ;
+
+    * R/Module.R: dispatch based on void-ness of the methods. For example if all
+    methods are known to be void, etc ...
+    
+    * R/00_classes.R: more information in the C++OverloadedMethods ref class
+    
+    * src/Module.cpp: new .External CppMethod__invoke_void and 
+    CppMethod__invoke_notvoid that are used when we know for sure that all 
+    overloaded methods are void, or not void
+    
+    * inst/include/Rcpp/Module.h: class_ gains invoke_void and invoke_notvoid 
+    to support the changes above
+    
 2010-11-18  Douglas Bates  <bates at stat.wisc.edu>
 
 	* inst/include/Rcpp/module/Module_generated_[class_]Constructor.h:

Modified: pkg/Rcpp/NAMESPACE
===================================================================
--- pkg/Rcpp/NAMESPACE	2010-11-20 11:47:09 UTC (rev 2468)
+++ pkg/Rcpp/NAMESPACE	2010-11-20 12:34:22 UTC (rev 2469)
@@ -18,7 +18,8 @@
     rcpp_set_stack_trace, rcpp_get_stack_trace,
     
     # .External functions
-    CppMethod__invoke, InternalFunction_invoke, Module__invoke, class__newInstance
+    CppMethod__invoke, CppMethod__invoke_void, CppMethod__invoke_notvoid, 
+    InternalFunction_invoke, Module__invoke, class__newInstance
 )
 
 import( methods )

Modified: pkg/Rcpp/R/00_classes.R
===================================================================
--- pkg/Rcpp/R/00_classes.R	2010-11-20 11:47:09 UTC (rev 2468)
+++ pkg/Rcpp/R/00_classes.R	2010-11-20 12:34:22 UTC (rev 2469)
@@ -36,7 +36,9 @@
 setRefClass( "C++OverloadedMethods", 
     fields = list( 
         pointer       = "externalptr", 
-        class_pointer = "externalptr"
+        class_pointer = "externalptr", 
+        size          = "integer", 
+        void          = "logical"
     )
 )
 

Modified: pkg/Rcpp/R/Module.R
===================================================================
--- pkg/Rcpp/R/Module.R	2010-11-20 11:47:09 UTC (rev 2468)
+++ pkg/Rcpp/R/Module.R	2010-11-20 12:34:22 UTC (rev 2469)
@@ -203,21 +203,41 @@
 dealWith <- function( x ) if(isTRUE(x[[1]])) invisible(NULL) else x[[2]]
 
 method_wrapper <- function( METHOD, where ){
-            f <- function(...) NULL
-	    extCall <- substitute(
-	    {
-           dealWith( .External(CppMethod__invoke, class_pointer, pointer, .pointer, ...) )
+        f <- function(...) NULL
+        
+        stuff <- list(
+            class_pointer = METHOD$class_pointer,
+            pointer = METHOD$pointer,
+            CppMethod__invoke = CppMethod__invoke,
+            CppMethod__invoke_void = CppMethod__invoke_void,
+            CppMethod__invoke_notvoid = CppMethod__invoke_notvoid,
+            dealWith = dealWith
+        )
+        
+        extCall <- if( all( METHOD$void ) ){
+            # all methods are void, so we know we want to return invisible(NULL)
+            substitute( 
+            {
+                .External(CppMethod__invoke_void, class_pointer, pointer, .pointer, ...)
+                invisible(NULL)
+            } , stuff )
+        } else if( all( ! METHOD$void ) ){
+            # none of the methods are void so we always return the result of 
+            # .External
+            substitute( 
+            {
+               .External(CppMethod__invoke_notvoid, class_pointer, pointer, .pointer, ...)
+            } , stuff )
+        } else {
+            # some are void, some are not, so the voidness is part of the result 
+            # we get from internally and we need to deal with it
+            substitute( 
+	        {
+               dealWith( .External(CppMethod__invoke, class_pointer, pointer, .pointer, ...) )
+            } , stuff )
         }
-           ,
-            list(
-                class_pointer = METHOD$class_pointer,
-                pointer = METHOD$pointer,
-                CppMethod__invoke = CppMethod__invoke, 
-                dealWith = dealWith
-                 )
-            )
-            body(f, where) <- extCall
-            f
+        body(f, where) <- extCall
+        f
 	}
 ## create a named list of the R methods to invoke C++ methods
 ## from the C++ class with pointer xp

Modified: pkg/Rcpp/inst/include/Rcpp/Module.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/Module.h	2010-11-20 11:47:09 UTC (rev 2468)
+++ pkg/Rcpp/inst/include/Rcpp/Module.h	2010-11-20 12:34:22 UTC (rev 2469)
@@ -71,7 +71,15 @@
 	virtual SEXP invoke( SEXP, SEXP, SEXP *, int ){ 
 		return R_NilValue ;
 	}
+	virtual SEXP invoke_void( SEXP, SEXP, SEXP *, int ){ 
+		return R_NilValue ;
+	}
+	virtual SEXP invoke_notvoid( SEXP, SEXP, SEXP *, int ){ 
+		return R_NilValue ;
+	}
 	
+	
+	
 	virtual Rcpp::CharacterVector method_names(){ return Rcpp::CharacterVector(0) ; }
 	virtual Rcpp::CharacterVector property_names(){ return Rcpp::CharacterVector(0) ; }
 	virtual bool property_is_readonly(const std::string& ) throw(std::range_error) { return false ; }
@@ -206,8 +214,16 @@
 	typedef std::vector<signed_method_class*> vec_signed_method ;
 	
 	S4_CppOverloadedMethods( vec_signed_method* m, SEXP class_xp ) : Reference( "C++OverloadedMethods" ){
-        field( "pointer" )       = Rcpp::XPtr< vec_signed_method >( m, false ) ;
+        
+	    int n = m->size() ;
+        Rcpp::LogicalVector voidness( n) ;
+        for( int i=0; i<n; i++){ voidness[i] = m->at(i)->is_void() ; }
+        
+	    field( "pointer" )       = Rcpp::XPtr< vec_signed_method >( m, false ) ;
         field( "class_pointer" ) = class_xp ;
+        field( "size" )          = n ;
+        field( "void" )          = voidness ;
+        
     }
 } ;
 
@@ -354,6 +370,51 @@
 		END_RCPP	
 	}
 	
+	SEXP invoke_void( SEXP method_xp, SEXP object, SEXP *args, int nargs ){ 
+		BEGIN_RCPP
+		
+		vec_signed_method* mets = reinterpret_cast< vec_signed_method* >( EXTPTR_PTR( method_xp ) ) ;
+		typename vec_signed_method::iterator it = mets->begin() ;
+		int n = mets->size() ;
+		method_class* m = 0 ;
+		bool ok = false ; 
+		for( int i=0; i<n; i++, ++it ){
+		    if( ( (*it)->valid )( args, nargs) ){
+		        m = (*it)->method ;
+		        ok = true ; 
+		        break ;
+		    }
+		}
+		if( !ok ){
+		    throw std::range_error( "could not find valid method" ) ; 	
+		}
+		m->operator()( XP(object), args ); 
+		END_RCPP	
+	}
+	
+	SEXP invoke_notvoid( SEXP method_xp, SEXP object, SEXP *args, int nargs ){ 
+		BEGIN_RCPP
+		
+		vec_signed_method* mets = reinterpret_cast< vec_signed_method* >( EXTPTR_PTR( method_xp ) ) ;
+		typename vec_signed_method::iterator it = mets->begin() ;
+		int n = mets->size() ;
+		method_class* m = 0 ;
+		bool ok = false ; 
+		for( int i=0; i<n; i++, ++it ){
+		    if( ( (*it)->valid )( args, nargs) ){
+		        m = (*it)->method ;
+		        ok = true ; 
+		        break ;
+		    }
+		}
+		if( !ok ){
+		    throw std::range_error( "could not find valid method" ) ; 	
+		}
+		return m->operator()( XP(object), args ) ;
+		END_RCPP	
+	}
+	
+	
 	self& AddMethod( const char* name_, method_class* m, ValidMethod valid = &yes ){
 		typename map_vec_signed_method::iterator it = singleton->vec_methods.find( name_ ) ; 
 	    if( it == singleton->vec_methods.end() ){

Modified: pkg/Rcpp/inst/include/Rcpp/routines.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/routines.h	2010-11-20 11:47:09 UTC (rev 2468)
+++ pkg/Rcpp/inst/include/Rcpp/routines.h	2010-11-20 12:34:22 UTC (rev 2469)
@@ -67,6 +67,8 @@
 
 /* .External functions */
 EXTFUN(CppMethod__invoke) ;
+EXTFUN(CppMethod__invoke_void) ;
+EXTFUN(CppMethod__invoke_notvoid) ;
 EXTFUN(InternalFunction_invoke) ;
 EXTFUN(Module__invoke) ;
 EXTFUN(class__newInstance) ;

Modified: pkg/Rcpp/inst/include/Rcpp/vector/MatrixRow.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/vector/MatrixRow.h	2010-11-20 11:47:09 UTC (rev 2468)
+++ pkg/Rcpp/inst/include/Rcpp/vector/MatrixRow.h	2010-11-20 12:34:22 UTC (rev 2469)
@@ -132,6 +132,7 @@
           default:                                   
               {}                         
         }
+        return *this ;
 	}
 
 	reference operator[]( int i ){

Modified: pkg/Rcpp/src/Module.cpp
===================================================================
--- pkg/Rcpp/src/Module.cpp	2010-11-20 11:47:09 UTC (rev 2468)
+++ pkg/Rcpp/src/Module.cpp	2010-11-20 12:34:22 UTC (rev 2469)
@@ -176,6 +176,55 @@
    	return clazz->invoke( met, obj, cargs, nargs ) ;
 }
 
+extern "C" SEXP CppMethod__invoke_void(SEXP args){
+	SEXP p = CDR(args) ;
+	
+	// the external pointer to the class
+	XP_Class clazz( CAR(p) ) ; p = CDR(p);
+	
+	// the external pointer to the method
+	SEXP met = CAR(p) ; p = CDR(p) ;
+	
+	// the external pointer to the object
+	SEXP obj = CAR(p); p = CDR(p) ;
+	
+	// additional arguments, processed the same way as .Call does
+	SEXP cargs[MAX_ARGS] ;
+    int nargs = 0 ;
+   	for(; nargs<MAX_ARGS; nargs++){
+   		if( p == R_NilValue ) break ;
+   		cargs[nargs] = CAR(p) ;
+   		p = CDR(p) ;
+   	}
+   	clazz->invoke_void( met, obj, cargs, nargs ) ;
+   	return R_NilValue ;
+}
+
+extern "C" SEXP CppMethod__invoke_notvoid(SEXP args){
+	SEXP p = CDR(args) ;
+	
+	// the external pointer to the class
+	XP_Class clazz( CAR(p) ) ; p = CDR(p);
+	
+	// the external pointer to the method
+	SEXP met = CAR(p) ; p = CDR(p) ;
+	
+	// the external pointer to the object
+	SEXP obj = CAR(p); p = CDR(p) ;
+	
+	// additional arguments, processed the same way as .Call does
+	SEXP cargs[MAX_ARGS] ;
+    int nargs = 0 ;
+   	for(; nargs<MAX_ARGS; nargs++){
+   		if( p == R_NilValue ) break ;
+   		cargs[nargs] = CAR(p) ;
+   		p = CDR(p) ;
+   	}
+   	
+   	return clazz->invoke_notvoid( met, obj, cargs, nargs ) ;
+}
+
+
 namespace Rcpp{
 	static Module* current_scope  ;
 }

Modified: pkg/Rcpp/src/Rcpp_init.c
===================================================================
--- pkg/Rcpp/src/Rcpp_init.c	2010-11-20 11:47:09 UTC (rev 2468)
+++ pkg/Rcpp/src/Rcpp_init.c	2010-11-20 12:34:22 UTC (rev 2469)
@@ -69,6 +69,8 @@
 
 static R_ExternalMethodDef extEntries[]  = {
     EXTDEF(CppMethod__invoke),
+    EXTDEF(CppMethod__invoke_void),
+    EXTDEF(CppMethod__invoke_notvoid),
     EXTDEF(InternalFunction_invoke),
     EXTDEF(Module__invoke), 
     EXTDEF(class__newInstance), 



More information about the Rcpp-commits mailing list