[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