[Rcpp-commits] r4513 - in pkg/Rcpp: . inst/include/Rcpp/sugar/functions inst/unitTests inst/unitTests/cpp

noreply at r-forge.r-project.org noreply at r-forge.r-project.org
Wed Sep 18 17:14:05 CEST 2013


Author: romain
Date: 2013-09-18 17:14:05 +0200 (Wed, 18 Sep 2013)
New Revision: 4513

Modified:
   pkg/Rcpp/ChangeLog
   pkg/Rcpp/TODO
   pkg/Rcpp/inst/include/Rcpp/sugar/functions/diff.h
   pkg/Rcpp/inst/unitTests/cpp/sugar.cpp
   pkg/Rcpp/inst/unitTests/runit.sugar.R
Log:
one less TODO item

Modified: pkg/Rcpp/ChangeLog
===================================================================
--- pkg/Rcpp/ChangeLog	2013-09-18 14:35:49 UTC (rev 4512)
+++ pkg/Rcpp/ChangeLog	2013-09-18 15:14:05 UTC (rev 4513)
@@ -9,7 +9,12 @@
         * R/Rcpp.package.skeleton.R: Setting attributes to TRUE by default. This is
         what we should encourage people to use. 
         * include/Rcpp/as.h: add as<char> specialization
-	
+        * include/Rcpp/sugar/functions/diff.h : rework the implementation of diff
+        so that it works even when we don't know the previous value
+        * unitTests/runit.sugar.R : 
+        * unitTests/cpp/sugar.cpp :
+        * TODO : 2 less items
+        
 2013-09-17  JJ Allaire  <jj at rstudio.org>
 
 	* R/Attributes.R: Call inlineCxxPlugin and Rcpp.plugin.maker without

Modified: pkg/Rcpp/TODO
===================================================================
--- pkg/Rcpp/TODO	2013-09-18 14:35:49 UTC (rev 4512)
+++ pkg/Rcpp/TODO	2013-09-18 15:14:05 UTC (rev 4513)
@@ -42,9 +42,6 @@
 	maybe we should use LazyVector like in outer to somehow cache the
 	result when it is judged expensive to calculate
 	
-    o   The current impl of "diff" might cause problems (e.g. with
-        ifelse) due to laziness, it is probably best to not make it lazy
-
     o 	crossprod
 	
     o	Vector * Matrix, Matrix * Matrix

Modified: pkg/Rcpp/inst/include/Rcpp/sugar/functions/diff.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/sugar/functions/diff.h	2013-09-18 14:35:49 UTC (rev 4512)
+++ pkg/Rcpp/inst/include/Rcpp/sugar/functions/diff.h	2013-09-18 15:14:05 UTC (rev 4513)
@@ -1,8 +1,8 @@
-// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 4 -*-
 //
 // diff.h: Rcpp R/C++ interface class library -- diff
 //
-// Copyright (C) 2010 - 2012 Dirk Eddelbuettel and Romain Francois
+// Copyright (C) 2010 - 2013 Dirk Eddelbuettel and Romain Francois
 //
 // This file is part of Rcpp.
 //
@@ -24,42 +24,50 @@
 
 namespace Rcpp{
 namespace sugar{
-	
-	// NOTE: caching the previous value so that we only have to fetch the 
-	//       value once only works because we process the object from left to 
-	//       right
+
+// NOTE: caching the previous value so that we only have to fetch the 
+//       value once only works because we process the object from left to 
+//       right
 template <int RTYPE, bool LHS_NA, typename LHS_T>
 class Diff : public Rcpp::VectorBase< RTYPE, LHS_NA , Diff<RTYPE,LHS_NA,LHS_T> > {
 public:
 	typedef typename Rcpp::VectorBase<RTYPE,LHS_NA,LHS_T> LHS_TYPE ;
 	typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;
 	
-	Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_), previous(lhs_[0]), was_na(false) {
-		was_na = traits::is_na<RTYPE>(previous) ;
-	}
+	Diff( const LHS_TYPE& lhs_ ) : 
+	    lhs(lhs_), 
+	    previous(lhs_[0]),
+	    previous_index(0),
+	    was_na(traits::is_na<RTYPE>(previous)) 
+	{}
 	
 	inline STORAGE operator[]( int i ) const {
-		STORAGE y = lhs[i+1] ;
-		if( was_na ){
-			previous = y ;
-			was_na = traits::is_na<RTYPE>(y) ;
-			return previous ; // NA
-		}
-		if( traits::is_na<RTYPE>(y) ) {
-			was_na = true ;
-			previous = y ;
-			return previous ; // NA
-		}
-		STORAGE res = y - previous ;
-		previous = y ;
-		was_na = false ;
-		return res ;
+        STORAGE y = lhs[i+1] ;
+        if( previous_index != i ){
+            // we don't know the previous value, we need to get it. 
+            set_previous(i, lhs[i] ) ; // record the current value
+        }
+        if( was_na || traits::is_na<RTYPE>(y) ) {
+            set_previous(i+1, y ) ;
+            return traits::get_na<RTYPE>() ; // NA
+        }
+        STORAGE res = y - previous ;
+        set_previous( i+1, y) ;
+        return res ;
+	}     
+	
+	inline void set_previous(int i, STORAGE value){
+	    previous = value ;
+	    was_na = is_na<RTYPE>(previous) ;
+	    previous_index = i ;
 	}
+	
 	inline int size() const { return lhs.size() - 1 ; }
 	         
 private:
 	const LHS_TYPE& lhs ;
 	mutable STORAGE previous ;
+	mutable int previous_index ;
 	mutable bool was_na ;
 } ;
 
@@ -68,12 +76,14 @@
 public:
 	typedef typename Rcpp::VectorBase<REALSXP,LHS_NA,LHS_T> LHS_TYPE ;
 	
-	Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_), previous(lhs_[0]) {}
+	Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_), previous(lhs_[0]), previous_index(0) {}
 	
 	inline double operator[]( int i ) const {
 		double y = lhs[i+1] ;
+		if( previous_index != i ) previous = lhs[i] ;
 		double res = y - previous ;
 		previous = y ;
+		previous_index = i+1 ;
 		return res ;
 	}
 	inline int size() const { return lhs.size() - 1 ; }
@@ -81,6 +91,7 @@
 private:
 	const LHS_TYPE& lhs ;
 	mutable double previous ;
+	mutable int previous_index ;
 } ;
 
 template <int RTYPE, typename LHS_T>
@@ -89,12 +100,14 @@
 	typedef typename Rcpp::VectorBase<RTYPE,false,LHS_T> LHS_TYPE ;
 	typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;
 	
-	Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_) {}
+	Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_), previous(lhs[0]), previous_index(0) {}
 	
 	inline STORAGE operator[]( int i ) const {
 		STORAGE y = lhs[i+1] ;
+		if( previous_index != i ) previous = lhs[i] ;
 		STORAGE diff = y - previous ;
 		previous = y ;
+		previous_index = i+1 ;
 		return y - previous ;
 	}
 	inline int size() const { return lhs.size() - 1 ; }
@@ -102,6 +115,7 @@
 private:
 	const LHS_TYPE& lhs ;
 	mutable STORAGE previous ;
+	mutable int previous_index ;
 } ;
 
 } // sugar

Modified: pkg/Rcpp/inst/unitTests/cpp/sugar.cpp
===================================================================
--- pkg/Rcpp/inst/unitTests/cpp/sugar.cpp	2013-09-18 14:35:49 UTC (rev 4512)
+++ pkg/Rcpp/inst/unitTests/cpp/sugar.cpp	2013-09-18 15:14:05 UTC (rev 4513)
@@ -145,6 +145,12 @@
 }
 
 // [[Rcpp::export]]
+NumericVector runit_diff_ifelse( LogicalVector pred, NumericVector xx, NumericVector yy){
+    NumericVector res = ifelse( pred, diff(xx), diff(yy) );
+    return res ;
+}
+
+// [[Rcpp::export]]
 List runit_exp( NumericVector xx, IntegerVector yy ){
     return List::create( exp(xx), exp(yy) ) ;
 }

Modified: pkg/Rcpp/inst/unitTests/runit.sugar.R
===================================================================
--- pkg/Rcpp/inst/unitTests/runit.sugar.R	2013-09-18 14:35:49 UTC (rev 4512)
+++ pkg/Rcpp/inst/unitTests/runit.sugar.R	2013-09-18 15:14:05 UTC (rev 4513)
@@ -211,9 +211,11 @@
 }
 
 test.sugar.diff <- function( ){
-	fx <- runit_diff
-	x <- rnorm( 100 )
-	checkEquals( fx(x) , diff(x) )
+    x <- rnorm( 100 )
+    checkEquals( runit_diff(x) , diff(x) ) 
+    y    <- rnorm(100)
+    pred <- sample( c(T,F), 99, replace = TRUE )
+    checkEquals( runit_diff_ifelse(pred, x, y ), ifelse( pred, diff(x), diff(y) ) )
 }
 
 test.sugar.exp <- function( ){



More information about the Rcpp-commits mailing list