1 // -*- c++ -*- (enables emacs c++ mode)
2 //===========================================================================
3 //
4 // Copyright (C) 2003-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_conjugated.h
32    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
33    @date September 18, 2003.
34    @brief handle conjugation of complex matrices/vectors.
35 */
36 #ifndef GMM_CONJUGATED_H__
37 #define GMM_CONJUGATED_H__
38 
39 #include "gmm_def.h"
40 
41 namespace gmm {
42   ///@cond DOXY_SHOW_ALL_FUNCTIONS
43 
44   /* ********************************************************************* */
45   /*		Conjugated references on vectors            		   */
46   /* ********************************************************************* */
47 
48   template <typename IT> struct conjugated_const_iterator {
49     typedef typename std::iterator_traits<IT>::value_type      value_type;
50     typedef typename std::iterator_traits<IT>::pointer         pointer;
51     typedef typename std::iterator_traits<IT>::reference       reference;
52     typedef typename std::iterator_traits<IT>::difference_type difference_type;
53     typedef typename std::iterator_traits<IT>::iterator_category
54     iterator_category;
55 
56     IT it;
57 
conjugated_const_iteratorconjugated_const_iterator58     conjugated_const_iterator(void) {}
conjugated_const_iteratorconjugated_const_iterator59     conjugated_const_iterator(const IT &i) : it(i) {}
60 
indexconjugated_const_iterator61     inline size_type index(void) const { return it.index(); }
62     conjugated_const_iterator operator ++(int)
63     { conjugated_const_iterator tmp = *this; ++it; return tmp; }
64     conjugated_const_iterator operator --(int)
65     { conjugated_const_iterator tmp = *this; --it; return tmp; }
66     conjugated_const_iterator &operator ++() { ++it; return *this; }
67     conjugated_const_iterator &operator --() { --it; return *this; }
68     conjugated_const_iterator &operator +=(difference_type i)
69       { it += i; return *this; }
70     conjugated_const_iterator &operator -=(difference_type i)
71       { it -= i; return *this; }
72     conjugated_const_iterator operator +(difference_type i) const
73       { conjugated_const_iterator itb = *this; return (itb += i); }
74     conjugated_const_iterator operator -(difference_type i) const
75       { conjugated_const_iterator itb = *this; return (itb -= i); }
76     difference_type operator -(const conjugated_const_iterator &i) const
77       { return difference_type(it - i.it); }
78 
79     value_type operator  *() const { return gmm::conj(*it); }
80     value_type operator [](size_type ii) const { return gmm::conj(it[ii]); }
81 
82     bool operator ==(const conjugated_const_iterator &i) const
83       { return (i.it == it); }
84     bool operator !=(const conjugated_const_iterator &i) const
85       { return (i.it != it); }
86     bool operator < (const conjugated_const_iterator &i) const
87       { return (it < i.it); }
88   };
89 
90   template <typename V> struct conjugated_vector_const_ref {
91     typedef conjugated_vector_const_ref<V> this_type;
92     typedef typename linalg_traits<V>::value_type value_type;
93     typedef typename linalg_traits<V>::const_iterator iterator;
94     typedef typename linalg_traits<this_type>::reference reference;
95     typedef typename linalg_traits<this_type>::origin_type origin_type;
96 
97     iterator begin_, end_;
98     const origin_type *origin;
99     size_type size_;
100 
conjugated_vector_const_refconjugated_vector_const_ref101     conjugated_vector_const_ref(const V &v)
102       : begin_(vect_const_begin(v)), end_(vect_const_end(v)),
103 	origin(linalg_origin(v)),
104 	size_(vect_size(v)) {}
105 
106     reference operator[](size_type i) const
107     { return gmm::conj(linalg_traits<V>::access(origin, begin_, end_, i)); }
108   };
109 
110   template <typename V> struct linalg_traits<conjugated_vector_const_ref<V> > {
111     typedef conjugated_vector_const_ref<V> this_type;
112     typedef typename linalg_traits<V>::origin_type origin_type;
113     typedef linalg_const is_reference;
114     typedef abstract_vector linalg_type;
115     typedef typename linalg_traits<V>::value_type value_type;
116     typedef value_type reference;
117     typedef abstract_null_type iterator;
118     typedef conjugated_const_iterator<typename
119                    linalg_traits<V>::const_iterator> const_iterator;
120     typedef typename linalg_traits<V>::storage_type storage_type;
121     typedef typename linalg_traits<V>::index_sorted index_sorted;
122     static size_type size(const this_type &v) { return v.size_; }
123     static iterator begin(this_type &v) { return iterator(v.begin_); }
124     static const_iterator begin(const this_type &v)
125     { return const_iterator(v.begin_); }
126     static iterator end(this_type &v)
127     { return iterator(v.end_); }
128     static const_iterator end(const this_type &v)
129     { return const_iterator(v.end_); }
130     static value_type access(const origin_type *o, const const_iterator &it,
131 			     const const_iterator &ite, size_type i)
132     { return gmm::conj(linalg_traits<V>::access(o, it.it, ite.it, i)); }
133     static const origin_type* origin(const this_type &v) { return v.origin; }
134   };
135 
136   template<typename V> std::ostream &operator <<
137     (std::ostream &o, const conjugated_vector_const_ref<V>& m)
138   { gmm::write(o,m); return o; }
139 
140   /* ********************************************************************* */
141   /*		Conjugated references on matrices            		   */
142   /* ********************************************************************* */
143 
144   template <typename M> struct conjugated_row_const_iterator {
145     typedef conjugated_row_const_iterator<M> iterator;
146     typedef typename linalg_traits<M>::const_row_iterator ITER;
147     typedef typename linalg_traits<M>::value_type value_type;
148     typedef ptrdiff_t difference_type;
149     typedef size_t size_type;
150 
151     ITER it;
152 
153     iterator operator ++(int) { iterator tmp = *this; it++; return tmp; }
154     iterator operator --(int) { iterator tmp = *this; it--; return tmp; }
155     iterator &operator ++()   { it++; return *this; }
156     iterator &operator --()   { it--; return *this; }
157     iterator &operator +=(difference_type i) { it += i; return *this; }
158     iterator &operator -=(difference_type i) { it -= i; return *this; }
159     iterator operator +(difference_type i) const
160     { iterator itt = *this; return (itt += i); }
161     iterator operator -(difference_type i) const
162     { iterator itt = *this; return (itt -= i); }
163     difference_type operator -(const iterator &i) const
164     { return it - i.it; }
165 
166     ITER operator *() const { return it; }
167     ITER operator [](int i) { return it + i; }
168 
169     bool operator ==(const iterator &i) const { return (it == i.it); }
170     bool operator !=(const iterator &i) const { return !(i == *this); }
171     bool operator < (const iterator &i) const { return (it < i.it); }
172 
173     conjugated_row_const_iterator(void) {}
174     conjugated_row_const_iterator(const ITER &i) : it(i) { }
175 
176   };
177 
178   template <typename M> struct  conjugated_row_matrix_const_ref {
179 
180     typedef conjugated_row_matrix_const_ref<M> this_type;
181     typedef typename linalg_traits<M>::const_row_iterator iterator;
182     typedef typename linalg_traits<M>::value_type value_type;
183     typedef typename linalg_traits<this_type>::origin_type origin_type;
184 
185     iterator begin_, end_;
186     const origin_type *origin;
187     size_type nr, nc;
188 
189     conjugated_row_matrix_const_ref(const M &m)
190       : begin_(mat_row_begin(m)), end_(mat_row_end(m)),
191 	origin(linalg_origin(m)), nr(mat_ncols(m)), nc(mat_nrows(m)) {}
192 
193     value_type operator()(size_type i, size_type j) const
194     { return gmm::conj(linalg_traits<M>::access(begin_+j, i)); }
195   };
196 
197   template <typename M>
198   struct linalg_traits<conjugated_row_matrix_const_ref<M> > {
199     typedef conjugated_row_matrix_const_ref<M> this_type;
200     typedef typename linalg_traits<M>::origin_type origin_type;
201     typedef linalg_const is_reference;
202     typedef abstract_matrix linalg_type;
203     typedef typename linalg_traits<M>::value_type value_type;
204     typedef value_type reference;
205     typedef typename linalg_traits<M>::storage_type storage_type;
206     typedef typename linalg_traits<M>::const_sub_row_type vector_type;
207     typedef conjugated_vector_const_ref<vector_type> sub_col_type;
208     typedef conjugated_vector_const_ref<vector_type> const_sub_col_type;
209     typedef conjugated_row_const_iterator<M> col_iterator;
210     typedef conjugated_row_const_iterator<M> const_col_iterator;
211     typedef abstract_null_type const_sub_row_type;
212     typedef abstract_null_type sub_row_type;
213     typedef abstract_null_type const_row_iterator;
214     typedef abstract_null_type row_iterator;
215     typedef col_major sub_orientation;
216     typedef typename linalg_traits<M>::index_sorted index_sorted;
217     static inline size_type ncols(const this_type &m) { return m.nc; }
218     static inline size_type nrows(const this_type &m) { return m.nr; }
219     static inline const_sub_col_type col(const const_col_iterator &it)
220     { return conjugated(linalg_traits<M>::row(it.it)); }
221     static inline const_col_iterator col_begin(const this_type &m)
222     { return const_col_iterator(m.begin_); }
223     static inline const_col_iterator col_end(const this_type &m)
224     { return const_col_iterator(m.end_); }
225     static inline const origin_type* origin(const this_type &m)
226     { return m.origin; }
227     static value_type access(const const_col_iterator &it, size_type i)
228     { return gmm::conj(linalg_traits<M>::access(it.it, i)); }
229   };
230 
231   template<typename M> std::ostream &operator <<
232   (std::ostream &o, const conjugated_row_matrix_const_ref<M>& m)
233   { gmm::write(o,m); return o; }
234 
235 
236   template <typename M> struct conjugated_col_const_iterator {
237     typedef conjugated_col_const_iterator<M> iterator;
238     typedef typename linalg_traits<M>::const_col_iterator ITER;
239     typedef typename linalg_traits<M>::value_type value_type;
240     typedef ptrdiff_t difference_type;
241     typedef size_t size_type;
242 
243     ITER it;
244 
245     iterator operator ++(int) { iterator tmp = *this; it++; return tmp; }
246     iterator operator --(int) { iterator tmp = *this; it--; return tmp; }
247     iterator &operator ++()   { it++; return *this; }
248     iterator &operator --()   { it--; return *this; }
249     iterator &operator +=(difference_type i) { it += i; return *this; }
250     iterator &operator -=(difference_type i) { it -= i; return *this; }
251     iterator operator +(difference_type i) const
252     { iterator itt = *this; return (itt += i); }
253     iterator operator -(difference_type i) const
254     { iterator itt = *this; return (itt -= i); }
255     difference_type operator -(const iterator &i) const
256     { return it - i.it; }
257 
258     ITER operator *() const { return it; }
259     ITER operator [](int i) { return it + i; }
260 
261     bool operator ==(const iterator &i) const { return (it == i.it); }
262     bool operator !=(const iterator &i) const { return !(i == *this); }
263     bool operator < (const iterator &i) const { return (it < i.it); }
264 
265     conjugated_col_const_iterator(void) {}
266     conjugated_col_const_iterator(const ITER &i) : it(i) { }
267 
268   };
269 
270   template <typename M> struct  conjugated_col_matrix_const_ref {
271 
272     typedef conjugated_col_matrix_const_ref<M> this_type;
273     typedef typename linalg_traits<M>::const_col_iterator iterator;
274     typedef typename linalg_traits<M>::value_type value_type;
275     typedef typename linalg_traits<this_type>::origin_type origin_type;
276 
277     iterator begin_, end_;
278     const origin_type *origin;
279     size_type nr, nc;
280 
281     conjugated_col_matrix_const_ref(const M &m)
282       : begin_(mat_col_begin(m)), end_(mat_col_end(m)),
283 	origin(linalg_origin(m)), nr(mat_ncols(m)), nc(mat_nrows(m)) {}
284 
285     value_type operator()(size_type i, size_type j) const
286     { return gmm::conj(linalg_traits<M>::access(begin_+i, j)); }
287   };
288 
289   template <typename M>
290   struct linalg_traits<conjugated_col_matrix_const_ref<M> > {
291     typedef conjugated_col_matrix_const_ref<M> this_type;
292     typedef typename linalg_traits<M>::origin_type origin_type;
293     typedef linalg_const is_reference;
294     typedef abstract_matrix linalg_type;
295     typedef typename linalg_traits<M>::value_type value_type;
296     typedef value_type reference;
297     typedef typename linalg_traits<M>::storage_type storage_type;
298     typedef typename linalg_traits<M>::const_sub_col_type vector_type;
299     typedef conjugated_vector_const_ref<vector_type> sub_row_type;
300     typedef conjugated_vector_const_ref<vector_type> const_sub_row_type;
301     typedef conjugated_col_const_iterator<M> row_iterator;
302     typedef conjugated_col_const_iterator<M> const_row_iterator;
303     typedef abstract_null_type const_sub_col_type;
304     typedef abstract_null_type sub_col_type;
305     typedef abstract_null_type const_col_iterator;
306     typedef abstract_null_type col_iterator;
307     typedef row_major sub_orientation;
308     typedef typename linalg_traits<M>::index_sorted index_sorted;
309     static inline size_type nrows(const this_type &m) { return m.nr; }
310     static inline size_type ncols(const this_type &m) { return m.nc; }
311     static inline const_sub_row_type row(const const_row_iterator &it)
312     { return conjugated(linalg_traits<M>::col(it.it)); }
313     static inline const_row_iterator row_begin(const this_type &m)
314     { return const_row_iterator(m.begin_); }
315     static inline const_row_iterator row_end(const this_type &m)
316     { return const_row_iterator(m.end_); }
317     static inline const origin_type* origin(const this_type &m)
318     { return m.origin; }
319     static value_type access(const const_row_iterator &it, size_type i)
320     { return gmm::conj(linalg_traits<M>::access(it.it, i)); }
321   };
322 
323   template<typename M> std::ostream &operator <<
324   (std::ostream &o, const conjugated_col_matrix_const_ref<M>& m)
325   { gmm::write(o,m); return o; }
326 
327 
328   template <typename L, typename SO> struct conjugated_return__ {
329     typedef conjugated_row_matrix_const_ref<L> return_type;
330   };
331   template <typename L> struct conjugated_return__<L, col_major> {
332     typedef conjugated_col_matrix_const_ref<L> return_type;
333   };
334   template <typename L, typename T, typename LT> struct conjugated_return_ {
335     typedef const L & return_type;
336   };
337   template <typename L, typename T>
338   struct conjugated_return_<L, std::complex<T>, abstract_vector> {
339     typedef conjugated_vector_const_ref<L> return_type;
340   };
341   template <typename L, typename T>
342   struct conjugated_return_<L, T, abstract_matrix> {
343     typedef typename conjugated_return__<L,
344     typename principal_orientation_type<typename
345     linalg_traits<L>::sub_orientation>::potype
346     >::return_type return_type;
347   };
348   template <typename L> struct conjugated_return {
349     typedef typename
350     conjugated_return_<L, typename linalg_traits<L>::value_type,
351 		       typename linalg_traits<L>::linalg_type
352 		       >::return_type return_type;
353   };
354 
355   ///@endcond
356   /** return a conjugated view of the input matrix or vector. */
357   template <typename L> inline
358   typename conjugated_return<L>::return_type
359   conjugated(const L &v) {
360     return conjugated(v, typename linalg_traits<L>::value_type(),
361 		      typename linalg_traits<L>::linalg_type());
362   }
363   ///@cond DOXY_SHOW_ALL_FUNCTIONS
364 
365   template <typename L, typename T, typename LT> inline
366   const L & conjugated(const L &v, T, LT) { return v; }
367 
368   template <typename L, typename T> inline
369   conjugated_vector_const_ref<L> conjugated(const L &v, std::complex<T>,
370 					    abstract_vector)
371   { return conjugated_vector_const_ref<L>(v); }
372 
373   template <typename L, typename T> inline
374   typename conjugated_return__<L,
375     typename principal_orientation_type<typename
376     linalg_traits<L>::sub_orientation>::potype>::return_type
377   conjugated(const L &v, T, abstract_matrix) {
378     return conjugated(v, typename principal_orientation_type<typename
379 		      linalg_traits<L>::sub_orientation>::potype());
380   }
381 
382   template <typename L> inline
383   conjugated_row_matrix_const_ref<L> conjugated(const L &v, row_major)
384   { return conjugated_row_matrix_const_ref<L>(v); }
385 
386   template <typename L> inline
387   conjugated_col_matrix_const_ref<L> conjugated(const L &v, col_major)
388   { return conjugated_col_matrix_const_ref<L>(v); }
389 
390   ///@endcond
391 
392 
393 }
394 
395 #endif //  GMM_CONJUGATED_H__
396