[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