[Rcpp-commits] r652 - in pkg: inst/unitTests src src/Rcpp
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Tue Feb 9 19:10:23 CET 2010
Author: romain
Date: 2010-02-09 19:10:22 +0100 (Tue, 09 Feb 2010)
New Revision: 652
Added:
pkg/src/SEXP_Vector.cpp
Modified:
pkg/inst/unitTests/runit.GenericVector.R
pkg/src/Rcpp/SEXP_Vector.h
Log:
+ GenericVector::iterator, and a C++ version of lapply, using std::transform
Modified: pkg/inst/unitTests/runit.GenericVector.R
===================================================================
--- pkg/inst/unitTests/runit.GenericVector.R 2010-02-09 17:31:29 UTC (rev 651)
+++ pkg/inst/unitTests/runit.GenericVector.R 2010-02-09 18:10:22 UTC (rev 652)
@@ -120,4 +120,24 @@
msg = "List( Dimension(2,3,4))" )
}
+test.List.iterator <- function(){
+
+ cpp_lapply <- cfunction(signature(x = "list", g = "function" ), '
+ Function fun(g) ;
+ List input(x) ;
+ List output( input.size() ) ;
+ std::transform( input.begin(), input.end(), output.begin(), fun ) ;
+ output.names() = input.names() ;
+ return output ;
+
+ ', Rcpp = TRUE, includes = "using namespace Rcpp;" )
+
+ data <- list( x = letters, y = LETTERS, z = 1:4 )
+ checkEquals(
+ cpp_lapply( data, length ),
+ list( x = 26L, y = 26L, z = 4L),
+ msg = "c++ version of lapply" )
+
+
+}
Modified: pkg/src/Rcpp/SEXP_Vector.h
===================================================================
--- pkg/src/Rcpp/SEXP_Vector.h 2010-02-09 17:31:29 UTC (rev 651)
+++ pkg/src/Rcpp/SEXP_Vector.h 2010-02-09 18:10:22 UTC (rev 652)
@@ -29,114 +29,157 @@
namespace Rcpp{
-template <int RTYPE>
-class SEXP_Vector : public VectorBase {
+class SEXP_Vector_Base : public VectorBase {
public:
- /* much inspired from item 30 of more effective C++ */
+ class iterator ;
+
class Proxy {
public:
- Proxy( SEXP_Vector& v, size_t i ) : parent(v), index(i) {}
+ Proxy( SEXP_Vector_Base& v, size_t i ) ;
- /* lvalue uses */
- Proxy& operator=(const Proxy& rhs){
- SET_VECTOR_ELT( parent, index, VECTOR_ELT( rhs.parent, rhs.index) ) ;
- return *this ;
- }
+ Proxy& operator=(SEXP rhs) ;
- Proxy& operator=(SEXP rhs){
- SET_VECTOR_ELT( parent, index, rhs ) ;
- return *this ;
- }
+ Proxy& operator=(const Proxy& rhs) ;
template <typename T>
Proxy& operator=( const T& rhs){
- SET_VECTOR_ELT( parent, index, wrap(rhs) ) ;
+ set( wrap(rhs) ) ;
return *this;
}
+ inline operator SEXP() const { return get() ; }
template <typename U> operator U(){
- SEXP xx = VECTOR_ELT( parent, index) ;
- return as<U>( xx ) ;
+ return as<U>( get() ) ;
}
+ void swap(Proxy& other) ;
+ friend class iterator ;
private:
- SEXP_Vector& parent;
+ SEXP_Vector_Base& parent;
size_t index ;
+ void move(int n) ;
+ void set(SEXP x) ;
+ SEXP get() const ;
} ;
- SEXP_Vector(): VectorBase(){}
+ class iterator {
+ public:
+ typedef Proxy& reference ;
+ typedef Proxy* pointer ;
+ typedef int difference_type ;
+ typedef Proxy value_type;
+ typedef std::random_access_iterator_tag iterator_category ;
+
+ iterator( SEXP_Vector_Base& object, int index );
+
+ inline iterator& operator++(){ proxy.move(1) ; return *this; }
+ inline iterator& operator++(int){ proxy.move(1) ; return *this; }
+
+ inline iterator& operator--() { proxy.move(-1) ; return *this; }
+ inline iterator& operator--(int) { proxy.move(-1) ; return *this; }
+
+ inline iterator operator+(difference_type n) const { return iterator( proxy.parent, proxy.index + n ) ; }
+ inline iterator operator-(difference_type n) const { return iterator( proxy.parent, proxy.index - n ) ; }
+
+ inline iterator& operator+=(difference_type n) { proxy.move(n) ; return *this; }
+ inline iterator& operator-=(difference_type n) { proxy.move(-n) ; return *this; }
+
+ inline reference operator*() { return proxy ; }
+ inline pointer operator->(){ return &proxy ; }
+
+ inline bool operator==( const iterator& y) { return this->proxy.index == y.proxy.index && this->proxy.parent == y.proxy.parent; }
+ inline bool operator!=( const iterator& y) { return this->proxy.index != y.proxy.index || this->proxy.parent != y.proxy.parent; }
+ inline bool operator< ( const iterator& y) { return this->proxy.index < y.proxy.index ; }
+ inline bool operator> ( const iterator& y) { return this->proxy.index > y.proxy.index ; }
+ inline bool operator<=( const iterator& y) { return this->proxy.index <= y.proxy.index ; }
+ inline bool operator>=( const iterator& y) { return this->proxy.index >= y.proxy.index ; }
+
+ inline difference_type operator-(const iterator& y) { return this->proxy.index - y.proxy.index ; }
+
+ private:
+ Proxy proxy ;
+ };
- SEXP_Vector(const SEXP_Vector& other) : VectorBase(other.asSexp()) {} ;
+ SEXP_Vector_Base() ;
+ const Proxy operator[]( int i ) const throw(index_out_of_bounds){
+ return Proxy(const_cast<SEXP_Vector_Base&>(*this), offset(i)) ;
+ }
+ Proxy operator[]( int i ) throw(index_out_of_bounds){
+ return Proxy(*this, offset(i) ) ;
+ }
+
+ inline iterator begin() { return iterator(*this, 0) ; }
+ inline iterator end() { return iterator(*this, size() ) ; }
+
+ Proxy operator()( const size_t& i) throw(index_out_of_bounds){
+ return Proxy(*this, offset(i) ) ;
+ }
+ Proxy operator()( const size_t& i, const size_t& j) throw(index_out_of_bounds,not_a_matrix){
+ return Proxy(*this, offset(i,j) ) ;
+ }
+
+ friend class Proxy;
+ friend class iterator ;
+
+} ;
+
+template <int RTYPE>
+class SEXP_Vector : public SEXP_Vector_Base{
+public:
+ SEXP_Vector() : SEXP_Vector_Base(){} ;
+
+ SEXP_Vector(const SEXP_Vector& other) : SEXP_Vector_Base(){
+ setSEXP( other.asSexp() ) ;
+ } ;
+
SEXP_Vector& operator=(const SEXP_Vector& other){
setSEXP( other.asSexp() ) ;
return *this ;
}
- SEXP_Vector(SEXP x) : VectorBase() {
+ SEXP_Vector(SEXP x) : SEXP_Vector_Base() {
SEXP y = r_cast<RTYPE>(x) ;
setSEXP( y );
}
- SEXP_Vector(const size_t& size) : VectorBase(){
+ SEXP_Vector(const size_t& size) : SEXP_Vector_Base(){
setSEXP( Rf_allocVector( RTYPE, size ) ) ;
}
- SEXP_Vector(const Dimension& dims) : VectorBase(){
+ SEXP_Vector(const Dimension& dims) : SEXP_Vector_Base(){
setSEXP( Rf_allocVector( RTYPE, dims.prod() ) ) ;
if( dims.size() > 1) attr( "dim" ) = dims ;
}
template <typename InputIterator>
- SEXP_Vector(InputIterator first, InputIterator last) : VectorBase() {
+ SEXP_Vector(InputIterator first, InputIterator last) : SEXP_Vector_Base() {
assign( first, last ) ;
}
#ifdef HAS_INIT_LISTS
- SEXP_Vector( std::initializer_list<SEXP> list) : VectorBase(){
+ SEXP_Vector( std::initializer_list<SEXP> list) : SEXP_Vector_Base(){
assign( list.begin(), list.end() ) ;
} ;
#endif
- const Proxy operator[]( int i ) const throw(index_out_of_bounds){
- return Proxy(const_cast<SEXP_Vector<RTYPE>&>(*this), offset(i)) ;
- }
- Proxy operator[]( int i ) throw(index_out_of_bounds){
- return Proxy(*this, offset(i) ) ;
- }
-
-
- Proxy operator()( const size_t& i) throw(index_out_of_bounds){
- return Proxy(*this, offset(i) ) ;
- }
- Proxy operator()( const size_t& i, const size_t& j) throw(index_out_of_bounds,not_a_matrix){
- return Proxy(*this, offset(i,j) ) ;
- }
-
- friend class Proxy;
-
template <typename InputIterator>
void assign( InputIterator first, InputIterator last){
- size_t size = std::distance( first, last );
- SEXP x = PROTECT( Rf_allocVector( RTYPE, size ) ) ;
- SEXP y = R_NilValue ; /* -Wall */
- for( size_t i=0; i<size ; i++, ++first){
- /* this is where the actual type of InputIterator matters */
- y = *first ; /* as long as *first can implicitely convert to SEXP, we're good to go */
- SET_VECTOR_ELT( x, i, y ) ;
- }
- setSEXP( x ) ;
- UNPROTECT( 1 ); /* x */
+ setSEXP( r_cast<RTYPE>( wrap( first, last) ) ) ;
}
+
-} ;
+} ;
typedef SEXP_Vector<VECSXP> GenericVector ;
typedef GenericVector List ;
-
} //namespace Rcpp
+namespace std {
+ template<> void swap( Rcpp::SEXP_Vector_Base::Proxy& a, Rcpp::SEXP_Vector_Base::Proxy& b) ;
+}
+
#endif
Added: pkg/src/SEXP_Vector.cpp
===================================================================
--- pkg/src/SEXP_Vector.cpp (rev 0)
+++ pkg/src/SEXP_Vector.cpp 2010-02-09 18:10:22 UTC (rev 652)
@@ -0,0 +1,76 @@
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
+//
+// Symbol.cpp: Rcpp R/C++ interface class library -- Symbols
+//
+// 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/>.
+
+#include <Rcpp/SEXP_Vector.h>
+
+namespace Rcpp{
+
+/* proxy */
+
+SEXP_Vector_Base::Proxy::Proxy(SEXP_Vector_Base& v, size_t i):
+ parent(v), index(i) {};
+
+void SEXP_Vector_Base::Proxy::set(SEXP x){
+ SET_VECTOR_ELT( parent, index, x ) ;
+}
+
+SEXP SEXP_Vector_Base::Proxy::get() const {
+ return VECTOR_ELT(parent, index );
+}
+
+SEXP_Vector_Base::Proxy& SEXP_Vector_Base::Proxy::operator=(SEXP rhs){
+ set(rhs);
+ return *this ;
+}
+
+SEXP_Vector_Base::Proxy& SEXP_Vector_Base::Proxy::operator=(const Proxy& rhs){
+ set(rhs.get());
+ return *this ;
+}
+
+void SEXP_Vector_Base::Proxy::swap(Proxy& other){
+ SEXP tmp = PROTECT( get() ) ;
+ set( other.get() ) ;
+ other.set( tmp ) ;
+ UNPROTECT(1) ;
+}
+
+void SEXP_Vector_Base::Proxy::move(int n){
+ index += n ;
+}
+
+/* iterator */
+
+SEXP_Vector_Base::iterator::iterator( SEXP_Vector_Base& object, int index_):
+ proxy(object,index_){}
+
+/* SEXP_Vector_Base */
+SEXP_Vector_Base::SEXP_Vector_Base() : VectorBase(){}
+
+
+} // namespace Rcpp
+
+namespace std{
+template<> void swap( Rcpp::SEXP_Vector_Base::Proxy& a, Rcpp::SEXP_Vector_Base::Proxy& b){
+ a.swap(b) ;
+}
+}
+
More information about the Rcpp-commits
mailing list