[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