1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- 2 // 3 // MatrixBase.h: Rcpp R/C++ interface class library -- 4 // 5 // Copyright (C) 2010 - 2016 Dirk Eddelbuettel and Romain Francois 6 // Copyright (C) 2016 Dirk Eddelbuettel and Romain Francois and Nathan Russell 7 // 8 // This file is part of Rcpp. 9 // 10 // Rcpp is free software: you can redistribute it and/or modify it 11 // under the terms of the GNU General Public License as published by 12 // the Free Software Foundation, either version 2 of the License, or 13 // (at your option) any later version. 14 // 15 // Rcpp is distributed in the hope that it will be useful, but 16 // WITHOUT ANY WARRANTY; without even the implied warranty of 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 // GNU General Public License for more details. 19 // 20 // You should have received a copy of the GNU General Public License 21 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>. 22 23 #ifndef Rcpp__vector__MatrixBase_h 24 #define Rcpp__vector__MatrixBase_h 25 26 #include <Rcpp/sugar/matrix/tools.h> 27 28 namespace Rcpp{ 29 30 /** a base class for vectors, modelled after the CRTP */ 31 template <int RTYPE, bool na, typename MATRIX> 32 class MatrixBase : public traits::expands_to_logical__impl<RTYPE> { 33 public: 34 struct r_type : traits::integral_constant<int,RTYPE>{} ; 35 struct r_matrix_interface {} ; 36 struct can_have_na : traits::integral_constant<bool,na>{} ; 37 typedef typename traits::storage_type<RTYPE>::type stored_type ; 38 get_ref()39 MATRIX& get_ref(){ 40 return static_cast<MATRIX&>(*this) ; 41 } 42 operator()43 inline stored_type operator()( int i, int j) const { 44 return static_cast<const MATRIX*>(this)->operator()(i, j) ; 45 } 46 size()47 inline R_xlen_t size() const { return static_cast<const MATRIX&>(*this).size() ; } nrow()48 inline R_xlen_t nrow() const { return static_cast<const MATRIX&>(*this).nrow() ; } ncol()49 inline R_xlen_t ncol() const { return static_cast<const MATRIX&>(*this).ncol() ; } 50 eye(int n)51 static MATRIX eye(int n) { 52 const bool enabled = 53 traits::is_arithmetic<stored_type>::value || 54 traits::same_type<stored_type, Rcomplex>::value; 55 (void)sizeof(traits::allowed_matrix_type<enabled>); 56 57 return MATRIX::diag(n, traits::one_type<stored_type>()); 58 } 59 ones(int n)60 static MATRIX ones(int n) { 61 const bool enabled = 62 traits::is_arithmetic<stored_type>::value || 63 traits::same_type<stored_type, Rcomplex>::value; 64 (void)sizeof(traits::allowed_matrix_type<enabled>); 65 66 MATRIX res(n, n); 67 std::fill( 68 res.begin(), res.end(), 69 traits::one_type<stored_type>() 70 ); 71 return res; 72 } 73 zeros(int n)74 static MATRIX zeros(int n) { 75 const bool enabled = 76 traits::is_arithmetic<stored_type>::value || 77 traits::same_type<stored_type, Rcomplex>::value; 78 (void)sizeof(traits::allowed_matrix_type<enabled>); 79 80 return MATRIX(n, n); 81 } 82 83 class iterator { 84 public: 85 typedef stored_type reference ; 86 typedef stored_type* pointer ; 87 typedef R_xlen_t difference_type ; 88 typedef stored_type value_type; 89 typedef std::random_access_iterator_tag iterator_category ; 90 iterator(const MatrixBase & object_,R_xlen_t index_)91 iterator( const MatrixBase& object_, R_xlen_t index_ ) : 92 object(object_), i(0), j(0), nr(object_.nrow()), nc(object_.ncol()) { 93 94 update_index( index_) ; 95 } 96 iterator(const iterator & other)97 iterator( const iterator& other) : 98 object(other.object), i(other.i), j(other.j), nr(other.nr), nc(other.nc){} 99 100 inline iterator& operator++(){ 101 i++ ; 102 if( i == nr ){ 103 j++ ; 104 i=0 ; 105 } 106 return *this ; 107 } 108 inline iterator operator++(int){ 109 iterator orig(*this) ; 110 ++(*this) ; 111 return orig ; 112 } 113 114 inline iterator& operator--(){ 115 i-- ; 116 if( i == -1 ){ 117 j-- ; 118 i = nr - 1 ; 119 } 120 return *this ; 121 } 122 inline iterator operator--(int){ 123 iterator orig(*this) ; 124 --(*this) ; 125 return orig ; 126 } 127 128 inline iterator operator+(difference_type n) const { 129 return iterator( object, i + (j*nr) + n ) ; 130 } 131 inline iterator operator-(difference_type n) const { 132 return iterator( object, i + (j*nr) - n ) ; 133 } 134 135 inline iterator& operator+=(difference_type n) { 136 update_index( i + j*nr + n ); 137 return *this ; 138 } 139 inline iterator& operator-=(difference_type n) { 140 update_index( i + j*nr - n ); 141 return *this ; 142 } 143 144 inline reference operator*() { 145 return object(i,j) ; 146 } 147 inline pointer operator->(){ 148 return &object(i,j) ; 149 } 150 151 inline bool operator==( const iterator& y) const { 152 return ( i == y.i && j == y.j ) ; 153 } 154 inline bool operator!=( const iterator& y) const { 155 return ( i != y.i || j != y.j ) ; 156 } 157 inline bool operator<( const iterator& other ) const { 158 return index() < other.index() ; 159 } 160 inline bool operator>( const iterator& other ) const { 161 return index() > other.index() ; 162 } 163 inline bool operator<=( const iterator& other ) const { 164 return index() <= other.index() ; 165 } 166 inline bool operator>=( const iterator& other ) const { 167 return index() >= other.index() ; 168 } 169 170 inline difference_type operator-(const iterator& other) const { 171 return index() - other.index() ; 172 } 173 174 175 private: 176 const MatrixBase& object ; 177 int i, j ; 178 int nr, nc ; 179 update_index(int index_)180 inline void update_index( int index_ ){ 181 i = internal::get_line( index_, nr ); 182 j = internal::get_column( index_, nr, i ) ; 183 } 184 index()185 inline R_xlen_t index() const { 186 return i + nr * j ; 187 } 188 189 } ; 190 begin()191 inline iterator begin() const { return iterator(*this, 0) ; } end()192 inline iterator end() const { return iterator(*this, size() ) ; } 193 194 } ; 195 196 } // namespace Rcpp 197 #endif 198