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//
2424
2525namespace Rcpp {
2626namespace 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
3131template <int RTYPE, bool LHS_NA, typename LHS_T>
3232class Diff : public Rcpp ::VectorBase< RTYPE, LHS_NA , Diff<RTYPE,LHS_NA,LHS_T> > {
3333public:
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
6067private:
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
6876public:
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
8191private:
8292 const LHS_TYPE& lhs ;
8393 mutable double previous ;
94+ mutable int previous_index ;
8495} ;
8596
8697template <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
102115private:
103116 const LHS_TYPE& lhs ;
104117 mutable STORAGE previous ;
118+ mutable int previous_index ;
105119} ;
106120
107121} // sugar
0 commit comments