|
Rcpp Version 0.9.10
|
00001 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 00002 // 00003 // Matrix.h: Rcpp R/C++ interface class library -- matrices 00004 // 00005 // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois 00006 // 00007 // This file is part of Rcpp. 00008 // 00009 // Rcpp is free software: you can redistribute it and/or modify it 00010 // under the terms of the GNU General Public License as published by 00011 // the Free Software Foundation, either version 2 of the License, or 00012 // (at your option) any later version. 00013 // 00014 // Rcpp is distributed in the hope that it will be useful, but 00015 // WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 // GNU General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU General Public License 00020 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>. 00021 00022 #ifndef Rcpp__vector__Matrix_h 00023 #define Rcpp__vector__Matrix_h 00024 00025 template <int RTYPE> 00026 class Matrix : public Vector<RTYPE>, public MatrixBase<RTYPE,true, Matrix<RTYPE> > { 00027 public: 00028 struct r_type : traits::integral_constant<int,RTYPE>{} ; 00029 struct can_have_na : traits::true_type{} ; 00030 00031 typedef Vector<RTYPE> VECTOR ; 00032 typedef typename VECTOR::iterator iterator ; 00033 typedef typename VECTOR::converter_type converter_type ; 00034 typedef typename VECTOR::stored_type stored_type ; 00035 typedef typename VECTOR::Proxy Proxy ; 00036 00037 Matrix() : VECTOR() {} 00038 00039 Matrix(SEXP x) : VECTOR(), nrows(0) { 00040 if( ! ::Rf_isMatrix(x) ) throw not_compatible("not a matrix") ; 00041 SEXP y = r_cast<RTYPE>( x ) ; 00042 VECTOR::setSEXP( y ); 00043 nrows = VECTOR::dims()[0] ; 00044 } 00045 00046 Matrix( const Dimension& dims) : VECTOR(), nrows(dims[0]) { 00047 if( dims.size() != 2 ) throw not_compatible("not a matrix") ; 00048 VECTOR::setSEXP( Rf_allocMatrix( RTYPE, dims[0], dims[1] ) ) ; 00049 VECTOR::init() ; 00050 } 00051 00052 Matrix( const int& nrows_, const int& ncols) : 00053 VECTOR( Dimension( nrows_, ncols ) ), 00054 nrows(nrows_) 00055 {} 00056 00057 template <typename Iterator> 00058 Matrix( const int& nrows_, const int& ncols, Iterator start ) : 00059 VECTOR( start, start + (nrows_*ncols) ), 00060 nrows(nrows_) 00061 { 00062 VECTOR::attr( "dim" ) = Dimension( nrows, ncols ) ; 00063 } 00064 00065 Matrix( const int& n) : VECTOR( Dimension( n, n ) ), nrows(n) {} 00066 00067 Matrix( const Matrix& other) : VECTOR(), nrows(other.nrows) { 00068 SEXP x = other.asSexp() ; 00069 if( ! ::Rf_isMatrix(x) ) throw not_compatible("not a matrix") ; 00070 VECTOR::setSEXP( x ) ; 00071 } 00072 00073 Matrix& operator=(const Matrix& other) { 00074 SEXP x = other.asSexp() ; 00075 if( ! ::Rf_isMatrix(x) ) not_compatible("not a matrix") ; 00076 VECTOR::setSEXP( x ) ; 00077 nrows = other.nrows ; 00078 return *this ; 00079 } 00080 00081 template <bool NA, typename MAT> 00082 Matrix( const MatrixBase<RTYPE,NA,MAT>& other ) : VECTOR(), nrows(other.nrow()) { 00083 int nc = other.ncol() ; 00084 RObject::setSEXP( Rf_allocMatrix( RTYPE, nrows, nc ) ) ; 00085 import_matrix_expression<NA,MAT>( other, nrows, nc ) ; 00086 } 00087 00088 // defined later 00089 Matrix( const SubMatrix<RTYPE>& ) ; 00090 Matrix& operator=( const SubMatrix<RTYPE>& ) ; 00091 00092 private: 00093 00094 template <bool NA, typename MAT> 00095 void import_matrix_expression( const MatrixBase<RTYPE,NA,MAT>& other, int nr, int nc ){ 00096 iterator start = VECTOR::begin() ; 00097 for( int j=0; j<nc; j++){ 00098 for( int i=0; i<nr; i++, ++start){ 00099 *start = other(i,j) ; 00100 } 00101 } 00102 } 00103 00104 public: 00105 00106 template <typename U> 00107 void fill_diag( const U& u){ 00108 fill_diag__dispatch( typename traits::is_trivial<RTYPE>::type(), u ) ; 00109 } 00110 00111 template <typename U> 00112 static Matrix diag( int size, const U& diag_value ){ 00113 Matrix res(size,size) ; 00114 res.fill_diag( diag_value ) ; 00115 return res ; 00116 } 00117 00118 inline Proxy operator[]( int i ){ 00119 return static_cast< Vector<RTYPE>* >( this )->operator[]( i ) ; 00120 } 00121 00122 inline Proxy operator[]( int i ) const { 00123 return static_cast< const Vector<RTYPE>* >( this )->operator[]( i ) ; 00124 } 00125 00126 inline Proxy operator()( const size_t& i, const size_t& j) { 00127 return static_cast< Vector<RTYPE>* >( this )->operator[]( 00128 offset( i, j ) 00129 ) ; 00130 } 00131 00132 inline Proxy operator()( const size_t& i, const size_t& j) const { 00133 return static_cast< const Vector<RTYPE>* >( this )->operator[]( 00134 offset( i, j ) 00135 ) ; 00136 } 00137 00138 typedef MatrixRow<RTYPE> Row ; 00139 typedef MatrixColumn<RTYPE> Column ; 00140 typedef SubMatrix<RTYPE> Sub ; 00141 00142 inline Row operator()( int i, internal::NamedPlaceHolder ){ 00143 return Row( *this, i ) ; 00144 } 00145 00146 inline Column operator()( internal::NamedPlaceHolder, int i ){ 00147 return Column( *this, i ) ; 00148 } 00149 00150 inline Sub operator()( const Range& row_range, const Range& col_range){ 00151 return Sub( const_cast<Matrix&>(*this), row_range, col_range ) ; 00152 } 00153 00154 inline Sub operator()( internal::NamedPlaceHolder, const Range& col_range){ 00155 return Sub( const_cast<Matrix&>(*this), Range(0,nrow()-1) , col_range ) ; 00156 } 00157 00158 inline Sub operator()( const Range& row_range, internal::NamedPlaceHolder ){ 00159 return Sub( const_cast<Matrix&>(*this), row_range, Range(0,ncol()-1) ) ; 00160 } 00161 00162 00163 private: 00164 00165 inline int offset( int i, int j) const { 00166 return i + nrows * j ; 00167 } 00168 00169 virtual void update(){ 00170 RCPP_DEBUG_1( "%s::update", DEMANGLE(Matrix) ) ; 00171 VECTOR::update_vector() ; 00172 } 00173 00174 template <typename U> 00175 void fill_diag__dispatch( traits::false_type, const U& u){ 00176 SEXP elem = PROTECT( converter_type::get( u ) ) ; 00177 int n = Matrix::ncol() ; 00178 int offset = n +1 ; 00179 iterator it( VECTOR::begin()) ; 00180 for( int i=0; i<n; i++){ 00181 *it = ::Rf_duplicate( elem ); 00182 it += offset; 00183 } 00184 UNPROTECT(1); // elem 00185 } 00186 00187 template <typename U> 00188 void fill_diag__dispatch( traits::true_type, const U& u){ 00189 stored_type elem = converter_type::get( u ) ; 00190 int n = Matrix::ncol() ; 00191 int offset = n + 1 ; 00192 iterator it( VECTOR::begin()) ; 00193 for( int i=0; i<n; i++){ 00194 *it = elem ; 00195 it += offset; 00196 } 00197 } 00198 00199 public: 00200 inline int ncol() const { 00201 return VECTOR::dims()[1]; 00202 } 00203 inline int nrow() const { 00204 return nrows ; 00205 } 00206 inline int cols() const { 00207 return VECTOR::dims()[1]; 00208 } 00209 inline int rows() const { 00210 return nrows ; 00211 } 00212 00213 inline Row row( int i ){ return Row( *this, i ) ; } 00214 inline Column column( int i ){ return Column(*this, i ) ; } 00215 00216 inline iterator begin() const{ return VECTOR::begin() ; } 00217 inline iterator end() const{ return VECTOR::end() ; } 00218 00219 private: 00220 int nrows ; 00221 00222 } ; 00223 00224 00225 #endif