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