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