1 // -*- c++ -*- (enables emacs c++ mode)
2 //===========================================================================
3 //
4 // Copyright (C) 2002-2008 Yves Renard
5 //
6 // This file is a part of GETFEM++
7 //
8 // Getfem++  is  free software;  you  can  redistribute  it  and/or modify it
9 // under  the  terms  of the  GNU  Lesser General Public License as published
10 // by  the  Free Software Foundation;  either version 2.1 of the License,  or
11 // (at your option) any later version.
12 // This program  is  distributed  in  the  hope  that it will be useful,  but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15 // License for more details.
16 // You  should  have received a copy of the GNU Lesser General Public License
17 // along  with  this program;  if not, write to the Free Software Foundation,
18 // Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
19 //
20 // As a special exception, you may use this file as part of a free software
21 // library without restriction.  Specifically, if other files instantiate
22 // templates or use macros or inline functions from this file, or you compile
23 // this file and link it with other files to produce an executable, this
24 // file does not by itself cause the resulting executable to be covered by
25 // the GNU General Public License.  This exception does not however
26 // invalidate any other reasons why the executable file might be covered by
27 // the GNU General Public License.
28 //
29 //===========================================================================
30 
31 /**@file gmm_transposed.h
32    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
33    @date November 10, 2002.
34    @brief Generic transposed matrices
35 */
36 #ifndef GMM_TRANSPOSED_H__
37 #define GMM_TRANSPOSED_H__
38 
39 #include "gmm_def.h"
40 
41 namespace gmm {
42 
43   /* ********************************************************************* */
44   /*		transposed reference                    		   */
45   /* ********************************************************************* */
46 
47   template <typename PT> struct  transposed_row_ref {
48 
49     typedef transposed_row_ref<PT> this_type;
50     typedef typename std::iterator_traits<PT>::value_type M;
51     typedef M * CPT;
52     typedef typename std::iterator_traits<PT>::reference ref_M;
53     typedef typename select_ref<typename linalg_traits<this_type>
54             ::const_col_iterator, typename linalg_traits<this_type>
55             ::col_iterator, PT>::ref_type iterator;
56     typedef typename linalg_traits<this_type>::reference reference;
57     typedef typename linalg_traits<this_type>::porigin_type porigin_type;
58 
59     iterator begin_, end_;
60     porigin_type origin;
61     size_type nr, nc;
62 
transposed_row_reftransposed_row_ref63     transposed_row_ref(ref_M m)
64       : begin_(mat_row_begin(m)), end_(mat_row_end(m)),
65 	origin(linalg_origin(m)), nr(mat_ncols(m)), nc(mat_nrows(m)) {}
66 
transposed_row_reftransposed_row_ref67     transposed_row_ref(const transposed_row_ref<CPT> &cr) :
68       begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {}
69 
operatortransposed_row_ref70     reference operator()(size_type i, size_type j) const
71     { return linalg_traits<M>::access(begin_+j, i); }
72   };
73 
74   template <typename PT> struct linalg_traits<transposed_row_ref<PT> > {
75     typedef transposed_row_ref<PT> this_type;
76     typedef typename std::iterator_traits<PT>::value_type M;
77     typedef typename linalg_traits<M>::origin_type origin_type;
78     typedef typename select_ref<const origin_type *, origin_type *,
79 			        PT>::ref_type porigin_type;
80     typedef typename which_reference<PT>::is_reference is_reference;
81     typedef abstract_matrix linalg_type;
82     typedef typename linalg_traits<M>::value_type value_type;
83     typedef typename select_ref<value_type,
84             typename linalg_traits<M>::reference, PT>::ref_type reference;
85     typedef typename linalg_traits<M>::storage_type storage_type;
86     typedef abstract_null_type sub_row_type;
87     typedef abstract_null_type const_sub_row_type;
88     typedef abstract_null_type row_iterator;
89     typedef abstract_null_type const_row_iterator;
90     typedef typename linalg_traits<M>::const_sub_row_type const_sub_col_type;
91     typedef typename select_ref<abstract_null_type, typename
92             linalg_traits<M>::sub_row_type, PT>::ref_type sub_col_type;
93     typedef typename linalg_traits<M>::const_row_iterator const_col_iterator;
94     typedef typename select_ref<abstract_null_type, typename
95             linalg_traits<M>::row_iterator, PT>::ref_type col_iterator;
96     typedef col_major sub_orientation;
97     typedef typename linalg_traits<M>::index_sorted index_sorted;
98     static size_type ncols(const this_type &v) { return v.nc; }
99     static size_type nrows(const this_type &v) { return v.nr; }
100     static const_sub_col_type col(const const_col_iterator &it)
101     { return linalg_traits<M>::row(it); }
102     static sub_col_type col(const col_iterator &it)
103     { return linalg_traits<M>::row(it); }
104     static col_iterator col_begin(this_type &m) { return m.begin_; }
105     static col_iterator col_end(this_type &m) { return m.end_; }
106     static const_col_iterator col_begin(const this_type &m)
107     { return m.begin_; }
108     static const_col_iterator col_end(const this_type &m) { return m.end_; }
109     static origin_type* origin(this_type &v) { return v.origin; }
110     static const origin_type* origin(const this_type &v) { return v.origin; }
111     static void do_clear(this_type &v);
112     static value_type access(const const_col_iterator &itcol, size_type i)
113     { return linalg_traits<M>::access(itcol, i); }
114     static reference access(const col_iterator &itcol, size_type i)
115     { return linalg_traits<M>::access(itcol, i); }
116   };
117 
118   template <typename PT>
119   void linalg_traits<transposed_row_ref<PT> >::do_clear(this_type &v) {
120     col_iterator it = mat_col_begin(v), ite = mat_col_end(v);
121     for (; it != ite; ++it) clear(col(it));
122   }
123 
124   template<typename PT> std::ostream &operator <<
125   (std::ostream &o, const transposed_row_ref<PT>& m)
126   { gmm::write(o,m); return o; }
127 
128   template <typename PT> struct  transposed_col_ref {
129 
130     typedef transposed_col_ref<PT> this_type;
131     typedef typename std::iterator_traits<PT>::value_type M;
132     typedef M * CPT;
133     typedef typename std::iterator_traits<PT>::reference ref_M;
134     typedef typename select_ref<typename linalg_traits<this_type>
135             ::const_row_iterator, typename linalg_traits<this_type>
136             ::row_iterator, PT>::ref_type iterator;
137     typedef typename linalg_traits<this_type>::reference reference;
138     typedef typename linalg_traits<this_type>::porigin_type porigin_type;
139 
140     iterator begin_, end_;
141     porigin_type origin;
142     size_type nr, nc;
143 
144     transposed_col_ref(ref_M m)
145       : begin_(mat_col_begin(m)), end_(mat_col_end(m)),
146 	origin(linalg_origin(m)), nr(mat_ncols(m)), nc(mat_nrows(m)) {}
147 
148     transposed_col_ref(const transposed_col_ref<CPT> &cr) :
149       begin_(cr.begin_),end_(cr.end_), origin(cr.origin),nr(cr.nr),nc(cr.nc) {}
150 
151     reference operator()(size_type i, size_type j) const
152     { return linalg_traits<M>::access(begin_+i, j); }
153   };
154 
155   template <typename PT> struct linalg_traits<transposed_col_ref<PT> > {
156     typedef transposed_col_ref<PT> this_type;
157     typedef typename std::iterator_traits<PT>::value_type M;
158     typedef typename linalg_traits<M>::origin_type origin_type;
159     typedef typename select_ref<const origin_type *, origin_type *,
160 			        PT>::ref_type porigin_type;
161     typedef typename which_reference<PT>::is_reference is_reference;
162     typedef abstract_matrix linalg_type;
163     typedef typename linalg_traits<M>::value_type value_type;
164     typedef typename select_ref<value_type,
165             typename linalg_traits<M>::reference, PT>::ref_type reference;
166     typedef typename linalg_traits<M>::storage_type storage_type;
167     typedef abstract_null_type sub_col_type;
168     typedef abstract_null_type const_sub_col_type;
169     typedef abstract_null_type col_iterator;
170     typedef abstract_null_type const_col_iterator;
171     typedef typename linalg_traits<M>::const_sub_col_type const_sub_row_type;
172     typedef typename select_ref<abstract_null_type, typename
173             linalg_traits<M>::sub_col_type, PT>::ref_type sub_row_type;
174     typedef typename linalg_traits<M>::const_col_iterator const_row_iterator;
175     typedef typename select_ref<abstract_null_type, typename
176             linalg_traits<M>::col_iterator, PT>::ref_type row_iterator;
177     typedef row_major sub_orientation;
178     typedef typename linalg_traits<M>::index_sorted index_sorted;
179     static size_type nrows(const this_type &v)
180     { return v.nr; }
181     static size_type ncols(const this_type &v)
182     { return v.nc; }
183     static const_sub_row_type row(const const_row_iterator &it)
184     { return linalg_traits<M>::col(it); }
185     static sub_row_type row(const row_iterator &it)
186     { return linalg_traits<M>::col(it); }
187     static row_iterator row_begin(this_type &m) { return m.begin_; }
188     static row_iterator row_end(this_type &m) { return m.end_; }
189     static const_row_iterator row_begin(const this_type &m)
190     { return m.begin_; }
191     static const_row_iterator row_end(const this_type &m) { return m.end_; }
192     static origin_type* origin(this_type &v) { return v.origin; }
193     static const origin_type* origin(const this_type &v) { return v.origin; }
194     static void do_clear(this_type &m);
195     static value_type access(const const_row_iterator &itrow, size_type i)
196     { return linalg_traits<M>::access(itrow, i); }
197     static reference access(const row_iterator &itrow, size_type i)
198     { return linalg_traits<M>::access(itrow, i); }
199   };
200 
201   template <typename PT>
202   void linalg_traits<transposed_col_ref<PT> >::do_clear(this_type &v) {
203     row_iterator it = mat_row_begin(v), ite = mat_row_end(v);
204     for (; it != ite; ++it) clear(row(it));
205   }
206 
207   template<typename PT> std::ostream &operator <<
208   (std::ostream &o, const transposed_col_ref<PT>& m)
209   { gmm::write(o,m); return o; }
210 
211   template <typename TYPE, typename PT> struct transposed_return_ {
212     typedef abstract_null_type return_type;
213   };
214   template <typename PT> struct transposed_return_<row_major, PT> {
215     typedef typename std::iterator_traits<PT>::value_type L;
216     typedef typename select_return<transposed_row_ref<const L *>,
217             transposed_row_ref< L *>, PT>::return_type return_type;
218   };
219   template <typename PT> struct transposed_return_<col_major, PT> {
220     typedef typename std::iterator_traits<PT>::value_type L;
221     typedef typename select_return<transposed_col_ref<const L *>,
222             transposed_col_ref< L *>, PT>::return_type return_type;
223   };
224   template <typename PT> struct transposed_return {
225     typedef typename std::iterator_traits<PT>::value_type L;
226     typedef typename transposed_return_<typename principal_orientation_type<
227             typename linalg_traits<L>::sub_orientation>::potype,
228 	    PT>::return_type return_type;
229   };
230 
231   template <typename L> inline
232   typename transposed_return<const L *>::return_type transposed(const L &l) {
233     return typename transposed_return<const L *>::return_type
234       (linalg_cast(const_cast<L &>(l)));
235   }
236 
237   template <typename L> inline
238   typename transposed_return<L *>::return_type transposed(L &l)
239   { return typename transposed_return<L *>::return_type(linalg_cast(l)); }
240 
241 }
242 
243 #endif //  GMM_TRANSPOSED_H__
244