[Rcpp-commits] r4441 - in pkg/Rcpp: . inst inst/include/Rcpp/api/meat inst/include/Rcpp/internal inst/include/Rcpp/traits inst/unitTests inst/unitTests/cpp

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Thu Aug 22 11:07:21 CEST 2013


Author: romain
Date: 2013-08-22 11:07:21 +0200 (Thu, 22 Aug 2013)
New Revision: 4441

Added:
   pkg/Rcpp/inst/include/Rcpp/api/meat/wrap.h
   pkg/Rcpp/inst/include/Rcpp/traits/is_primitive.h
Modified:
   pkg/Rcpp/ChangeLog
   pkg/Rcpp/inst/NEWS.Rd
   pkg/Rcpp/inst/include/Rcpp/api/meat/meat.h
   pkg/Rcpp/inst/include/Rcpp/internal/wrap.h
   pkg/Rcpp/inst/include/Rcpp/traits/r_type_traits.h
   pkg/Rcpp/inst/include/Rcpp/traits/traits.h
   pkg/Rcpp/inst/unitTests/cpp/wrap.cpp
   pkg/Rcpp/inst/unitTests/runit.wrap.R
Log:
more wrap, e.g. std::map<int, double>, boost::unordered_map<double, std::vector<double> >, ...

Modified: pkg/Rcpp/ChangeLog
===================================================================
--- pkg/Rcpp/ChangeLog	2013-08-22 07:33:37 UTC (rev 4440)
+++ pkg/Rcpp/ChangeLog	2013-08-22 09:07:21 UTC (rev 4441)
@@ -1,5 +1,16 @@
 2013-08-22 Romain Francois <romain at r-enthusiasts.com>
 
+        * include/Rcpp/traits/is_primitive.h : new trait to identify if a type is 
+        primitive, this is a shortcut of using r_type_traits and compare it
+        to r_type_primitive_tag
+        * include/Rcpp/traits/r_type_traits.h : new tag r_type_pair_tag to handle
+        wrapping map<KEY, VALUE> where KEY can be converted to String and VALUE 
+        can wrap itself
+        * include/Rcpp/internal/wrap.h : handling r_type_pair_tag
+        * include/Rcpp/api/meat/wrap.h : implementations to handle map<KEY, VALUE>
+        * unitTests/cpp/wrap.cpp : more tests for map<KEY, VALUE> with KEY not a string
+        * unitTests/runit.wrap.R : more tests for map<KEY, VALUE> with KEY not a string
+        
         * include/Rcpp/internal/export.h : added export_range__dispatch for the 
         r_type_generic_tag tag. Meaning we can now use as< vector<T> > where 
         T is not a primitive

Modified: pkg/Rcpp/inst/NEWS.Rd
===================================================================
--- pkg/Rcpp/inst/NEWS.Rd	2013-08-22 07:33:37 UTC (rev 4440)
+++ pkg/Rcpp/inst/NEWS.Rd	2013-08-22 09:07:21 UTC (rev 4441)
@@ -19,6 +19,18 @@
       can be seen as a \code{T}. For example \code{is<DataFrame>(x)}. 
       This is a building block for more expressive dispatch in various places
       (modules and attributes functions). 
+      \item \code{wrap} can now handle more types, i.e. types that iterate over 
+      \code{std::pair<const KEY, VALUE>} where KEY can be converted to a 
+      \code{String} and \code{VALUE} is either a primitive type (int, double)
+      or a type that wraps. Examples :
+      \itemize{
+          \item \code{std::map<int, double>} : we can make a String from an int, 
+          and double is primitive
+          \item \code{boost::unordered_map<double, std::vector<double> >}: we can make
+          a String from a double and \code{std::vector<double>} can wrap itself
+      }
+      Other examples of this are included at the end of the \code{wrap} unit test
+      file (\code{runit.wrap.R} and \code{wrap.cpp}) . 
     }
 
     \item Changes in Attributes:

Modified: pkg/Rcpp/inst/include/Rcpp/api/meat/meat.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/api/meat/meat.h	2013-08-22 07:33:37 UTC (rev 4440)
+++ pkg/Rcpp/inst/include/Rcpp/api/meat/meat.h	2013-08-22 09:07:21 UTC (rev 4441)
@@ -1,8 +1,8 @@
 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
 //
-// backward.h: Rcpp R/C++ interface class library -- 
+// meat.h: Rcpp R/C++ interface class library -- 
 //
-// Copyright (C) 2012    Dirk Eddelbuettel and Romain Francois
+// Copyright (C) 2012 - 2013    Dirk Eddelbuettel and Romain Francois
 //
 // This file is part of Rcpp.
 //
@@ -30,5 +30,6 @@
 #include <Rcpp/api/meat/Reference.h>
 #include <Rcpp/api/meat/is.h>
 #include <Rcpp/api/meat/export.h>
+#include <Rcpp/api/meat/wrap.h>
 
 #endif

Added: pkg/Rcpp/inst/include/Rcpp/api/meat/wrap.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/api/meat/wrap.h	                        (rev 0)
+++ pkg/Rcpp/inst/include/Rcpp/api/meat/wrap.h	2013-08-22 09:07:21 UTC (rev 4441)
@@ -0,0 +1,68 @@
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
+//
+// wrap.h: Rcpp R/C++ interface class library -- wrap implementations 
+//
+// Copyright (C) 2013    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/>.
+
+#ifndef Rcpp_api_meat_wrap_h
+#define Rcpp_api_meat_wrap_h
+
+namespace Rcpp{ 
+namespace internal{
+        
+template <typename InputIterator, typename KEY, typename VALUE, int RTYPE>
+inline SEXP range_wrap_dispatch___impl__pair( InputIterator first, InputIterator last, Rcpp::traits::true_type ){
+	size_t size = std::distance( first, last ) ;
+	typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;
+	
+	SEXP names = PROTECT( Rf_allocVector(STRSXP, size) ) ;
+	SEXP x = PROTECT( Rf_allocVector(RTYPE, size) ) ;
+	STORAGE* ptr = Rcpp::internal::r_vector_start<RTYPE>( x ) ;
+	Rcpp::String buffer ;
+	for( size_t i = 0; i < size ; i++, ++first){
+        buffer = first->first ;
+        ptr[i] = first->second ;
+        SET_STRING_ELT( names, i, buffer.get_sexp() ) ;
+	}
+	::Rf_setAttrib( x, R_NamesSymbol, names) ;
+	UNPROTECT(2) ;
+	return x ;
+}
+                
+template <typename InputIterator, typename KEY, typename VALUE, int RTYPE>
+inline SEXP range_wrap_dispatch___impl__pair( InputIterator first, InputIterator last, Rcpp::traits::false_type ){
+	size_t size = std::distance( first, last ) ;
+	
+	SEXP names = PROTECT( Rf_allocVector(STRSXP, size) ) ;
+	SEXP x = PROTECT( Rf_allocVector(VECSXP, size) ) ;
+	Rcpp::String buffer ;
+	for( size_t i = 0; i < size ; i++, ++first){
+        buffer = first->first ;
+        SET_VECTOR_ELT( x, i, Rcpp::wrap(first->second) );
+        SET_STRING_ELT( names, i, buffer.get_sexp() ) ;
+	}
+	::Rf_setAttrib( x, R_NamesSymbol, names) ;
+	UNPROTECT(2) ;
+	return x ;
+}
+  
+
+} // namespace internal
+} // namespace Rcpp
+
+#endif

Modified: pkg/Rcpp/inst/include/Rcpp/internal/wrap.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/internal/wrap.h	2013-08-22 07:33:37 UTC (rev 4440)
+++ pkg/Rcpp/inst/include/Rcpp/internal/wrap.h	2013-08-22 09:07:21 UTC (rev 4441)
@@ -351,6 +351,40 @@
 	return x ;
 
 }
+
+/** 
+ * iterating over pair<const int, VALUE>
+ * where VALUE is some primitive type
+ */
+template <typename InputIterator, typename KEY, typename VALUE, int RTYPE>
+inline SEXP range_wrap_dispatch___impl__pair( InputIterator first, InputIterator last, Rcpp::traits::true_type ) ;
+
+/** 
+ * iterating over pair<const int, VALUE>
+ * where VALUE is a type that needs wrapping
+ */
+template <typename InputIterator, typename KEY, typename VALUE, int RTYPE>
+inline SEXP range_wrap_dispatch___impl__pair( InputIterator first, InputIterator last, Rcpp::traits::false_type ) ;
+
+
+/**
+ * Range wrap dispatch for iterators over std::pair<const int, T>
+ */
+template<typename InputIterator, typename T>
+inline SEXP range_wrap_dispatch___impl( InputIterator first, InputIterator last, ::Rcpp::traits::r_type_pair_tag ){
+	typedef typename T::second_type VALUE ;
+	typedef typename T::first_type KEY ;
+	
+	return range_wrap_dispatch___impl__pair<
+			InputIterator,
+			KEY, 
+			VALUE, 
+			Rcpp::traits::r_sexptype_traits<VALUE>::rtype
+		>( first, last, 
+		typename Rcpp::traits::is_primitive<VALUE>::type()
+		) ;
+}
+
 // }}}
 
 /**

Added: pkg/Rcpp/inst/include/Rcpp/traits/is_primitive.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/traits/is_primitive.h	                        (rev 0)
+++ pkg/Rcpp/inst/include/Rcpp/traits/is_primitive.h	2013-08-22 09:07:21 UTC (rev 4441)
@@ -0,0 +1,37 @@
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
+/* :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1: */
+//
+// is_primitive.h: Rcpp R/C++ interface class library -- traits to help wrap
+//
+// Copyright (C) 2013 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/>.
+
+#ifndef Rcpp__traits__is_primitive__h
+#define Rcpp__traits__is_primitive__h
+
+namespace Rcpp{
+namespace traits{
+
+	template <typename T> struct is_primitive : public same_type<
+		typename r_type_traits<T>::r_category , 
+		r_type_primitive_tag
+	>{} ;
+	
+} // traits
+} // Rcpp
+
+#endif

Modified: pkg/Rcpp/inst/include/Rcpp/traits/r_type_traits.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/traits/r_type_traits.h	2013-08-22 07:33:37 UTC (rev 4440)
+++ pkg/Rcpp/inst/include/Rcpp/traits/r_type_traits.h	2013-08-22 09:07:21 UTC (rev 4441)
@@ -61,6 +61,12 @@
 struct r_type_pairstring_generic_tag{} ;
 
 /**
+ * Identifies a pair<const KEY, VALUE>, used to wrap map<KEY, VALUE>
+ * VALUE can be anything that wraps, KEY can be anything we can build a String from
+ */
+struct r_type_pair_tag{} ;
+
+/**
  * identifies a module object pointer
  */ 
 struct r_type_module_object_pointer_tag{} ;
@@ -103,6 +109,12 @@
  */
 template <typename T> struct r_type_traits< Rcpp::object<T> >{ typedef r_type_module_object_pointer_tag r_category ; } ;
 
+
+template <typename KEY, typename VALUE> 
+struct r_type_traits< std::pair<const KEY,VALUE> > { 
+	typedef r_type_pair_tag r_category ; 
+} ;
+
 /** 
  * special cases pair<string,T> to deal with map<string,T> etc ...
  */

Modified: pkg/Rcpp/inst/include/Rcpp/traits/traits.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/traits/traits.h	2013-08-22 07:33:37 UTC (rev 4440)
+++ pkg/Rcpp/inst/include/Rcpp/traits/traits.h	2013-08-22 09:07:21 UTC (rev 4441)
@@ -60,6 +60,7 @@
 #include <Rcpp/traits/remove_const_and_reference.h>
 #include <Rcpp/traits/result_of.h>
 #include <Rcpp/traits/is_module_object.h>
+#include <Rcpp/traits/is_primitive.h>
 
 #endif
 

Modified: pkg/Rcpp/inst/unitTests/cpp/wrap.cpp
===================================================================
--- pkg/Rcpp/inst/unitTests/cpp/wrap.cpp	2013-08-22 07:33:37 UTC (rev 4440)
+++ pkg/Rcpp/inst/unitTests/cpp/wrap.cpp	2013-08-22 09:07:21 UTC (rev 4441)
@@ -196,3 +196,57 @@
     return wrap(m);
 }
 
+
+RCPP_EXPOSED_CLASS(Foo)
+class Foo{
+    public: 
+        Foo() : x(0.0){}
+        Foo( double x_ ) : x(x_){}
+        double get() { return x ; }
+   private:
+       double x ;
+} ;
+RCPP_MODULE(mod){
+    class_<Foo>("Foo")
+        .constructor<double>()
+        .method( "get", &Foo::get )
+    ;
+}
+
+// [[Rcpp::export]]
+SEXP map_int_double(){
+    std::map<int, double> map ;
+    map[0] = 2.0 ;
+    map[-1] = 3.0 ;
+    return wrap( map ) ;
+}
+ 
+// [[Rcpp::export]]
+SEXP map_double_double(){
+    std::map<double, double> map ;
+    map[0.0] = 2.0 ;
+    map[1.2] = 3.0 ;
+    return wrap( map ) ;
+}
+
+// [[Rcpp::export]]
+SEXP map_int_vector_double(){
+    std::map<int, std::vector<double> > map ;
+    map[0].push_back( 1.0 ) ;
+    map[0].push_back( 2.0 ) ;
+    
+    map[1].push_back( 2.0 ) ;
+    map[1].push_back( 3.0 ) ;
+    
+    return wrap( map ) ;
+}
+
+// [[Rcpp::export]]
+SEXP map_int_Foo(){
+    std::map<int, Foo> map ;
+    map[0] = Foo( 2 ) ;
+    map[1] = Foo( 3 ) ;
+    return wrap( map ) ;
+}
+
+

Modified: pkg/Rcpp/inst/unitTests/runit.wrap.R
===================================================================
--- pkg/Rcpp/inst/unitTests/runit.wrap.R	2013-08-22 07:33:37 UTC (rev 4440)
+++ pkg/Rcpp/inst/unitTests/runit.wrap.R	2013-08-22 09:07:21 UTC (rev 4441)
@@ -149,5 +149,37 @@
     checkEquals( res[["c"]], c(1L,2L,2L,2L) ,  msg = "wrap( tr1::unordered_map<string,vector<int>>) " )
 }
 
+test.wrap.map.int.double <- function(){
+    checkEquals( 
+        map_int_double(), 
+        c("-1" = 3, "0" = 2 ), 
+        msg = "std::map<int,double>"
+    )    
 }
 
+test.wrap.map.double.double <- function(){
+    checkEquals( 
+        map_double_double(), 
+        c("0" = 2, "1.2" = 3 ), 
+        msg = "std::map<double,double>"
+    )    
+}
+
+test.wrap.map.int.vector_double <- function(){
+    checkEquals( 
+        map_int_vector_double(), 
+        list("0" = c(1,2), "1" = c(2,3) ), 
+        msg = "std::map<double, std::vector<double> >"
+    )    
+}
+
+test.wrap.map.int.Foo <- function(){
+    checkEquals( 
+        sapply( map_int_Foo(), function(.) .$get() ), 
+        c("0" = 2, "1" = 3 ), 
+        msg = "std::map<int, MODULE EXPOSED CLASS >"
+    )    
+}
+
+}
+



More information about the Rcpp-commits mailing list