@@ -27,8 +27,11 @@ namespace Rcpp{
2727
2828template <int RTYPE , template <class > class StoragePolicy = PreserveStorage >
2929class Matrix : public Vector <RTYPE , StoragePolicy>, public MatrixBase<RTYPE , true , Matrix<RTYPE ,StoragePolicy> > {
30+ // The only data member. Packages pass Rcpp objects by reference across
31+ // shared-library boundaries (e.g. rust calls into revdbayes through XPtr
32+ // function pointers), and the two sides may have been compiled against
33+ // different Rcpp versions. Adding a member changes the layout they share.
3034 int nrows ;
31- int ncols ;
3235
3336public:
3437 using Vector<RTYPE , StoragePolicy>::size; // disambiguate diamond pattern for g++-6 and later
@@ -50,33 +53,33 @@ class Matrix : public Vector<RTYPE, StoragePolicy>, public MatrixBase<RTYPE, tru
5053 typedef typename VECTOR ::Proxy Proxy ;
5154 typedef typename VECTOR ::const_Proxy const_Proxy ;
5255
53- Matrix () : VECTOR (Dimension(0 , 0 )), nrows(0 ), ncols( 0 ) {}
56+ Matrix () : VECTOR (Dimension(0 , 0 )), nrows(0 ) {}
5457
55- Matrix (SEXP x) : VECTOR (x), nrows( VECTOR ::dims()[0 ] ), ncols( VECTOR ::dims()[ 1 ] ) {}
58+ Matrix (SEXP x) : VECTOR (x), nrows( VECTOR ::dims()[0 ] ) {}
5659
57- Matrix ( const Dimension& dims) : VECTOR ( Rf_allocMatrix( RTYPE , dims[0 ], dims[1 ] ) ), nrows(dims[0 ]), ncols(dims[ 1 ]) {
60+ Matrix ( const Dimension& dims) : VECTOR ( Rf_allocMatrix( RTYPE , dims[0 ], dims[1 ] ) ), nrows(dims[0 ]) {
5861 if ( dims.size () != 2 ) throw not_a_matrix ();
5962 VECTOR::init () ;
6063 }
61- Matrix ( const int & nrows_, const int & ncols_ ) : VECTOR ( Dimension( nrows_, ncols_ ) ),
62- nrows (nrows_), ncols(ncols_)
64+ Matrix ( const int & nrows_, const int & ncols ) : VECTOR ( Dimension( nrows_, ncols ) ),
65+ nrows (nrows_)
6366 {}
6467
6568 template <typename Iterator>
66- Matrix ( const int & nrows_, const int & ncols_ , Iterator start ) :
67- VECTOR( start, start + (static_cast <R_xlen_t>(nrows_)*ncols_ ) ),
68- nrows(nrows_), ncols(ncols_)
69+ Matrix ( const int & nrows_, const int & ncols , Iterator start ) :
70+ VECTOR( start, start + (static_cast <R_xlen_t>(nrows_)*ncols ) ),
71+ nrows(nrows_)
6972 {
7073 VECTOR::attr ( " dim" ) = Dimension ( nrows, ncols ) ;
7174 }
7275
73- Matrix ( const int & n) : VECTOR( Dimension( n, n ) ), nrows(n), ncols(n) {}
76+ Matrix ( const int & n) : VECTOR( Dimension( n, n ) ), nrows(n) {}
7477
7578
76- Matrix ( const Matrix& other) : VECTOR( other.get__() ), nrows(other.nrows), ncols(other.ncols) {}
79+ Matrix ( const Matrix& other) : VECTOR( other.get__() ), nrows(other.nrows) {}
7780
7881 template <bool NA , typename MAT >
79- Matrix ( const MatrixBase<RTYPE ,NA ,MAT >& other ) : VECTOR( Rf_allocMatrix( RTYPE , static_cast <int >(other.nrow()), static_cast<int>(other.ncol()) ) ), nrows(static_cast <int >(other.nrow())), ncols( static_cast < int >(other.ncol())) {
82+ Matrix ( const MatrixBase<RTYPE ,NA ,MAT >& other ) : VECTOR( Rf_allocMatrix( RTYPE , static_cast <int >(other.nrow()), static_cast<int>(other.ncol()) ) ), nrows(static_cast <int >(other.nrow())) {
8083 import_matrix_expression<NA ,MAT >( other, nrows, ncol () ) ;
8184 }
8285
@@ -87,21 +90,23 @@ class Matrix : public Vector<RTYPE, StoragePolicy>, public MatrixBase<RTYPE, tru
8790 if ( ! ::Rf_isMatrix (x) ) throw not_a_matrix ();
8891 VECTOR::set__ ( x ) ;
8992 nrows = other.nrows ;
90- ncols = other.ncols ;
9193 return *this ;
9294 }
9395 Matrix& operator =( const SubMatrix<RTYPE >& ) ;
9496
95- explicit Matrix ( const no_init_matrix& obj) : VECTOR(Rf_allocMatrix(RTYPE , obj.nrow(), obj.ncol())), nrows(obj.nrow()), ncols(obj.ncol()) {}
97+ explicit Matrix ( const no_init_matrix& obj) : VECTOR(Rf_allocMatrix(RTYPE , obj.nrow(), obj.ncol())), nrows(obj.nrow()) {}
9698
99+ // A matrix has exactly nrow * ncol elements, so the column count follows
100+ // from the (cached) length without reading the dim attribute. Only an
101+ // empty matrix, which may still have columns, needs the attribute.
97102 inline int ncol () const {
98- return ncols ;
103+ return nrows == 0 ? VECTOR::dims ()[ 1 ] : static_cast < int >( VECTOR::size () / nrows ) ;
99104 }
100105 inline int nrow () const {
101106 return nrows ;
102107 }
103108 inline int cols () const {
104- return ncols ;
109+ return ncol () ;
105110 }
106111 inline int rows () const {
107112 return nrows ;
0 commit comments