[Rcpp-commits] r525 - in pkg: . inst inst/unitTests src src/Rcpp/internal

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Sun Jan 31 11:48:13 CET 2010


Author: romain
Date: 2010-01-31 11:48:13 +0100 (Sun, 31 Jan 2010)
New Revision: 525

Added:
   pkg/inst/unitTests/runit.wrap.R
Modified:
   pkg/NEWS
   pkg/inst/ChangeLog
   pkg/src/Rcpp/internal/wrap.h
   pkg/src/RcppCommon.h
Log:
map<string,T> and multimap<string,T> become wrap()'able (if T is) 

Modified: pkg/NEWS
===================================================================
--- pkg/NEWS	2010-01-31 07:28:22 UTC (rev 524)
+++ pkg/NEWS	2010-01-31 10:48:13 UTC (rev 525)
@@ -1,8 +1,12 @@
 
-0.7.5	(under development
+0.7.5	(under development)
 
     o	std::multiset<T> becomes wrap<>()'able
 
+    o	std::map<std::string,T> becomes wrap<>()'able
+
+    o	std::multimap<std::string,T> becomes wrap<>()'able
+
 0.7.4	2010-01-30
 
     o	matrix matrix-like indexing using operator() for all vector 

Modified: pkg/inst/ChangeLog
===================================================================
--- pkg/inst/ChangeLog	2010-01-31 07:28:22 UTC (rev 524)
+++ pkg/inst/ChangeLog	2010-01-31 10:48:13 UTC (rev 525)
@@ -1,7 +1,9 @@
 2010-01-31  Romain Francois <francoisromain at free.fr>
 
-	* src/Rcpp/internal/wrap.h: added support for wrap( multiset<T> )
-	where T is wrappable
+	* src/Rcpp/internal/wrap.h: more wrap for stl templates: 
+	multiset<T> where T can be wrap()'ed -> vector or list
+	map<string,T> where T can be wrap()'ed -> named vector or named list
+	multimap<string,T> where T can be wrap()'ed -> named vector or named list
 
 2010-01-30  Dirk Eddelbuettel  <edd at debian.org>
 

Added: pkg/inst/unitTests/runit.wrap.R
===================================================================
--- pkg/inst/unitTests/runit.wrap.R	                        (rev 0)
+++ pkg/inst/unitTests/runit.wrap.R	2010-01-31 10:48:13 UTC (rev 525)
@@ -0,0 +1,225 @@
+#!/usr/bin/r -t
+#
+# Copyright (C) 2010	Dirk Eddelbuettel and Romain Francois
+#
+# This file is part of Rcpp.
+#
+# Rcpp is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Rcpp is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.
+
+.setUp <- function(){
+	suppressMessages( require( inline ) )
+}
+
+test.wrap.map.string.int <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::map< std::string, int > m ;
+	m["b"] = 100;
+  	m["a"] = 200;
+  	m["c"] = 300;
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = 200L, b = 100L, c = 300L), 
+		msg = "wrap( map<string,int>) " )
+}
+
+test.wrap.map.string.double <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::map<std::string,double> m ;
+	m["b"] = 100;
+  	m["a"] = 200;
+  	m["c"] = 300;
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = 200, b = 100, c = 300), 
+		msg = "wrap( map<string,double>) " )
+}
+
+test.wrap.map.string.bool <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::map<std::string,bool> m ;
+	m["b"] = true;
+  	m["a"] = false;
+  	m["c"] = true;
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = FALSE, b = TRUE, c = TRUE ), 
+		msg = "wrap( map<string,bool>) " )
+}
+
+test.wrap.map.string.Rbyte <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::map<std::string,Rbyte> m ;
+	m["b"] = (Rbyte)0;
+  	m["a"] = (Rbyte)1;
+  	m["c"] = (Rbyte)2;
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = as.raw(1), b = as.raw(0), c = as.raw(2) ), 
+		msg = "wrap( map<string,Rbyte>) " )
+}
+
+test.wrap.map.string.string <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::map<std::string,std::string> m ;
+	m["b"] = "foo" ;
+  	m["a"] = "bar" ;
+  	m["c"] = "bling" ;
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = "bar", b = "foo", c = "bling" ), 
+		msg = "wrap( map<string,string>) " )
+}
+
+test.wrap.map.string.generic <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::map< std::string,std::vector<int> > m ;
+	std::vector<int> b ; b.push_back(1) ; b.push_back(2) ; m["b"] = b ;
+  	std::vector<int> a ; a.push_back(1) ; a.push_back(2) ; a.push_back(2) ; m["a"] = a ;
+  	std::vector<int> c ; c.push_back(1) ; c.push_back(2) ; c.push_back(2) ; c.push_back(2) ; m["c"] = c ;
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), list( a = c(1L, 2L, 2L), b = c(1L, 2L), c = c(1L,2L,2L,2L) ) , 
+		msg = "wrap( map<string,vector<int>>) " )
+}
+
+
+
+
+
+test.wrap.multimap.string.int <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::multimap< std::string, int > m ;
+	m.insert( std::pair<std::string,int>("b", 100) );
+  	m.insert( std::pair<std::string,int>("a", 200) );
+  	m.insert( std::pair<std::string,int>("c", 300) );
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = 200L, b = 100L, c = 300L), 
+		msg = "wrap( multimap<string,int>) " )
+}
+
+test.wrap.multimap.string.double <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::multimap<std::string,double> m ;
+	m.insert( std::pair<std::string,double>("b", 100) );
+  	m.insert( std::pair<std::string,double>("a", 200) );
+  	m.insert( std::pair<std::string,double>("c", 300) );
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = 200, b = 100, c = 300), 
+		msg = "wrap( multimap<string,double>) " )
+}
+
+test.wrap.multimap.string.bool <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::multimap<std::string,bool> m ;
+	m.insert( std::pair<std::string,bool>("b", true ) ) ;
+  	m.insert( std::pair<std::string,bool>("a", false) ) ;
+  	m.insert( std::pair<std::string,bool>("c", true ) ) ;
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = FALSE, b = TRUE, c = TRUE ), 
+		msg = "wrap( multimap<string,bool>) " )
+}
+
+test.wrap.multimap.string.Rbyte <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::multimap<std::string,Rbyte> m ;
+	m.insert( std::pair<std::string,Rbyte>("b", (Rbyte)0) );
+  	m.insert( std::pair<std::string,Rbyte>("a", (Rbyte)1) );
+  	m.insert( std::pair<std::string,Rbyte>("c", (Rbyte)2) );
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = as.raw(1), b = as.raw(0), c = as.raw(2) ), 
+		msg = "wrap( multimap<string,Rbyte>) " )
+}
+
+test.wrap.multimap.string.string <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	std::multimap<std::string,std::string> m ;
+	m.insert( std::pair<std::string,std::string>( "b", "foo"  ) ) ;
+  	m.insert( std::pair<std::string,std::string>( "a", "bar"  ) ) ;
+  	m.insert( std::pair<std::string,std::string>( "c", "bling") ) ;
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), c( a = "bar", b = "foo", c = "bling" ), 
+		msg = "wrap( multimap<string,string>) " )
+}
+
+test.wrap.multimap.string.generic <- function(){
+	
+	funx <- cfunction(signature(), 
+	'
+	typedef std::pair<std::string,std::vector<int> > _pair ;
+	std::multimap< std::string,std::vector<int> > m ;
+	std::vector<int> b ; b.push_back(1) ; b.push_back(2) ; 
+	m.insert( _pair("b", b) );
+  	
+	std::vector<int> a ; a.push_back(1) ; a.push_back(2) ; a.push_back(2) ; 
+  	m.insert( _pair("a", a) );
+  	
+  	std::vector<int> c ; c.push_back(1) ; c.push_back(2) ; c.push_back(2) ; c.push_back(2) ; 
+  	m.insert( _pair("c",  c) );
+  	return wrap(m) ;
+	', 
+	Rcpp=TRUE, verbose=FALSE, includes = "using namespace Rcpp;" )
+	
+	checkEquals( funx(), list( a = c(1L, 2L, 2L), b = c(1L, 2L), c = c(1L,2L,2L,2L) ) , 
+		msg = "wrap( multimap<string,vector<int>>) " )
+}
+

Modified: pkg/src/Rcpp/internal/wrap.h
===================================================================
--- pkg/src/Rcpp/internal/wrap.h	2010-01-31 07:28:22 UTC (rev 524)
+++ pkg/src/Rcpp/internal/wrap.h	2010-01-31 10:48:13 UTC (rev 525)
@@ -33,6 +33,8 @@
 
 namespace internal{
 
+// pre declaring
+template <typename InputIterator> SEXP range_wrap(InputIterator first, InputIterator last) ;
 
 // {{{ information about R vectors
 // welcome to template metaprogramming !!
@@ -92,10 +94,11 @@
 template <typename T> struct wrap_type_traits< std::set<T> > { typedef wrap_type_stl_container_tag category ; } ;
 template <typename T> struct wrap_type_traits< std::deque<T> > { typedef wrap_type_stl_container_tag category ; } ;
 template <typename T> struct wrap_type_traits< std::multiset<T> > { typedef wrap_type_stl_container_tag category ; } ;
+template <typename T> struct wrap_type_traits< std::map<std::string,T> > { typedef wrap_type_stl_container_tag category ; } ;
+template <typename T> struct wrap_type_traits< std::multimap<std::string,T> > { typedef wrap_type_stl_container_tag category ; } ;
 // #ifdef HAS_INIT_LISTS
 // template <typename T> struct wrap_type_traits< std::initializer_list<T> > { typedef wrap_type_stl_container_tag category ; } ;
 // #endif
-
 template <> struct wrap_type_traits<int> { typedef wrap_type_primitive_tag category; } ;
 template <> struct wrap_type_traits<double> { typedef wrap_type_primitive_tag category; } ;
 template <> struct wrap_type_traits<Rbyte> { typedef wrap_type_primitive_tag category; } ;
@@ -112,7 +115,24 @@
 struct r_type_generic_tag{} ;
 struct r_type_bool_tag{} ;
 
+struct r_type_pairstring_primitive_tag{} ;
+struct r_type_pairstring_string_tag{} ;
+struct r_type_pairstring_generic_tag{} ;
+struct r_type_pairstring_bool_tag{} ;
+
 template <typename T> struct r_type_traits { typedef r_type_generic_tag category ; } ;
+
+// special cases pair<string,T> to deal with map<string,T> etc ...
+template <typename T> struct r_type_traits< std::pair<const std::string,T> > { typedef r_type_pairstring_generic_tag category ; } ;
+template<> struct r_type_traits< std::pair<const std::string,int> >{ typedef r_type_pairstring_primitive_tag category ; } ;
+template<> struct r_type_traits< std::pair<const std::string,size_t> >{ typedef r_type_pairstring_primitive_tag category ; } ;
+template<> struct r_type_traits< std::pair<const std::string,double> >{ typedef r_type_pairstring_primitive_tag category ; } ;
+template<> struct r_type_traits< std::pair<const std::string,Rbyte> >{ typedef r_type_pairstring_primitive_tag category ; } ;
+template<> struct r_type_traits< std::pair<const std::string,Rcomplex> >{ typedef r_type_pairstring_primitive_tag category ; } ;
+template<> struct r_type_traits< std::pair<const std::string,bool> >{ typedef r_type_pairstring_bool_tag category ; } ;
+template<> struct r_type_traits< std::pair<const std::string,std::string> >{ typedef r_type_pairstring_string_tag category ; } ;
+template<> struct r_type_traits< std::pair<const std::string,char> >{ typedef r_type_pairstring_string_tag category ; } ;
+
 template<> struct r_type_traits<int>{ typedef r_type_primitive_tag category ; } ;
 template<> struct r_type_traits<size_t>{ typedef r_type_primitive_tag category ; } ;
 template<> struct r_type_traits<double>{ typedef r_type_primitive_tag category ; } ;
@@ -124,6 +144,7 @@
 // }}}
 
 // {{{ range wrap 
+// {{{ unnamed range wrap
 template <typename InputIterator, typename T>
 SEXP range_wrap_dispatch___impl( InputIterator first, InputIterator last, r_type_primitive_tag){ 
 	size_t size = std::distance( first, last ) ;
@@ -144,7 +165,7 @@
 } ;
 
 
-// this implementation is used when T is not a primitive type
+// this implementation is used when T is not a primitive type.
 // T needs to be wrappable though
 template <typename InputIterator, typename T>
 SEXP range_wrap_dispatch___impl( InputIterator first, InputIterator last, r_type_generic_tag ){ 
@@ -180,7 +201,95 @@
 SEXP range_wrap_dispatch( InputIterator first, InputIterator last ){
 	return range_wrap_dispatch___impl<InputIterator,T>( first, last, typename r_type_traits<T>::category() ) ;
 }
+// }}}
 
+// {{{ named range wrap
+// we get into these when iterating over a pair<const string,T> 
+// which is what e.g. map<string,T> produces
+template <typename InputIterator, typename T>
+SEXP range_wrap_dispatch___impl( InputIterator first, InputIterator last, r_type_pairstring_primitive_tag){ 
+	size_t size = std::distance( first, last ) ;
+	const int RTYPE = r_sexptype<typename T::second_type>::rtype ;
+	SEXP x = PROTECT( Rf_allocVector( RTYPE, size ) );
+	SEXP names = PROTECT( Rf_allocVector( STRSXP, size ) ) ;
+	typename storage_type<RTYPE>::type* start = r_vector_start<RTYPE, typename storage_type<RTYPE>::type >(x) ;
+	size_t i =0;
+	std::string buf ; 
+	for( ; i<size; i++, ++first){
+		start[i] = (*first).second ;
+		buf = (*first).first ;
+		SET_STRING_ELT( names, i, Rf_mkChar(buf.c_str()) ) ;
+	}
+	::Rf_setAttrib( x, R_NamesSymbol, names ) ;
+	UNPROTECT(2) ; /* x, names */
+	return x ;
+} ;
+
+template <typename InputIterator, typename T>
+SEXP range_wrap_dispatch___impl( InputIterator first, InputIterator last, r_type_pairstring_bool_tag){ 
+	size_t size = std::distance( first, last ) ;
+	SEXP x = PROTECT( Rf_allocVector( LGLSXP, size ) );
+	SEXP names = PROTECT( Rf_allocVector( STRSXP, size ) ) ;
+	size_t i =0;
+	std::string buf ;
+	int* start = LOGICAL(x) ;
+	for( ; i<size; i++, ++first){
+		start[i] = bool_to_Rboolean( (*first).second );
+		buf = (*first).first ;
+		SET_STRING_ELT( names, i, Rf_mkChar(buf.c_str()) ) ;
+	}
+	::Rf_setAttrib( x, R_NamesSymbol, names ) ;
+	UNPROTECT(2) ; /* x, names */
+	return x ;
+} ;
+
+
+// this implementation is used when T is not a primitive type.
+// T needs to be wrappable though
+template <typename InputIterator, typename T>
+SEXP range_wrap_dispatch___impl( InputIterator first, InputIterator last, r_type_pairstring_generic_tag ){ 
+	size_t size = std::distance( first, last ) ;
+	SEXP x = PROTECT( Rf_allocVector( VECSXP, size ) );
+	SEXP names = PROTECT( Rf_allocVector( STRSXP, size ) ) ;
+	size_t i =0 ;
+	std::string buf ;
+	SEXP element = R_NilValue ;
+	while( i < size ){
+		element = ::Rcpp::wrap( first->second ) ;
+		buf = first->first ;
+		SET_VECTOR_ELT( x, i, element ) ;
+		SET_STRING_ELT( names, i, Rf_mkChar(buf.c_str()) ) ; 
+		i++ ;
+		++first ;
+	}
+	::Rf_setAttrib( x, R_NamesSymbol, names ) ;
+	UNPROTECT(2) ; /* x, names */
+	return x ;
+} ;
+
+template<typename InputIterator, typename T>
+SEXP range_wrap_dispatch___impl( InputIterator first, InputIterator last, r_type_pairstring_string_tag ){
+	size_t size = std::distance( first, last ) ;
+	SEXP x = PROTECT( Rf_allocVector( STRSXP, size ) ) ;
+	SEXP names = PROTECT( Rf_allocVector( STRSXP, size ) ) ;
+	size_t i = 0 ;
+	std::string buffer ;
+	while( i < size ){
+		buffer = first->second ;
+		SET_STRING_ELT( x, i, Rf_mkChar( buffer.c_str()) ) ;
+		
+		buffer = first->first ;
+		SET_STRING_ELT( names, i, Rf_mkChar( buffer.c_str()) ) ;
+		
+		i++ ;
+		++first ;
+	}
+	::Rf_setAttrib( x, R_NamesSymbol, names ) ;
+	UNPROTECT(2) ; /* x, names */
+	return x ;
+}
+// }}}
+
 // we use the iterator trait to make the dispatch
 template <typename InputIterator>
 SEXP range_wrap(InputIterator first, InputIterator last){
@@ -232,9 +341,11 @@
 template <typename T> SEXP wrap_dispatch( const T& object, wrap_type_stl_container_tag ){
 	return range_wrap( object.begin(), object.end() ) ;
 }
+// wrapping a primitive type : int, double, std::string
 template <typename T> SEXP wrap_dispatch( const T& object, wrap_type_primitive_tag ){
 	return primitive_wrap( object ) ;
 }
+// when we don't know how to deal with it, we try implicit conversion
 template <typename T> SEXP wrap_dispatch( const T& object, wrap_type_unknown_tag ){
 	SEXP x = object ;
 	return x ;

Modified: pkg/src/RcppCommon.h
===================================================================
--- pkg/src/RcppCommon.h	2010-01-31 07:28:22 UTC (rev 524)
+++ pkg/src/RcppCommon.h	2010-01-31 10:48:13 UTC (rev 525)
@@ -46,7 +46,6 @@
 #include <stdexcept>
 #include <vector>
 #include <deque>
-#include <multiset>
 #include <functional>
 #include <numeric>
 #include <algorithm>



More information about the Rcpp-commits mailing list