Skip to content

Commit cf77796

Browse files
one less TODO item
1 parent 619ecf2 commit cf77796

File tree

5 files changed

+57
-33
lines changed

5 files changed

+57
-33
lines changed

ChangeLog

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
* R/Rcpp.package.skeleton.R: Setting attributes to TRUE by default. This is
1010
what we should encourage people to use.
1111
* include/Rcpp/as.h: add as<char> specialization
12-
12+
* include/Rcpp/sugar/functions/diff.h : rework the implementation of diff
13+
so that it works even when we don't know the previous value
14+
* unitTests/runit.sugar.R :
15+
* unitTests/cpp/sugar.cpp :
16+
* TODO : 2 less items
17+
1318
2013-09-17 JJ Allaire <jj@rstudio.org>
1419

1520
* R/Attributes.R: Call inlineCxxPlugin and Rcpp.plugin.maker without

TODO

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ Syntactic sugar
4242
maybe we should use LazyVector like in outer to somehow cache the
4343
result when it is judged expensive to calculate
4444

45-
o The current impl of "diff" might cause problems (e.g. with
46-
ifelse) due to laziness, it is probably best to not make it lazy
47-
4845
o crossprod
4946

5047
o Vector * Matrix, Matrix * Matrix

inst/include/Rcpp/sugar/functions/diff.h

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
1+
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 4 -*-
22
//
33
// diff.h: Rcpp R/C++ interface class library -- diff
44
//
5-
// Copyright (C) 2010 - 2012 Dirk Eddelbuettel and Romain Francois
5+
// Copyright (C) 2010 - 2013 Dirk Eddelbuettel and Romain Francois
66
//
77
// This file is part of Rcpp.
88
//
@@ -24,42 +24,50 @@
2424

2525
namespace Rcpp{
2626
namespace sugar{
27-
28-
// NOTE: caching the previous value so that we only have to fetch the
29-
// value once only works because we process the object from left to
30-
// right
27+
28+
// NOTE: caching the previous value so that we only have to fetch the
29+
// value once only works because we process the object from left to
30+
// right
3131
template <int RTYPE, bool LHS_NA, typename LHS_T>
3232
class Diff : public Rcpp::VectorBase< RTYPE, LHS_NA , Diff<RTYPE,LHS_NA,LHS_T> > {
3333
public:
3434
typedef typename Rcpp::VectorBase<RTYPE,LHS_NA,LHS_T> LHS_TYPE ;
3535
typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;
3636

37-
Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_), previous(lhs_[0]), was_na(false) {
38-
was_na = traits::is_na<RTYPE>(previous) ;
39-
}
37+
Diff( const LHS_TYPE& lhs_ ) :
38+
lhs(lhs_),
39+
previous(lhs_[0]),
40+
previous_index(0),
41+
was_na(traits::is_na<RTYPE>(previous))
42+
{}
4043

4144
inline STORAGE operator[]( int i ) const {
42-
STORAGE y = lhs[i+1] ;
43-
if( was_na ){
44-
previous = y ;
45-
was_na = traits::is_na<RTYPE>(y) ;
46-
return previous ; // NA
47-
}
48-
if( traits::is_na<RTYPE>(y) ) {
49-
was_na = true ;
50-
previous = y ;
51-
return previous ; // NA
52-
}
53-
STORAGE res = y - previous ;
54-
previous = y ;
55-
was_na = false ;
56-
return res ;
45+
STORAGE y = lhs[i+1] ;
46+
if( previous_index != i ){
47+
// we don't know the previous value, we need to get it.
48+
set_previous(i, lhs[i] ) ; // record the current value
49+
}
50+
if( was_na || traits::is_na<RTYPE>(y) ) {
51+
set_previous(i+1, y ) ;
52+
return traits::get_na<RTYPE>() ; // NA
53+
}
54+
STORAGE res = y - previous ;
55+
set_previous( i+1, y) ;
56+
return res ;
57+
}
58+
59+
inline void set_previous(int i, STORAGE value){
60+
previous = value ;
61+
was_na = is_na<RTYPE>(previous) ;
62+
previous_index = i ;
5763
}
64+
5865
inline int size() const { return lhs.size() - 1 ; }
5966

6067
private:
6168
const LHS_TYPE& lhs ;
6269
mutable STORAGE previous ;
70+
mutable int previous_index ;
6371
mutable bool was_na ;
6472
} ;
6573

@@ -68,19 +76,22 @@ class Diff<REALSXP, LHS_NA, LHS_T> : public Rcpp::VectorBase< REALSXP, LHS_NA, D
6876
public:
6977
typedef typename Rcpp::VectorBase<REALSXP,LHS_NA,LHS_T> LHS_TYPE ;
7078

71-
Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_), previous(lhs_[0]) {}
79+
Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_), previous(lhs_[0]), previous_index(0) {}
7280

7381
inline double operator[]( int i ) const {
7482
double y = lhs[i+1] ;
83+
if( previous_index != i ) previous = lhs[i] ;
7584
double res = y - previous ;
7685
previous = y ;
86+
previous_index = i+1 ;
7787
return res ;
7888
}
7989
inline int size() const { return lhs.size() - 1 ; }
8090

8191
private:
8292
const LHS_TYPE& lhs ;
8393
mutable double previous ;
94+
mutable int previous_index ;
8495
} ;
8596

8697
template <int RTYPE, typename LHS_T>
@@ -89,19 +100,22 @@ class Diff<RTYPE,false,LHS_T> : public Rcpp::VectorBase< RTYPE, false , Diff<RTY
89100
typedef typename Rcpp::VectorBase<RTYPE,false,LHS_T> LHS_TYPE ;
90101
typedef typename Rcpp::traits::storage_type<RTYPE>::type STORAGE ;
91102

92-
Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_) {}
103+
Diff( const LHS_TYPE& lhs_ ) : lhs(lhs_), previous(lhs[0]), previous_index(0) {}
93104

94105
inline STORAGE operator[]( int i ) const {
95106
STORAGE y = lhs[i+1] ;
107+
if( previous_index != i ) previous = lhs[i] ;
96108
STORAGE diff = y - previous ;
97109
previous = y ;
110+
previous_index = i+1 ;
98111
return y - previous ;
99112
}
100113
inline int size() const { return lhs.size() - 1 ; }
101114

102115
private:
103116
const LHS_TYPE& lhs ;
104117
mutable STORAGE previous ;
118+
mutable int previous_index ;
105119
} ;
106120

107121
} // sugar

inst/unitTests/cpp/sugar.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,12 @@ NumericVector runit_diff( NumericVector xx){
144144
return res ;
145145
}
146146

147+
// [[Rcpp::export]]
148+
NumericVector runit_diff_ifelse( LogicalVector pred, NumericVector xx, NumericVector yy){
149+
NumericVector res = ifelse( pred, diff(xx), diff(yy) );
150+
return res ;
151+
}
152+
147153
// [[Rcpp::export]]
148154
List runit_exp( NumericVector xx, IntegerVector yy ){
149155
return List::create( exp(xx), exp(yy) ) ;

inst/unitTests/runit.sugar.R

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,11 @@ test.sugar.assignment <- function( ){
211211
}
212212

213213
test.sugar.diff <- function( ){
214-
fx <- runit_diff
215-
x <- rnorm( 100 )
216-
checkEquals( fx(x) , diff(x) )
214+
x <- rnorm( 100 )
215+
checkEquals( runit_diff(x) , diff(x) )
216+
y <- rnorm(100)
217+
pred <- sample( c(T,F), 99, replace = TRUE )
218+
checkEquals( runit_diff_ifelse(pred, x, y ), ifelse( pred, diff(x), diff(y) ) )
217219
}
218220

219221
test.sugar.exp <- function( ){

0 commit comments

Comments
 (0)