1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2000-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 
33 #ifndef GMM_REF_H__
34 #define GMM_REF_H__
35 
36 /** @file gmm_ref.h
37    @author  Yves Renard <Yves.Renard@insa-lyon.fr>
38    @date August 26, 2000.
39  *  @brief Provide some simple pseudo-containers.
40  *
41  *  WARNING : modifiying the container infirm the validity of references.
42  */
43 
44 
45 #include <iterator>
46 #include "gmm_except.h"
47 
48 namespace gmm {
49 
50   /* ********************************************************************* */
51   /* Simple reference.                                                     */
52   /* ********************************************************************* */
53 
54   template<typename ITER> class tab_ref {
55 
56     protected :
57 
58       ITER begin_, end_;
59 
60     public :
61 
62       typedef typename std::iterator_traits<ITER>::value_type  value_type;
63       typedef typename std::iterator_traits<ITER>::pointer     pointer;
64       typedef typename std::iterator_traits<ITER>::pointer     const_pointer;
65       typedef typename std::iterator_traits<ITER>::reference   reference;
66       typedef typename std::iterator_traits<ITER>::reference   const_reference;
67       typedef typename std::iterator_traits<ITER>::difference_type
68 	                                                       difference_type;
69       typedef ITER                            iterator;
70       typedef ITER                            const_iterator;
71       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
72       typedef std::reverse_iterator<iterator> reverse_iterator;
73       typedef size_t size_type;
74 
empty(void)75       bool empty(void) const { return begin_ == end_; }
size(void)76       size_type size(void) const { return end_ - begin_; }
77 
begin(void)78       const iterator &begin(void) { return begin_; }
begin(void)79       const const_iterator &begin(void) const { return begin_; }
end(void)80       const iterator &end(void) { return end_; }
end(void)81       const const_iterator &end(void) const { return end_; }
rbegin(void)82       reverse_iterator rbegin(void) { return reverse_iterator(end()); }
rbegin(void)83       const_reverse_iterator rbegin(void) const
84       { return const_reverse_iterator(end()); }
rend(void)85       reverse_iterator rend(void) { return reverse_iterator(begin()); }
rend(void)86       const_reverse_iterator rend(void) const
87       { return const_reverse_iterator(begin()); }
88 
front(void)89       reference front(void) { return *begin(); }
front(void)90       const_reference front(void) const { return *begin(); }
back(void)91       reference back(void) { return *(--(end())); }
back(void)92       const_reference back(void) const { return *(--(end())); }
pop_front(void)93       void pop_front(void) { ++begin_; }
94 
95       const_reference operator [](size_type ii) const { return *(begin_ + ii);}
96       reference operator [](size_type ii) { return *(begin_ + ii); }
97 
tab_ref(void)98       tab_ref(void) {}
tab_ref(const ITER & b,const ITER & e)99       tab_ref(const ITER &b, const ITER &e) : begin_(b), end_(e) {}
100   };
101 
102 
103   /* ********************************************************************* */
104   /* Reference with index.                                                 */
105   /* ********************************************************************* */
106 
107 //   template<typename ITER> struct tab_ref_index_iterator_
108 //     : public dynamic_array<size_t>::const_iterator
109 //   {
110 //     typedef typename std::iterator_traits<ITER>::value_type  value_type;
111 //     typedef typename std::iterator_traits<ITER>::pointer     pointer;
112 //     typedef typename std::iterator_traits<ITER>::reference   reference;
113 //     typedef typename std::iterator_traits<ITER>::difference_type
114 //     difference_type;
115 //     typedef std::random_access_iterator_tag iterator_category;
116 //     typedef size_t size_type;
117 //     typedef dynamic_array<size_type>::const_iterator dnas_iterator_;
118 //     typedef tab_ref_index_iterator_<ITER> iterator;
119 
120 
121 //     ITER piter;
122 
123 //     iterator operator ++(int)
124 //     { iterator tmp = *this; ++(*((dnas_iterator_ *)(this))); return tmp; }
125 //     iterator operator --(int)
126 //     { iterator tmp = *this; --(*((dnas_iterator_ *)(this))); return tmp; }
127 //     iterator &operator ++()
128 //     { ++(*((dnas_iterator_ *)(this))); return *this; }
129 //     iterator &operator --()
130 //     { --(*((dnas_iterator_ *)(this))); return *this; }
131 //     iterator &operator +=(difference_type i)
132 //     { (*((dnas_iterator_ *)(this))) += i; return *this; }
133 //     iterator &operator -=(difference_type i)
134 //     { (*((dnas_iterator_ *)(this))) -= i; return *this; }
135 //     iterator operator +(difference_type i) const
136 //     { iterator it = *this; return (it += i); }
137 //     iterator operator -(difference_type i) const
138 //     { iterator it = *this; return (it -= i); }
139 //     difference_type operator -(const iterator &i) const
140 //     { return *((dnas_iterator_ *)(this)) - *((dnas_iterator_ *)(&i)); }
141 
142 //     reference operator *() const
143 //     { return *(piter + *((*((dnas_iterator_ *)(this))))); }
144 //     reference operator [](int ii)
145 //     { return *(piter + *((*((dnas_iterator_ *)(this+ii))))); }
146 
147 //     bool operator ==(const iterator &i) const
148 //     {
149 //       return ((piter) == ((i.piter))
150 //        && *((dnas_iterator_ *)(this)) == *((*((dnas_iterator_ *)(this)))));
151 //     }
152 //     bool operator !=(const iterator &i) const
153 //     { return !(i == *this); }
154 //     bool operator < (const iterator &i) const
155 //     {
156 //       return ((piter) == ((i.piter))
157 // 	 && *((dnas_iterator_ *)(this)) < *((*((dnas_iterator_ *)(this)))));
158 //     }
159 
160 //     tab_ref_index_iterator_(void) {}
161 //     tab_ref_index_iterator_(const ITER &iter, const dnas_iterator_ &dnas_iter)
162 //       : dnas_iterator_(dnas_iter), piter(iter) {}
163 //   };
164 
165 
166 //   template<typename ITER> class tab_ref_index
167 //   {
168 //     public :
169 
170 //       typedef typename std::iterator_traits<ITER>::value_type value_type;
171 //       typedef typename std::iterator_traits<ITER>::pointer    pointer;
172 //       typedef typename std::iterator_traits<ITER>::pointer    const_pointer;
173 //       typedef typename std::iterator_traits<ITER>::reference  reference;
174 //       typedef typename std::iterator_traits<ITER>::reference  const_reference;
175 //       typedef typename std::iterator_traits<ITER>::difference_type
176 // 	                                                       difference_type;
177 //       typedef size_t size_type;
178 //       typedef tab_ref_index_iterator_<ITER> iterator;
179 //       typedef iterator                          const_iterator;
180 //       typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
181 //       typedef std::reverse_iterator<iterator> reverse_iterator;
182 
183 //     protected :
184 
185 //       ITER begin_;
186 //       dynamic_array<size_type> index_;
187 
188 //     public :
189 
190 //       bool empty(void) const { return index_.empty(); }
191 //       size_type size(void) const { return index_.size(); }
192 
193 
194 //       iterator begin(void) { return iterator(begin_, index_.begin()); }
195 //       const_iterator begin(void) const
196 //       { return iterator(begin_, index_.begin()); }
197 //       iterator end(void) { return iterator(begin_, index_.end()); }
198 //       const_iterator end(void) const { return iterator(begin_, index_.end()); }
199 //       reverse_iterator rbegin(void) { return reverse_iterator(end()); }
200 //       const_reverse_iterator rbegin(void) const
201 //       { return const_reverse_iterator(end()); }
202 //       reverse_iterator rend(void) { return reverse_iterator(begin()); }
203 //       const_reverse_iterator rend(void) const
204 //       { return const_reverse_iterator(begin()); }
205 
206 
207 //       reference front(void) { return *(begin_ +index_[0]); }
208 //       const_reference front(void) const { return *(begin_ +index_[0]); }
209 //       reference back(void) { return *(--(end())); }
210 //       const_reference back(void) const { return *(--(end())); }
211 
212 //       tab_ref_index(void) {}
213 //       tab_ref_index(const ITER &b, const dynamic_array<size_type> &ind)
214 //       { begin_ = b; index_ = ind; }
215 
216 //     // to be changed in a const_reference ?
217 //       value_type operator [](size_type ii) const
218 //       { return *(begin_ + index_[ii]);}
219 //       reference operator [](size_type ii) { return *(begin_ + index_[ii]); }
220 
221 //   };
222 
223 
224   /// iterator over a gmm::tab_ref_index_ref<ITER,ITER_INDEX>
225   template<typename ITER, typename ITER_INDEX>
226     struct tab_ref_index_ref_iterator_
227     {
228       typedef typename std::iterator_traits<ITER>::value_type value_type;
229       typedef typename std::iterator_traits<ITER>::pointer    pointer;
230       typedef typename std::iterator_traits<ITER>::reference  reference;
231       typedef typename std::iterator_traits<ITER>::difference_type
232                                                               difference_type;
233       typedef std::random_access_iterator_tag iterator_category;
234       typedef tab_ref_index_ref_iterator_<ITER, ITER_INDEX> iterator;
235       typedef size_t size_type;
236 
237       ITER piter;
238       ITER_INDEX iter_index;
239 
240       iterator operator ++(int)
241       { iterator tmp = *this; ++iter_index; return tmp; }
242       iterator operator --(int)
243       { iterator tmp = *this; --iter_index; return tmp; }
244       iterator &operator ++() { ++iter_index; return *this; }
245       iterator &operator --() { --iter_index; return *this; }
246       iterator &operator +=(difference_type i)
247       { iter_index += i; return *this; }
248       iterator &operator -=(difference_type i)
249       { iter_index -= i; return *this; }
250       iterator operator +(difference_type i) const
251       { iterator it = *this; return (it += i); }
252       iterator operator -(difference_type i) const
253       { iterator it = *this; return (it -= i); }
254       difference_type operator -(const iterator &i) const
255       { return iter_index - i.iter_index; }
256 
257       reference operator *() const
258       { return *(piter + *iter_index); }
259       reference operator [](size_type ii) const
260       { return *(piter + *(iter_index+ii)); }
261 
262       bool operator ==(const iterator &i) const
263       { return ((piter) == ((i.piter)) && iter_index == i.iter_index); }
264       bool operator !=(const iterator &i) const { return !(i == *this); }
265       bool operator < (const iterator &i) const
266       { return ((piter) == ((i.piter)) && iter_index < i.iter_index); }
267 
tab_ref_index_ref_iterator_tab_ref_index_ref_iterator_268       tab_ref_index_ref_iterator_(void) {}
tab_ref_index_ref_iterator_tab_ref_index_ref_iterator_269       tab_ref_index_ref_iterator_(const ITER &iter,
270 				  const ITER_INDEX &dnas_iter)
271 	: piter(iter), iter_index(dnas_iter) {}
272 
273     };
274 
275   /**
276       convenience template function for quick obtention of a indexed iterator
277       without having to specify its (long) typename
278   */
279   template<typename ITER, typename ITER_INDEX>
280   tab_ref_index_ref_iterator_<ITER,ITER_INDEX>
index_ref_iterator(ITER it,ITER_INDEX it_i)281   index_ref_iterator(ITER it, ITER_INDEX it_i) {
282     return tab_ref_index_ref_iterator_<ITER,ITER_INDEX>(it, it_i);
283   }
284 
285   /** indexed array reference (given a container X, and a set of indexes I,
286       this class provides a pseudo-container Y such that
287       @code Y[i] = X[I[i]] @endcode
288   */
289   template<typename ITER, typename ITER_INDEX> class tab_ref_index_ref {
290   public :
291 
292     typedef std::iterator_traits<ITER>            traits_type;
293     typedef typename traits_type::value_type      value_type;
294     typedef typename traits_type::pointer         pointer;
295     typedef typename traits_type::pointer         const_pointer;
296     typedef typename traits_type::reference       reference;
297     typedef typename traits_type::reference       const_reference;
298     typedef typename traits_type::difference_type difference_type;
299     typedef size_t                                size_type;
300     typedef tab_ref_index_ref_iterator_<ITER, ITER_INDEX>   iterator;
301     typedef iterator                              const_iterator;
302     typedef std::reverse_iterator<const_iterator>     const_reverse_iterator;
303     typedef std::reverse_iterator<iterator>           reverse_iterator;
304 
305   protected :
306 
307     ITER begin_;
308     ITER_INDEX index_begin_, index_end_;
309 
310   public :
311 
empty(void)312     bool empty(void) const { return index_begin_ == index_end_; }
size(void)313     size_type size(void) const { return index_end_ - index_begin_; }
314 
begin(void)315     iterator begin(void) { return iterator(begin_, index_begin_); }
begin(void)316     const_iterator begin(void) const
317     { return iterator(begin_, index_begin_); }
end(void)318     iterator end(void) { return iterator(begin_, index_end_); }
end(void)319     const_iterator end(void) const { return iterator(begin_, index_end_); }
rbegin(void)320     reverse_iterator rbegin(void) { return reverse_iterator(end()); }
rbegin(void)321     const_reverse_iterator rbegin(void) const
322     { return const_reverse_iterator(end()); }
rend(void)323     reverse_iterator rend(void) { return reverse_iterator(begin()); }
rend(void)324     const_reverse_iterator rend(void) const
325     { return const_reverse_iterator(begin()); }
326 
front(void)327     reference front(void) { return *(begin_ + *index_begin_); }
front(void)328     const_reference front(void) const { return *(begin_ + *index_begin_); }
back(void)329     reference back(void) { return *(--(end())); }
back(void)330     const_reference back(void) const { return *(--(end())); }
pop_front(void)331     void pop_front(void) { ++index_begin_; }
332 
tab_ref_index_ref(void)333     tab_ref_index_ref(void) {}
tab_ref_index_ref(const ITER & b,const ITER_INDEX & bi,const ITER_INDEX & ei)334     tab_ref_index_ref(const ITER &b, const ITER_INDEX &bi,
335 		      const ITER_INDEX &ei)
336       : begin_(b), index_begin_(bi), index_end_(ei) {}
337 
338     // to be changed in a const_reference ?
339     const_reference operator [](size_type ii) const
340     { return *(begin_ + index_begin_[ii]);}
341     reference operator [](size_type ii)
342     { return *(begin_ + index_begin_[ii]); }
343 
344   };
345 
346 
347   /* ********************************************************************* */
348   /* Reference on regularly spaced elements.                               */
349   /* ********************************************************************* */
350 
351   template<typename ITER> struct tab_ref_reg_spaced_iterator_ {
352 
353     typedef typename std::iterator_traits<ITER>::value_type value_type;
354     typedef typename std::iterator_traits<ITER>::pointer    pointer;
355     typedef typename std::iterator_traits<ITER>::reference  reference;
356     typedef typename std::iterator_traits<ITER>::difference_type
357                                                             difference_type;
358     typedef typename std::iterator_traits<ITER>::iterator_category
359                                                             iterator_category;
360     typedef size_t size_type;
361     typedef tab_ref_reg_spaced_iterator_<ITER> iterator;
362 
363     ITER it;
364     size_type N, i;
365 
366     iterator operator ++(int) { iterator tmp = *this; i++; return tmp; }
367     iterator operator --(int) { iterator tmp = *this; i--; return tmp; }
368     iterator &operator ++()   { i++; return *this; }
369     iterator &operator --()   { i--; return *this; }
370     iterator &operator +=(difference_type ii) { i+=ii; return *this; }
371     iterator &operator -=(difference_type ii) { i-=ii; return *this; }
372     iterator operator +(difference_type ii) const
373     { iterator itt = *this; return (itt += ii); }
374     iterator operator -(difference_type ii) const
375     { iterator itt = *this; return (itt -= ii); }
376     difference_type operator -(const iterator &ii) const
377     { return (N ? (it - ii.it) / N : 0) + i - ii.i; }
378 
379     reference operator *() const { return *(it + i*N); }
380     reference operator [](size_type ii) const { return *(it + (i+ii)*N); }
381 
382     bool operator ==(const iterator &ii) const
383     { return (*this - ii) == difference_type(0); }
384     bool operator !=(const iterator &ii) const
385     { return  (*this - ii) != difference_type(0); }
386     bool operator < (const iterator &ii) const
387     { return (*this - ii) < difference_type(0); }
388 
tab_ref_reg_spaced_iterator_tab_ref_reg_spaced_iterator_389     tab_ref_reg_spaced_iterator_(void) {}
tab_ref_reg_spaced_iterator_tab_ref_reg_spaced_iterator_390     tab_ref_reg_spaced_iterator_(const ITER &iter, size_type n, size_type ii)
391       : it(iter), N(n), i(ii) { }
392 
393   };
394 
395   /**
396       convenience template function for quick obtention of a strided iterator
397       without having to specify its (long) typename
398   */
399   template<typename ITER> tab_ref_reg_spaced_iterator_<ITER>
reg_spaced_iterator(ITER it,size_t stride)400   reg_spaced_iterator(ITER it, size_t stride) {
401     return tab_ref_reg_spaced_iterator_<ITER>(it, stride);
402   }
403 
404   /**
405      provide a "strided" view a of container
406   */
407   template<typename ITER> class tab_ref_reg_spaced {
408   public :
409 
410     typedef typename std::iterator_traits<ITER>::value_type value_type;
411     typedef typename std::iterator_traits<ITER>::pointer    pointer;
412     typedef typename std::iterator_traits<ITER>::pointer    const_pointer;
413     typedef typename std::iterator_traits<ITER>::reference  reference;
414     typedef typename std::iterator_traits<ITER>::reference  const_reference;
415     typedef typename std::iterator_traits<ITER>::difference_type
416             difference_type;
417     typedef size_t size_type;
418     typedef tab_ref_reg_spaced_iterator_<ITER> iterator;
419     typedef iterator                          const_iterator;
420     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
421     typedef std::reverse_iterator<iterator> reverse_iterator;
422 
423   protected :
424 
425     ITER begin_;
426     size_type N, size_;
427 
428   public :
429 
empty(void)430     bool empty(void) const { return size_ == 0; }
size(void)431     size_type size(void) const { return size_; }
432 
begin(void)433     iterator begin(void) { return iterator(begin_, N, 0); }
begin(void)434     const_iterator begin(void) const { return iterator(begin_, N, 0); }
end(void)435     iterator end(void) { return iterator(begin_, N, size_); }
end(void)436     const_iterator end(void) const { return iterator(begin_, N, size_); }
rbegin(void)437     reverse_iterator rbegin(void) { return reverse_iterator(end()); }
rbegin(void)438     const_reverse_iterator rbegin(void) const
439     { return const_reverse_iterator(end()); }
rend(void)440     reverse_iterator rend(void) { return reverse_iterator(begin()); }
rend(void)441     const_reverse_iterator rend(void) const
442     { return const_reverse_iterator(begin()); }
443 
front(void)444     reference front(void) { return *begin_; }
front(void)445     const_reference front(void) const { return *begin_; }
back(void)446     reference back(void) { return *(begin_ + N * (size_-1)); }
back(void)447     const_reference back(void) const { return *(begin_ + N * (size_-1)); }
pop_front(void)448     void pop_front(void) { begin_ += N; }
449 
tab_ref_reg_spaced(void)450     tab_ref_reg_spaced(void) {}
tab_ref_reg_spaced(const ITER & b,size_type n,size_type s)451     tab_ref_reg_spaced(const ITER &b, size_type n, size_type s)
452       : begin_(b), N(n), size_(s) {}
453 
454 
455     const_reference operator [](size_type ii) const
456     { return *(begin_ + ii * N);}
457     reference operator [](size_type ii) { return *(begin_ + ii * N); }
458 
459   };
460 
461   /// iterator over a tab_ref_with_selection
462   template<typename ITER, typename COND>
463   struct tab_ref_with_selection_iterator_ : public ITER {
464     typedef typename std::iterator_traits<ITER>::value_type value_type;
465     typedef typename std::iterator_traits<ITER>::pointer    pointer;
466     typedef typename std::iterator_traits<ITER>::reference  reference;
467     typedef typename std::iterator_traits<ITER>::difference_type
468                                                               difference_type;
469     typedef std::forward_iterator_tag iterator_category;
470     typedef tab_ref_with_selection_iterator_<ITER, COND> iterator;
471     const COND cond;
472 
forwardtab_ref_with_selection_iterator_473     void forward(void) { while (!(cond)(*this)) ITER::operator ++(); }
474     iterator &operator ++()
475     { ITER::operator ++(); forward(); return *this; }
476     iterator operator ++(int)
477     { iterator tmp = *this; ++(*this); return tmp; }
478 
tab_ref_with_selection_iterator_tab_ref_with_selection_iterator_479     tab_ref_with_selection_iterator_(void) {}
tab_ref_with_selection_iterator_tab_ref_with_selection_iterator_480     tab_ref_with_selection_iterator_(const ITER &iter, const COND c)
481       : ITER(iter), cond(c) {}
482 
483   };
484 
485   /**
486      given a container X and a predicate P, provide pseudo-container Y
487      of all elements of X such that P(X[i]).
488   */
489   template<typename ITER, typename COND> class tab_ref_with_selection {
490 
491   protected :
492 
493     ITER begin_, end_;
494     COND cond;
495 
496   public :
497 
498     typedef typename std::iterator_traits<ITER>::value_type value_type;
499     typedef typename std::iterator_traits<ITER>::pointer    pointer;
500     typedef typename std::iterator_traits<ITER>::pointer    const_pointer;
501     typedef typename std::iterator_traits<ITER>::reference  reference;
502     typedef typename std::iterator_traits<ITER>::reference  const_reference;
503     typedef size_t  size_type;
504     typedef tab_ref_with_selection_iterator_<ITER, COND> iterator;
505     typedef iterator   const_iterator;
506 
begin(void)507     iterator begin(void) const
508     { iterator it(begin_, cond); it.forward(); return it; }
end(void)509     iterator end(void) const { return iterator(end_, cond); }
empty(void)510     bool empty(void) const { return begin_ == end_; }
511 
front(void)512     value_type front(void) const { return *begin(); }
pop_front(void)513     void pop_front(void) { ++begin_; begin_ = begin(); }
514 
condition(void)515     COND &condition(void) { return cond; }
condition(void)516     const COND &condition(void) const { return cond; }
517 
tab_ref_with_selection(void)518     tab_ref_with_selection(void) {}
tab_ref_with_selection(const ITER & b,const ITER & e,const COND & c)519     tab_ref_with_selection(const ITER &b, const ITER &e, const COND &c)
520       : begin_(b), end_(e), cond(c) { begin_ = begin(); }
521 
522   };
523 
524 }
525 
526 #endif /* GMM_REF_H__  */
527