Skip to content

Rcpp is inconsistent with RInternals integers types #369

@fplazaonate

Description

@fplazaonate

Rcpp is inconsistent with RInternals integers types.
At some places in the code, 'size_t' and 'int' are used instead of 'R_xlen_t '

For all I know, it causes the following issues:

  • inability of creating in Rcpp a matrix with more than 2^31-1 elements(runtime error)
  • inability of querying a matrix with more than 2^31-1 (segfault caused by an integer overflow)

I proposed a time ago some patches #338
Some of them were subject of discussion because they changed the Rcpp interface.
However, some changes are mandatory to solve this issue:

Dimension::prod

From

inline int prod() const {
    return std::accumulate( dims.begin(), dims.end(), 1, std::multiplies<int>() ) ;
}

To

inline R_xlen_t prod() const {
    return std::accumulate( dims.begin(), dims.end(), static_cast<R_xlen_t>(1), std::multiplies<R_xlen_t>() )
}
Matrix::Matrix

From

    template <typename Iterator>
    Matrix( const int& nrows_, const int& ncols, Iterator start ) :
    VECTOR( start, start + (nrows_*ncols) ),

To

     template <typename Iterator>
     Matrix( const int& nrows_, const int& ncols, Iterator start ) :
     VECTOR( start, start + (static_cast<R_xlen_t>(nrows_)*ncols) ),
Matrix::offset

From

inline R_xlen_t offset( int i, int j) const { return i + nrows * j ; }

To

inline R_xlen_t offset(const int i, const int j) const { return i + static_cast<R_xlen_t>(nrows) * j ; }  
Vector::offset

From

size_t offset(const size_t& i, const size_t& j) const {
         if( !::Rf_isMatrix(Storage::get__()) ) throw not_a_matrix() ;

         int *dim = dims() ;
         size_t nrow = static_cast<size_t>(dim[0]) ;
         size_t ncol = static_cast<size_t>(dim[1]) ;

         if( i >= nrow || j >= ncol ) throw index_out_of_bounds() ;

         return i + nrow*j ;
}

To

R_xlen_t offset(const int& i, const int& j) const {
         if( !::Rf_isMatrix(Storage::get__()) ) throw not_a_matrix() ;

         const int* dim = dims() ;
         const int nrow = dim[0] ;
         const int ncol = dim[1] ;

         if(i < 0|| i >= nrow || j < 0 || j >= ncol ) throw index_out_of_bounds() ;

         return i + static_cast<R_xlen_t>(nrow)*j ;
}
Vector::offset

From

size_t offset(const size_t& i) const {
         if( static_cast<R_xlen_t>(i) >= ::Rf_xlength(Storage::get__()) ) throw index_out_of_bounds() ;

         return i ;
}

To

R_xlen_t offset(const R_xlen_t& i) const {
       if(i < 0 || i >= ::Rf_xlength(Storage::get__()) ) throw index_out_of_bounds() ;
         return i ;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions