1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2002-2020 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 3 of the License,  or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program  is  distributed  in  the  hope  that it will be useful,  but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You  should  have received a copy of the GNU Lesser General Public License
18  along  with  this program;  if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
20 
21  As a special exception, you  may use  this file  as it is a part of a free
22  software  library  without  restriction.  Specifically,  if   other  files
23  instantiate  templates  or  use macros or inline functions from this file,
24  or  you compile this  file  and  link  it  with other files  to produce an
25  executable, this file  does  not  by itself cause the resulting executable
26  to be covered  by the GNU Lesser General Public License.  This   exception
27  does not  however  invalidate  any  other  reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 
32 /**@file gmm_sub_vector.h
33    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
34    @date October 13, 2002.
35    @brief Generic sub-vectors.
36 */
37 
38 #ifndef GMM_SUB_VECTOR_H__
39 #define GMM_SUB_VECTOR_H__
40 
41 #include "gmm_interface.h"
42 #include "gmm_sub_index.h"
43 
44 namespace gmm {
45 
46   /* ********************************************************************* */
47   /*		sparse sub-vectors                                         */
48   /* ********************************************************************* */
49 
50   template <typename IT, typename MIT, typename SUBI>
51   struct sparse_sub_vector_iterator {
52 
53     IT itb, itbe;
54     SUBI si;
55 
56     typedef std::iterator_traits<IT>                traits_type;
57     typedef typename traits_type::value_type        value_type;
58     typedef typename traits_type::pointer           pointer;
59     typedef typename traits_type::reference         reference;
60     typedef typename traits_type::difference_type   difference_type;
61     typedef std::bidirectional_iterator_tag         iterator_category;
62     typedef size_t                                  size_type;
63     typedef sparse_sub_vector_iterator<IT, MIT, SUBI>    iterator;
64 
indexsparse_sub_vector_iterator65     size_type index(void) const { return si.rindex(itb.index()); }
66     void forward(void);
67     void backward(void);
68     iterator &operator ++()
69     { ++itb; forward(); return *this; }
70     iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; }
71     iterator &operator --()
72     { --itb; backward(); return *this; }
73     iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; }
74     reference operator *() const { return *itb; }
75 
76     bool operator ==(const iterator &i) const { return itb == i.itb; }
77     bool operator !=(const iterator &i) const { return !(i == *this); }
78 
sparse_sub_vector_iteratorsparse_sub_vector_iterator79     sparse_sub_vector_iterator(void) {}
sparse_sub_vector_iteratorsparse_sub_vector_iterator80     sparse_sub_vector_iterator(const IT &it, const IT &ite, const SUBI &s)
81       : itb(it), itbe(ite), si(s) { forward(); }
sparse_sub_vector_iteratorsparse_sub_vector_iterator82     sparse_sub_vector_iterator
83     (const sparse_sub_vector_iterator<MIT, MIT, SUBI> &it)
84       : itb(it.itb), itbe(it.itbe), si(it.si) {}
85     sparse_sub_vector_iterator &operator =
86     (const sparse_sub_vector_iterator<MIT, MIT, SUBI> &it)
87     { itb = it.itb; itbe = it.itbe;  si = it.si; return *this; }
88 
89   };
90 
91   template <typename IT, typename MIT, typename SUBI>
forward(void)92   void  sparse_sub_vector_iterator<IT, MIT, SUBI>::forward(void)
93   { while(itb!=itbe && index()==size_type(-1)) { ++itb; } }
94 
95   template <typename IT, typename MIT, typename SUBI>
backward(void)96   void  sparse_sub_vector_iterator<IT, MIT, SUBI>::backward(void)
97   { while(itb!=itbe && index()==size_type(-1)) --itb; }
98 
99   template <typename PT, typename SUBI> struct sparse_sub_vector {
100     typedef sparse_sub_vector<PT, SUBI> this_type;
101     typedef typename std::iterator_traits<PT>::value_type V;
102     typedef V * CPT;
103     typedef typename select_ref<typename linalg_traits<V>::const_iterator,
104             typename linalg_traits<V>::iterator, PT>::ref_type iterator;
105     typedef typename linalg_traits<this_type>::reference reference;
106     typedef typename linalg_traits<this_type>::porigin_type porigin_type;
107 
108     iterator begin_, end_;
109     porigin_type origin;
110     SUBI si;
111 
sizesparse_sub_vector112     size_type size(void) const { return si.size(); }
113 
114     reference operator[](size_type i) const
115     { return linalg_traits<V>::access(origin, begin_, end_, si.index(i)); }
116 
sparse_sub_vectorsparse_sub_vector117     sparse_sub_vector(V &v, const SUBI &s) : begin_(vect_begin(v)),
118        end_(vect_end(v)), origin(linalg_origin(v)), si(s) {}
sparse_sub_vectorsparse_sub_vector119     sparse_sub_vector(const V &v, const SUBI &s)
120       : begin_(vect_begin(const_cast<V &>(v))),
121        end_(vect_end(const_cast<V &>(v))),
122 	origin(linalg_origin(const_cast<V &>(v))), si(s) {}
sparse_sub_vectorsparse_sub_vector123     sparse_sub_vector() {}
sparse_sub_vectorsparse_sub_vector124     sparse_sub_vector(const sparse_sub_vector<CPT, SUBI> &cr)
125       : begin_(cr.begin_),end_(cr.end_),origin(cr.origin), si(cr.si) {}
126   };
127 
128   template <typename IT, typename MIT, typename SUBI, typename ORG,
129 	    typename PT> inline
set_to_begin(sparse_sub_vector_iterator<IT,MIT,SUBI> & it,ORG o,sparse_sub_vector<PT,SUBI> *,linalg_modifiable)130   void set_to_begin(sparse_sub_vector_iterator<IT, MIT, SUBI> &it,
131 		    ORG o, sparse_sub_vector<PT, SUBI> *,
132 		    linalg_modifiable) {
133     typedef sparse_sub_vector<PT, SUBI> VECT;
134     typedef typename linalg_traits<VECT>::V_reference ref_t;
135     set_to_begin(it.itb, o, typename linalg_traits<VECT>::pV(), ref_t());
136     set_to_end(it.itbe, o, typename linalg_traits<VECT>::pV(), ref_t());
137     it.forward();
138   }
139   template <typename IT, typename MIT, typename SUBI, typename ORG,
140 	    typename PT> inline
set_to_begin(sparse_sub_vector_iterator<IT,MIT,SUBI> & it,ORG o,const sparse_sub_vector<PT,SUBI> *,linalg_modifiable)141   void set_to_begin(sparse_sub_vector_iterator<IT, MIT, SUBI> &it,
142 		    ORG o, const sparse_sub_vector<PT, SUBI> *,
143 		    linalg_modifiable) {
144     typedef sparse_sub_vector<PT, SUBI> VECT;
145     typedef typename linalg_traits<VECT>::V_reference ref_t;
146     set_to_begin(it.itb, o, typename linalg_traits<VECT>::pV(), ref_t());
147     set_to_end(it.itbe, o, typename linalg_traits<VECT>::pV(), ref_t());
148     it.forward();
149   }
150 
151   template <typename IT, typename MIT, typename SUBI, typename ORG,
152 	    typename PT> inline
set_to_end(sparse_sub_vector_iterator<IT,MIT,SUBI> & it,ORG o,sparse_sub_vector<PT,SUBI> *,linalg_modifiable)153   void set_to_end(sparse_sub_vector_iterator<IT, MIT, SUBI> &it,
154 		    ORG o, sparse_sub_vector<PT, SUBI> *, linalg_modifiable) {
155     typedef sparse_sub_vector<PT, SUBI> VECT;
156     typedef typename linalg_traits<VECT>::V_reference ref_t;
157     set_to_end(it.itb, o, typename linalg_traits<VECT>::pV(), ref_t());
158     set_to_end(it.itbe, o, typename linalg_traits<VECT>::pV(), ref_t());
159     it.forward();
160   }
161   template <typename IT, typename MIT, typename SUBI, typename ORG,
162 	    typename PT> inline
set_to_end(sparse_sub_vector_iterator<IT,MIT,SUBI> & it,ORG o,const sparse_sub_vector<PT,SUBI> *,linalg_modifiable)163   void set_to_end(sparse_sub_vector_iterator<IT, MIT, SUBI> &it,
164 		    ORG o, const sparse_sub_vector<PT, SUBI> *,
165 		  linalg_modifiable) {
166     typedef sparse_sub_vector<PT, SUBI> VECT;
167     typedef typename linalg_traits<VECT>::V_reference ref_t;
168     set_to_end(it.itb, o, typename linalg_traits<VECT>::pV(), ref_t());
169     set_to_end(it.itbe, o, typename linalg_traits<VECT>::pV(), ref_t());
170     it.forward();
171   }
172 
173   template <typename PT, typename SUBI>
174   struct linalg_traits<sparse_sub_vector<PT, SUBI> > {
175     typedef sparse_sub_vector<PT, SUBI> this_type;
176     typedef this_type * pthis_type;
177     typedef PT pV;
178     typedef typename std::iterator_traits<PT>::value_type V;
179     typedef typename linalg_and<typename index_is_sorted<SUBI>::bool_type,
180 	    typename linalg_traits<V>::index_sorted>::bool_type index_sorted;
181     typedef typename linalg_traits<V>::is_reference V_reference;
182     typedef typename linalg_traits<V>::origin_type origin_type;
183     typedef typename select_ref<const origin_type *, origin_type *,
184 			        PT>::ref_type porigin_type;
185     typedef typename which_reference<PT>::is_reference is_reference;
186     typedef abstract_vector linalg_type;
187     typedef typename linalg_traits<V>::value_type value_type;
188     typedef typename select_ref<value_type, typename
189             linalg_traits<V>::reference, PT>::ref_type reference;
190     typedef typename select_ref<typename linalg_traits<V>::const_iterator,
191 	    typename linalg_traits<V>::iterator, PT>::ref_type pre_iterator;
192     typedef typename select_ref<abstract_null_type,
193 	    sparse_sub_vector_iterator<pre_iterator, pre_iterator, SUBI>,
194 	    PT>::ref_type iterator;
195     typedef sparse_sub_vector_iterator<typename linalg_traits<V>
196             ::const_iterator, pre_iterator, SUBI> const_iterator;
197     typedef abstract_sparse storage_type;
198     static size_type size(const this_type &v) { return v.size(); }
199     static iterator begin(this_type &v) {
200       iterator it;
201       it.itb = v.begin_; it.itbe = v.end_; it.si = v.si;
202       if (!is_const_reference(is_reference()))
203 	set_to_begin(it, v.origin, pthis_type(), is_reference());
204       else it.forward();
205       return it;
206     }
207     static const_iterator begin(const this_type &v) {
208       const_iterator it; it.itb = v.begin_; it.itbe = v.end_; it.si = v.si;
209       if (!is_const_reference(is_reference()))
210 	{ set_to_begin(it, v.origin, pthis_type(), is_reference()); }
211       else it.forward();
212       return it;
213     }
214     static iterator end(this_type &v) {
215       iterator it;
216       it.itb = v.end_; it.itbe = v.end_; it.si = v.si;
217       if (!is_const_reference(is_reference()))
218 	set_to_end(it, v.origin, pthis_type(), is_reference());
219       else it.forward();
220       return it;
221     }
222     static const_iterator end(const this_type &v) {
223       const_iterator it; it.itb = v.end_; it.itbe = v.end_; it.si = v.si;
224       if (!is_const_reference(is_reference()))
225 	set_to_end(it, v.origin, pthis_type(), is_reference());
226       else it.forward();
227       return it;
228     }
229     static origin_type* origin(this_type &v) { return v.origin; }
230     static const origin_type* origin(const this_type &v) { return v.origin; }
231     static void clear(origin_type* o, const iterator &begin_,
232 		      const iterator &end_) {
233       std::deque<size_type> ind;
234       iterator it = begin_;
235       for (; it != end_; ++it) ind.push_front(it.index());
236       for (; !(ind.empty()); ind.pop_back())
237 	access(o, begin_, end_, ind.back()) = value_type(0);
238     }
239     static void do_clear(this_type &v) { clear(v.origin, begin(v), end(v)); }
240     static value_type access(const origin_type *o, const const_iterator &it,
241 			     const const_iterator &ite, size_type i)
242     { return linalg_traits<V>::access(o, it.itb, ite.itb, it.si.index(i)); }
243     static reference access(origin_type *o, const iterator &it,
244 			    const iterator &ite, size_type i)
245     { return linalg_traits<V>::access(o, it.itb, ite.itb, it.si.index(i)); }
246   };
247 
248   template <typename PT, typename SUBI> std::ostream &operator <<
249   (std::ostream &o, const sparse_sub_vector<PT, SUBI>& m)
250   { gmm::write(o,m); return o; }
251 
252   /* ********************************************************************* */
253   /*		skyline sub-vectors                                        */
254   /* ********************************************************************* */
255 
256     template <typename IT, typename MIT, typename SUBI>
257   struct skyline_sub_vector_iterator {
258 
259     IT itb;
260     SUBI si;
261 
262     typedef std::iterator_traits<IT>                traits_type;
263     typedef typename traits_type::value_type        value_type;
264     typedef typename traits_type::pointer           pointer;
265     typedef typename traits_type::reference         reference;
266     typedef typename traits_type::difference_type   difference_type;
267     typedef std::bidirectional_iterator_tag         iterator_category;
268     typedef size_t                                  size_type;
269     typedef skyline_sub_vector_iterator<IT, MIT, SUBI>    iterator;
270 
271     size_type index(void) const
272     { return (itb.index() - si.min + si.step() - 1) / si.step(); }
273     void backward(void);
274     iterator &operator ++()
275     { itb += si.step(); return *this; }
276     iterator operator ++(int) { iterator tmp = *this; ++(*this); return tmp; }
277     iterator &operator --()
278     { itb -= si.step(); return *this; }
279     iterator operator --(int) { iterator tmp = *this; --(*this); return tmp; }
280 
281     iterator &operator +=(difference_type i)
282     { itb += si.step() * i; return *this; }
283     iterator &operator -=(difference_type i)
284     { itb -= si.step() * i; return *this; }
285     iterator operator +(difference_type i) const
286     { iterator ii = *this; return (ii += i); }
287     iterator operator -(difference_type i) const
288     { iterator ii = *this; return (ii -= i); }
289     difference_type operator -(const iterator &i) const
290     { return (itb - i.itb) / si.step(); }
291 
292     reference operator *() const  { return *itb; }
293     reference operator [](int ii) { return *(itb + ii * si.step());  }
294 
295     bool operator ==(const iterator &i) const { return index() == i.index();}
296     bool operator !=(const iterator &i) const { return !(i == *this); }
297     bool operator < (const iterator &i) const { return index()  < i.index();}
298 
299     skyline_sub_vector_iterator(void) {}
300     skyline_sub_vector_iterator(const IT &it, const SUBI &s)
301       : itb(it), si(s) {}
302     skyline_sub_vector_iterator(const skyline_sub_vector_iterator<MIT, MIT,
303 	 SUBI> &it) : itb(it.itb), si(it.si) {}
304   };
305 
306   template <typename IT, typename SUBI>
307   void update_for_sub_skyline(IT &it, IT &ite, const SUBI &si) {
308     if (it.index() >= si.max || ite.index() <= si.min) { it = ite; return; }
309     ptrdiff_t dec1 = si.min - it.index(), dec2 = ite.index() - si.max;
310     it  += (dec1 < 0) ? ((si.step()-((-dec1) % si.step())) % si.step()) : dec1;
311     ite -= (dec2 < 0) ? -((-dec2) % si.step()) : dec2;
312   }
313 
314   template <typename PT, typename SUBI> struct skyline_sub_vector {
315     typedef skyline_sub_vector<PT, SUBI> this_type;
316     typedef typename std::iterator_traits<PT>::value_type V;
317     typedef V * pV;
318     typedef typename select_ref<typename linalg_traits<V>::const_iterator,
319             typename linalg_traits<V>::iterator, PT>::ref_type iterator;
320     typedef typename linalg_traits<this_type>::reference reference;
321     typedef typename linalg_traits<this_type>::porigin_type porigin_type;
322 
323     iterator begin_, end_;
324     porigin_type origin;
325     SUBI si;
326 
327     size_type size(void) const { return si.size(); }
328 
329     reference operator[](size_type i) const
330     { return linalg_traits<V>::access(origin, begin_, end_, si.index(i)); }
331 
332     skyline_sub_vector(V &v, const SUBI &s) : begin_(vect_begin(v)),
333        end_(vect_end(v)), origin(linalg_origin(v)), si(s) {
334       update_for_sub_skyline(begin_, end_, si);
335     }
336     skyline_sub_vector(const V &v, const SUBI &s)
337       : begin_(vect_begin(const_cast<V &>(v))),
338 	end_(vect_end(const_cast<V &>(v))),
339 	origin(linalg_origin(const_cast<V &>(v))), si(s) {
340       update_for_sub_skyline(begin_, end_, si);
341     }
342     skyline_sub_vector() {}
343     skyline_sub_vector(const skyline_sub_vector<pV, SUBI> &cr)
344       : begin_(cr.begin_),end_(cr.end_),origin(cr.origin), si(cr.si) {}
345   };
346 
347   template <typename IT, typename MIT, typename SUBI, typename ORG,
348 	    typename PT> inline
349   void set_to_begin(skyline_sub_vector_iterator<IT, MIT, SUBI> &it,
350 		    ORG o, skyline_sub_vector<PT, SUBI> *,
351 		    linalg_modifiable) {
352     typedef skyline_sub_vector<PT, SUBI> VECT;
353     typedef typename linalg_traits<VECT>::V_reference ref_t;
354     IT itbe = it.itb;
355     set_to_begin(it.itb, o, typename linalg_traits<VECT>::pV(), ref_t());
356     set_to_end(itbe, o, typename linalg_traits<VECT>::pV(), ref_t());
357     update_for_sub_skyline(it.itb, itbe, it.si);
358   }
359   template <typename IT, typename MIT, typename SUBI, typename ORG,
360 	    typename PT> inline
361   void set_to_begin(skyline_sub_vector_iterator<IT, MIT, SUBI> &it,
362 		    ORG o, const skyline_sub_vector<PT, SUBI> *,
363 		    linalg_modifiable) {
364     typedef skyline_sub_vector<PT, SUBI> VECT;
365     typedef typename linalg_traits<VECT>::V_reference ref_t;
366     IT itbe = it.itb;
367     set_to_begin(it.itb, o, typename linalg_traits<VECT>::pV(), ref_t());
368     set_to_end(itbe, o, typename linalg_traits<VECT>::pV(), ref_t());
369     update_for_sub_skyline(it.itb, itbe, it.si);
370   }
371 
372   template <typename IT, typename MIT, typename SUBI, typename ORG,
373 	    typename PT> inline
374   void set_to_end(skyline_sub_vector_iterator<IT, MIT, SUBI> &it,
375 		    ORG o, skyline_sub_vector<PT, SUBI> *,
376 		  linalg_modifiable) {
377     typedef skyline_sub_vector<PT, SUBI> VECT;
378     typedef typename linalg_traits<VECT>::V_reference ref_t;
379     IT itb = it.itb;
380     set_to_begin(itb, o, typename linalg_traits<VECT>::pV(), ref_t());
381     set_to_end(it.itb, o, typename linalg_traits<VECT>::pV(), ref_t());
382     update_for_sub_skyline(itb, it.itb, it.si);
383   }
384   template <typename IT, typename MIT, typename SUBI, typename ORG,
385 	    typename PT> inline
386   void set_to_end(skyline_sub_vector_iterator<IT, MIT, SUBI> &it,
387 		    ORG o, const skyline_sub_vector<PT, SUBI> *,
388 		  linalg_modifiable) {
389     typedef skyline_sub_vector<PT, SUBI> VECT;
390     typedef typename linalg_traits<VECT>::V_reference ref_t;
391     IT itb = it.itb;
392     set_to_begin(itb, o, typename linalg_traits<VECT>::pV(), ref_t());
393     set_to_end(it.itb, o, typename linalg_traits<VECT>::pV(), ref_t());
394     update_for_sub_skyline(itb, it.itb, it.si);
395   }
396 
397 
398   template <typename PT, typename SUBI>
399   struct linalg_traits<skyline_sub_vector<PT, SUBI> > {
400     typedef skyline_sub_vector<PT, SUBI> this_type;
401     typedef this_type *pthis_type;
402     typedef typename std::iterator_traits<PT>::value_type V;
403     typedef typename linalg_traits<V>::is_reference V_reference;
404     typedef typename linalg_traits<V>::origin_type origin_type;
405     typedef typename select_ref<const origin_type *, origin_type *,
406 			        PT>::ref_type porigin_type;
407     typedef V * pV;
408     typedef typename which_reference<PT>::is_reference is_reference;
409     typedef abstract_vector linalg_type;
410     typedef typename linalg_traits<V>::value_type value_type;
411     typedef typename select_ref<value_type, typename
412             linalg_traits<V>::reference, PT>::ref_type reference;
413     typedef typename linalg_traits<V>::const_iterator const_V_iterator;
414     typedef typename linalg_traits<V>::iterator V_iterator;
415     typedef typename select_ref<const_V_iterator, V_iterator,
416 				PT>::ref_type pre_iterator;
417     typedef typename select_ref<abstract_null_type,
418 	    skyline_sub_vector_iterator<pre_iterator, pre_iterator, SUBI>,
419 	    PT>::ref_type iterator;
420     typedef skyline_sub_vector_iterator<const_V_iterator, pre_iterator, SUBI>
421             const_iterator;
422     typedef abstract_skyline storage_type;
423     typedef linalg_true index_sorted;
424     static size_type size(const this_type &v) { return v.size(); }
425     static iterator begin(this_type &v) {
426       iterator it;
427       it.itb = v.begin_; it.si = v.si;
428       if (!is_const_reference(is_reference()))
429 	set_to_begin(it, v.origin, pthis_type(), is_reference());
430       return it;
431     }
432     static const_iterator begin(const this_type &v) {
433       const_iterator it; it.itb = v.begin_; it.si = v.si;
434       if (!is_const_reference(is_reference()))
435 	{ set_to_begin(it, v.origin, pthis_type(), is_reference()); }
436       return it;
437     }
438     static iterator end(this_type &v) {
439       iterator it;
440       it.itb = v.end_; it.si = v.si;
441       if (!is_const_reference(is_reference()))
442 	set_to_end(it, v.origin, pthis_type(), is_reference());
443       return it;
444     }
445     static const_iterator end(const this_type &v) {
446       const_iterator it; it.itb = v.end_; it.si = v.si;
447       if (!is_const_reference(is_reference()))
448 	set_to_end(it, v.origin, pthis_type(), is_reference());
449       return it;
450     }
451     static origin_type* origin(this_type &v) { return v.origin; }
452     static const origin_type* origin(const this_type &v) { return v.origin; }
453     static void clear(origin_type*, const iterator &it, const iterator &ite)
454     { std::fill(it, ite, value_type(0)); }
455     static void do_clear(this_type &v) { clear(v.origin, begin(v), end(v)); }
456     static value_type access(const origin_type *o, const const_iterator &it,
457 			     const const_iterator &ite, size_type i)
458     { return linalg_traits<V>::access(o, it.itb, ite.itb, it.si.index(i)); }
459     static reference access(origin_type *o, const iterator &it,
460 			    const iterator &ite, size_type i)
461     { return linalg_traits<V>::access(o, it.itb, ite.itb, it.si.index(i)); }
462   };
463 
464   template <typename PT, typename SUBI> std::ostream &operator <<
465   (std::ostream &o, const skyline_sub_vector<PT, SUBI>& m)
466   { gmm::write(o,m); return o; }
467 
468   /* ******************************************************************** */
469   /*		sub vector.                                               */
470   /* ******************************************************************** */
471   /* sub_vector_type<PT, SUBI>::vector_type is the sub vector type        */
472   /* returned by sub_vector(v, sub_index)                                 */
473   /************************************************************************/
474 
475   template <typename PT, typename SUBI, typename st_type> struct svrt_ir {
476     typedef abstract_null_type vector_type;
477   };
478 
479   template <typename PT>
480   struct svrt_ir<PT, sub_index, abstract_dense> {
481     typedef typename std::iterator_traits<PT>::value_type V;
482     typedef typename vect_ref_type<PT,  V>::iterator iterator;
483     typedef tab_ref_index_ref_with_origin<iterator,
484       sub_index::const_iterator, V> vector_type;
485   };
486 
487   template <typename PT>
488   struct svrt_ir<PT, unsorted_sub_index, abstract_dense> {
489     typedef typename std::iterator_traits<PT>::value_type V;
490     typedef typename vect_ref_type<PT,  V>::iterator iterator;
491     typedef tab_ref_index_ref_with_origin<iterator,
492       unsorted_sub_index::const_iterator, V> vector_type;
493   };
494 
495   template <typename PT>
496   struct svrt_ir<PT, sub_interval, abstract_dense> {
497     typedef typename std::iterator_traits<PT>::value_type V;
498     typedef typename vect_ref_type<PT,  V>::iterator iterator;
499     typedef tab_ref_with_origin<iterator, V> vector_type;
500   };
501 
502   template <typename PT>
503   struct svrt_ir<PT, sub_slice, abstract_dense> {
504     typedef typename std::iterator_traits<PT>::value_type V;
505     typedef typename vect_ref_type<PT,  V>::iterator iterator;
506     typedef tab_ref_reg_spaced_with_origin<iterator, V> vector_type;
507   };
508 
509   template <typename PT, typename SUBI>
510   struct svrt_ir<PT, SUBI, abstract_skyline> {
511     typedef skyline_sub_vector<PT, SUBI> vector_type;
512   };
513 
514   template <typename PT>
515   struct svrt_ir<PT, sub_index, abstract_skyline> {
516     typedef sparse_sub_vector<PT, sub_index> vector_type;
517   };
518 
519   template <typename PT>
520   struct svrt_ir<PT, unsorted_sub_index, abstract_skyline> {
521     typedef sparse_sub_vector<PT, unsorted_sub_index> vector_type;
522   };
523 
524 
525   template <typename PT, typename SUBI>
526   struct svrt_ir<PT, SUBI, abstract_sparse> {
527     typedef sparse_sub_vector<PT, SUBI> vector_type;
528   };
529 
530   template <typename PT, typename SUBI>
531   struct sub_vector_type {
532     typedef typename std::iterator_traits<PT>::value_type V;
533     typedef typename svrt_ir<PT, SUBI,
534       typename linalg_traits<V>::storage_type>::vector_type vector_type;
535   };
536 
537   template <typename V, typename SUBI>
538   typename select_return<
539     typename sub_vector_type<const V *, SUBI>::vector_type,
540     typename sub_vector_type<V *, SUBI>::vector_type, const V *>::return_type
541   sub_vector(const V &v, const SUBI &si) {
542     GMM_ASSERT2(si.last() <= vect_size(v),
543                 "sub vector too large, " << si.last() << " > " << vect_size(v));
544     return typename select_return<
545       typename sub_vector_type<const V *, SUBI>::vector_type,
546       typename sub_vector_type<V *, SUBI>::vector_type, const V *>::return_type
547       (linalg_cast(v), si);
548   }
549 
550   template <typename V, typename SUBI>
551   typename select_return<
552     typename sub_vector_type<const V *, SUBI>::vector_type,
553     typename sub_vector_type<V *, SUBI>::vector_type, V *>::return_type
554   sub_vector(V &v, const SUBI &si) {
555     GMM_ASSERT2(si.last() <= vect_size(v),
556                 "sub vector too large, " << si.last() << " > " << vect_size(v));
557     return  typename select_return<
558       typename sub_vector_type<const V *, SUBI>::vector_type,
559       typename sub_vector_type<V *, SUBI>::vector_type, V *>::return_type
560       (linalg_cast(v), si);
561   }
562 
563 }
564 
565 #endif //  GMM_SUB_VECTOR_H__
566