Skip to content

Commit 82516b9

Browse files
committed
Merge branch 'feature/pr342-at-accessors'
2 parents cf02f45 + 62018cc commit 82516b9

File tree

7 files changed

+61
-11
lines changed

7 files changed

+61
-11
lines changed

ChangeLog

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
2015-08-19 Florian Plaza Oñate <[email protected]>
2+
* inst/include/Rcpp/vector/Vector.h: Add 'at' methods which implement
3+
accessors with bounds cheking (pull request #342, fixes issue #341)
4+
* inst/include/Rcpp/vector/Matrix.h: Ditto
5+
* inst/unitTests/cpp/Vector.cpp: Add unit tests for at acessors
6+
* inst/unitTests/cpp/Matrix.cpp: Ditto
7+
* inst/unitTests/runit.Vector.R: Ditto
8+
* inst/unitTests/runit.Matrix.R: Ditto
9+
110
2015-08-18 Dirk Eddelbuettel <[email protected]>
211

312
* inst/unitTests/runit.Module.client.package.R: Disabled for bad

inst/include/Rcpp/vector/Matrix.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ class Matrix : public Vector<RTYPE, StoragePolicy>, public MatrixBase<RTYPE, tru
135135
return static_cast< const Vector<RTYPE>* >( this )->operator[]( offset( i, j ) ) ;
136136
}
137137

138+
inline Proxy at( const size_t& i, const size_t& j) {
139+
return static_cast< Vector<RTYPE>* >( this )->operator()( i, j ) ;
140+
}
141+
inline const_Proxy at( const size_t& i, const size_t& j) const {
142+
return static_cast< const Vector<RTYPE>* >( this )->operator()( i, j ) ;
143+
}
144+
138145
inline Row operator()( int i, internal::NamedPlaceHolder ) {
139146
return Row( *this, i ) ;
140147
}

inst/include/Rcpp/vector/Vector.h

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -278,26 +278,26 @@ class Vector :
278278
/**
279279
* offset based on the dimensions of this vector
280280
*/
281-
size_t offset(const size_t& i, const size_t& j) const {
281+
R_xlen_t offset(const int& i, const int& j) const {
282282
if( !::Rf_isMatrix(Storage::get__()) ) throw not_a_matrix() ;
283283

284284
/* we need to extract the dimensions */
285-
int *dim = dims() ;
286-
size_t nrow = static_cast<size_t>(dim[0]) ;
287-
size_t ncol = static_cast<size_t>(dim[1]) ;
288-
if( i >= nrow || j >= ncol ) throw index_out_of_bounds() ;
289-
return i + nrow*j ;
285+
const int* dim = dims() ;
286+
const int nrow = dim[0] ;
287+
const int ncol = dim[1] ;
288+
if(i < 0|| i >= nrow || j < 0 || j >= ncol ) throw index_out_of_bounds() ;
289+
return i + static_cast<R_xlen_t>(nrow)*j ;
290290
}
291291

292292
/**
293293
* one dimensional offset doing bounds checking to ensure
294294
* it is valid
295295
*/
296-
size_t offset(const size_t& i) const {
297-
if( static_cast<R_xlen_t>(i) >= ::Rf_xlength(Storage::get__()) ) throw index_out_of_bounds() ;
296+
R_xlen_t offset(const R_xlen_t& i) const {
297+
if(i < 0 || i >= ::Rf_xlength(Storage::get__()) ) throw index_out_of_bounds() ;
298298
return i ;
299299
}
300-
300+
301301
R_xlen_t offset(const std::string& name) const {
302302
SEXP names = RCPP_GET_NAMES( Storage::get__() ) ;
303303
if( Rf_isNull(names) ) throw index_out_of_bounds();
@@ -318,7 +318,7 @@ class Vector :
318318

319319
inline iterator begin() { return cache.get() ; }
320320
inline iterator end() { return cache.get() + size() ; }
321-
inline const_iterator begin() const{ return cache.get_const() ; }
321+
inline const_iterator begin() const{ return cache.get_const() ; }
322322
inline const_iterator end() const{ return cache.get_const() + size() ; }
323323

324324
inline Proxy operator[]( R_xlen_t i ){ return cache.ref(i) ; }
@@ -331,6 +331,13 @@ class Vector :
331331
return cache.ref( offset(i) ) ;
332332
}
333333

334+
inline Proxy at( const size_t& i) {
335+
return cache.ref( offset(i) ) ;
336+
}
337+
inline const_Proxy at( const size_t& i) const {
338+
return cache.ref( offset(i) ) ;
339+
}
340+
334341
inline Proxy operator()( const size_t& i, const size_t& j) {
335342
return cache.ref( offset(i,j) ) ;
336343
}

inst/unitTests/cpp/Matrix.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,3 +238,7 @@ NumericVector runit_const_Matrix_column( const NumericMatrix& m ){
238238
return col1 ;
239239
}
240240

241+
// [[Rcpp::export]]
242+
int mat_access_with_bounds_checking(const IntegerMatrix m, int i, int j) {
243+
return m.at(i, j);
244+
}

inst/unitTests/cpp/Vector.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,3 +777,8 @@ int noprotect_vector( Vector<REALSXP, NoProtectStorage> x){
777777
int noprotect_matrix( Matrix<REALSXP, NoProtectStorage> x){
778778
return x.nrow() ;
779779
}
780+
781+
// [[Rcpp::export]]
782+
int vec_access_with_bounds_checking(const IntegerVector x, int index) {
783+
return x.at(index);
784+
}

inst/unitTests/runit.Matrix.R

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,16 @@ if (.runThisTest) {
171171
checkEquals( m[,1], m[,2] )
172172
}
173173

174+
test.IntegerMatrix.accessor.with.bounds.checking <- function() {
175+
m <- matrix(seq(1L, 12, by=1L), nrow=4L, ncol=3L)
176+
checkEquals(mat_access_with_bounds_checking(m, 0, 0), 1)
177+
checkEquals(mat_access_with_bounds_checking(m, 1, 2), 10)
178+
checkEquals(mat_access_with_bounds_checking(m, 3, 2), 12)
179+
checkException(mat_access_with_bounds_checking(m, 4, 2) , msg = "index out of bounds not detected" )
180+
checkException(mat_access_with_bounds_checking(m, 3, 3) , msg = "index out of bounds not detected" )
181+
checkException(mat_access_with_bounds_checking(m, 3, -1) , msg = "index out of bounds not detected" )
182+
checkException(mat_access_with_bounds_checking(m, -1, 2) , msg = "index out of bounds not detected" )
183+
checkException(mat_access_with_bounds_checking(m, -1, -1) , msg = "index out of bounds not detected" )
184+
}
185+
174186
}

inst/unitTests/runit.Vector.R

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,12 @@ if (.runThisTest) {
683683
x <- matrix(rnorm(10), nrow=2)
684684
checkIdentical( noprotect_matrix(x), 2L )
685685
}
686-
686+
687+
test.IntegerVector.accessor.with.bounds.checking <- function() {
688+
x <- seq(1L, 5L, by=1L)
689+
checkEquals(vec_access_with_bounds_checking(x, 3), 4)
690+
checkException(vec_access_with_bounds_checking(x, 5) , msg = "index out of bounds not detected" )
691+
checkException(vec_access_with_bounds_checking(x, -1) , msg = "index out of bounds not detected" )
692+
}
687693
}
688694

0 commit comments

Comments
 (0)