G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsKnotIterator.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 namespace gismo {
17 
18 namespace internal {
19 
20  template<typename T> class gsKnotIterator;
21 
29 template <typename T>
30 class gsUKnotIterator
31 {
32 public:
33  friend class gsKnotVector<T>;
34  friend class gsKnotIterator<T>;
35 
36  typedef typename gsKnotVector<T>::mult_t mult_t; //index_t, gsKnotVector.h:85
37  typedef std::random_access_iterator_tag iterator_category;
38  typedef const gsKnotVector<T> knotVector;
39  typedef T value_type;
40  typedef std::ptrdiff_t difference_type;
41  typedef const T& reference;
42  typedef const T* pointer;
43  typedef const mult_t* mltpointer;
44 
45 private:
46  mltpointer m_mlt ;
47  pointer m_raw ;
48  mult_t m_upos;
49  mult_t m_sh ;
50 
51 //#if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
52  mult_t m_dbg;// iteration limit: extra member for iterator debugging mode
53 //#endif
54 
55 protected:
56 
57  // Change the value of the knot - access restricted to friend classes
58  // Warning: call GISMO_ASSERT(check()) after using.
59  void setValue(const T val)
60  {
61  std::fill(const_cast<T*>(m_raw) + firstAppearance(),
62  const_cast<T*>(m_raw) + multSum(), val);
63  }
64 
65 public:
66 
71  gsUKnotIterator()
72  : m_mlt(NULL), m_raw(NULL), m_upos(0), m_sh(0), m_dbg(0)
73  { }
74 
84  explicit gsUKnotIterator(knotVector & KV, const mult_t upos = 0, const index_t s = 0)
85  : m_mlt ( KV.multSumData() ), m_raw ( KV.data() ),
86  m_upos( upos ), m_sh (s )
87  {
88  m_dbg = KV.uSize()+1;
89 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
90  //m_dbg = KV.uSize()+1;
91  GISMO_ENSURE(upos < m_dbg, "Invalid iterator position "<< upos
92  <<" for knot vector with "<<KV.uSize()<<" unique knots");
93 # endif
94  }
95 
100  static inline gsUKnotIterator End(knotVector & KV)
101  { // the past-the-end position occurs for upos=KV.uSize()
102  return gsUKnotIterator(KV, KV.uSize(),KV.numLeftGhosts());
103  }
104 
105 public:
106 
108  reference operator* () const
109  {
110 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
111  GISMO_ENSURE(m_upos >= 0 && m_upos + 1 < m_dbg, "Access to invalid knot position.");
112 # endif
113  return m_raw[m_mlt[m_upos]-1];
114  }
115 
116  pointer operator-> () const {return m_raw+m_mlt[m_upos]-1 ;}
117 
118  gsUKnotIterator& operator++()
119  {
120  ++m_upos;
121 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
122  GISMO_ENSURE(m_upos < m_dbg, "Invalid knot-iterator increment: "
123  << m_upos <<" is past the end position ("<<m_dbg-1<<").");
124 # endif
125  return *this;
126  }
127 
128  gsUKnotIterator& operator--()
129  {
130 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
131  GISMO_ENSURE(m_upos > 0 && m_upos < m_dbg, "Invalid knot-iterator decrement");
132 # endif
133  --m_upos;
134  return *this;
135  }
136 
137  gsUKnotIterator operator++(int) { gsUKnotIterator tmp(*this); ++(*this); return tmp; }
138  gsUKnotIterator operator--(int) { gsUKnotIterator tmp(*this); --(*this); return tmp; }
139 
152  bool operator == (const gsUKnotIterator& other) const
153  { return m_upos == other.m_upos;}// && m_raw == other.m_raw;}
154 
167  bool operator != (const gsUKnotIterator& other) const {return m_upos != other.m_upos;}
168  bool operator < (const gsUKnotIterator& other) const {return m_upos < other.m_upos;}
169  bool operator > (const gsUKnotIterator& other) const {return m_upos > other.m_upos;}
170  bool operator <= (const gsUKnotIterator& other) const {return m_upos <= other.m_upos;}
171  bool operator >= (const gsUKnotIterator& other) const {return m_upos >= other.m_upos;}
172 
177  reference operator[] (ptrdiff_t a) const
178  {
179 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
180  GISMO_ENSURE(m_upos+a>=0 && m_upos+a+1 < m_dbg, "Invalid access to non-existent knot.");
181 # endif
182  return m_raw[m_mlt[m_upos+a]-1];
183  }
184 
189  gsUKnotIterator& operator+=(const difference_type & a)
190  {
191  m_upos += a;
192 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
193  // Note: we allow invalid position for iterators on empty knot-vectors
194  GISMO_ENSURE(m_dbg<2 || (m_upos >= 0 && m_upos < m_dbg),
195  "Iterator jumped to invalid knot position.");
196 # endif
197  return *this;
198  }
199 
204  gsUKnotIterator operator+(const difference_type & a) const
205  {
206  gsUKnotIterator tmp(*this);
207  return tmp+=a;
208  }
209 
214  gsUKnotIterator& operator-=(const difference_type & a)
215  {
216  return operator+=(-a);
217  }
218 
223  gsUKnotIterator operator-(const difference_type & a) const
224  {
225  gsUKnotIterator tmp(*this);
226  return tmp-=a;
227  }
228 
229  friend difference_type operator-(const gsUKnotIterator & l, const gsUKnotIterator & r)
230  {return l.m_upos - r.m_upos; }
231 
235  reference value() const
236  {
237 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
238  GISMO_ENSURE(m_upos >= 0 && m_upos + 1< m_dbg, "Access to invalid knot position.");
239 # endif
240  return this->operator*();
241  }
242 
247  mult_t multiplicity() const
248  {
249 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
250  GISMO_ENSURE(m_upos >= 0 && m_upos + 1< m_dbg, "Access to invalid knot position.");
251 # endif
252  if ( 0 == m_upos )//is it the first unique knot?
253  return *m_mlt;
254  else
255  {
256  mltpointer mp = m_mlt + m_upos;
257  return *mp - *(mp-1);
258  }
259  }
260 
265  mult_t uIndex() const {return m_upos-m_sh;}
266 
272  mult_t uCardinalIndex() const {return m_upos;}
273 
282  mult_t firstAppearance() const
283  {
284  return 0 == m_upos ? 0 : m_mlt[m_upos-1];
285  }
286 
295  mult_t lastAppearance() const
296  {
297 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
298  GISMO_ENSURE(m_upos >= 0 && m_upos + 1< m_dbg, "Access to invalid knot position.");
299 # endif
300  return m_mlt[m_upos] - 1;
301  }
302 
311  mult_t multSum() const
312  { return m_mlt[m_upos];}
313 
314 private:
315 
316  /*
317  \brief Sets the iterator to the first (without repetitions)
318  knot in the knot sequence
319 
320  // needed ?
321  void reset()
322  {
323  m_upos = 0;
324  }
325  */
326 };
327 
335 template <typename T>
336 class gsKnotIterator
337 {
338 public:
339  friend class gsKnotVector<T>;
340 
341  typedef typename gsKnotVector<T>::mult_t mult_t;
342  typedef std::random_access_iterator_tag iterator_category;
343  typedef const gsKnotVector<T> knotVector;
344  typedef T value_type;
345  typedef std::ptrdiff_t difference_type;
346  typedef const T& reference;
347  typedef const T* pointer;
348  typedef const mult_t* mltpointer;
349 
350 private:
351  gsUKnotIterator<T> m_uit;
352  mult_t m_pos;
353 
354 #if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
355  mult_t m_dbg;// iteration limit: extra member for iterator debugging mode
356 #endif
357 
358 public:
359 
363  gsKnotIterator()
364  : m_uit(), m_pos(0)
365  { }
366 
376  explicit gsKnotIterator(knotVector & KV, const mult_t upos = 0, const index_t s = 0)
377  : m_uit(KV,upos,s), m_pos(firstAppearance())
378  {
379 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
380  m_dbg = KV.size()+1;
381  GISMO_ENSURE(static_cast<size_t>(upos) <= KV.uSize(),
382  "Invalid iterator position "<< upos
383  <<" for knot vector with "<<KV.uSize()<<" unique knots");
384 # endif
385  }
386 
391  static inline gsKnotIterator End(const gsKnotVector<T> & KV)
392  { // the past-the-end position occurs for upos=KV.uSize()
393  return gsKnotIterator(KV, KV.uSize(),KV.numLeftGhosts());
394  }
395 
396 public:
397 
399  reference operator* () const
400  {
401 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
402  GISMO_ENSURE(m_pos >= 0 && m_pos + 1< m_dbg,
403  "Access to invalid knot position.");
404 # endif
405  return m_uit.m_raw[m_pos];
406  }
407 
408  pointer get() const {return m_uit.m_raw+m_pos;}
409  pointer operator-> () const {return get();}
410 
411  gsKnotIterator& operator++()
412  {
413  if (++m_pos == m_uit.multSum())//crossing interval?
414  ++m_uit;
415 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
416  GISMO_ENSURE(m_pos < m_dbg, "Invalid knot-iterator increment: "
417  << m_pos <<" is past the end position ("<<m_dbg-1<<").");
418 # endif
419  return *this;
420  }
421 
422  gsKnotIterator& operator--()
423  {
424 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
425  GISMO_ENSURE(m_pos > 0 && m_pos < m_dbg, "Invalid knot-iterator decrement");
426 # endif
427  if ( m_pos-- == firstAppearance() )//crossing interval?
428  --m_uit;
429  return *this;
430  }
431 
432  gsKnotIterator operator++(int) { gsKnotIterator tmp(*this); ++(*this); return tmp; }
433  gsKnotIterator operator--(int) { gsKnotIterator tmp(*this); --(*this); return tmp; }
434 
447  bool operator == (const gsKnotIterator& other) const
448  { return m_pos == other.m_pos;}// && m_raw == other.m_raw;}
449 
462  bool operator != (const gsKnotIterator& other) const {return m_pos != other.m_pos;}
463  bool operator < (const gsKnotIterator& other) const {return m_pos < other.m_pos;}
464  bool operator > (const gsKnotIterator& other) const {return m_pos > other.m_pos;}
465  bool operator <= (const gsKnotIterator& other) const {return m_pos <= other.m_pos;}
466  bool operator >= (const gsKnotIterator& other) const {return m_pos >= other.m_pos;}
467 
472  reference operator[] (ptrdiff_t a) const
473  {
474 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
475  GISMO_ENSURE(m_pos+a>=0 && m_pos+a+1 < m_dbg, "Invalid access to non-existent knot.");
476 # endif
477  return m_uit.m_raw[m_pos+a];
478  }
479 
484  reference operator() (ptrdiff_t a) const
485  {
486 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
487  GISMO_ENSURE(m_pos+a>=0 && m_pos+a+1 < m_dbg, "Invalid access to non-existent knot.");
488 # endif
489  return m_uit[a];
490  }
491 
497  const gsUKnotIterator<T> & uIterator() const
498  { return m_uit; }
499 
505  void uNext()
506  {
507  ++m_uit;
508  m_pos = firstAppearance();
509  //m_pos = (m_uit++).multSum();//advance unique position and update m_pos
510  }
511 
517  void uPrev()
518  {
519  --m_uit;
520  m_pos = firstAppearance();
521  }
522 
524  void uAdd(const difference_type & a)
525  {
526  m_uit += a;
527  m_pos = firstAppearance();
528  }
529 
534  gsKnotIterator& operator+=(const difference_type & a)
535  {
536  m_pos += a;
537 # if defined(_GLIBCXX_DEBUG) || _SECURE_SCL != 0
538  GISMO_ENSURE((m_pos >= 0 && m_pos < m_dbg),
539  "Iterator jumped to invalid knot position.");
540 # endif
541 
542  if (a<0) //substracting ?
543  {
544  mltpointer end = m_uit.m_mlt + m_uit.m_upos;
545  mltpointer beg = end + a;
546  if (beg < m_uit.m_mlt) beg = m_uit.m_mlt;
547  //note: [beg, end) is a valid sorted range, complexity: O(log a)
548  m_uit.m_upos = std::upper_bound(beg, end, m_pos) - m_uit.m_mlt;
549  }
550  else //incrementing
551  {
552  mltpointer beg = m_uit.m_mlt + m_uit.m_upos;
553  // O(log a) efficient version
554  mltpointer end = std::min(m_uit.m_mlt + m_uit.m_dbg-1, beg + a);
555  m_uit.m_upos = std::upper_bound(beg, end, m_pos) - m_uit.m_mlt;
556 
557  // unsafe version withoud m_dbg
558  //mltpointer end = beg + a; // note: could be over the end of m_mlt
559  // while (beg!=end && (*beg)<=m_pos) { ++beg; }
560  // m_uit.m_upos = beg - m_uit.m_mlt;
561  }
562 
563  return *this;
564  }
565 
570  gsKnotIterator operator+(const difference_type & a) const
571  {
572  gsKnotIterator tmp(*this);
573  return tmp+=a;
574  }
575 
576 
581  gsKnotIterator& operator-=(const difference_type & a)
582  {
583  return operator+=(-a);
584  }
585 
590  gsKnotIterator operator-(const difference_type & a) const
591  {
592  gsKnotIterator tmp(*this);
593  return tmp-=a;
594  }
595 
596  friend difference_type operator-(const gsKnotIterator & l, const gsKnotIterator & r)
597  {return l.m_pos - r.m_pos; }
598 
602  reference value() const {return this->operator*();}
603 
608  mult_t multiplicity() const
609  {
610  return m_uit.multiplicity();
611  }
612 
617  mult_t index() const {return m_pos;}
618 
623  mult_t uIndex() const {return m_uit.uIndex();}
624 
630  mult_t uCardinalIndex() const {return m_uit.uCardinalIndex();}
631 
639  mult_t firstAppearance() const
640  { return m_uit.firstAppearance();}
641 
649  mult_t lastAppearance() const
650  { return m_uit.lastAppearance();}
651 
660  mult_t multSum() const
661  { return m_uit.multSum();}
662 
667  void backToFirstAppearance()
668  { m_pos = m_uit.firstAppearance();}
669 
670  /*
671  \brief Sets the iterator to the first knot in the knot sequence
672  // needed ?
673  void reset()
674  {
675  m_pos = 0;
676  m_upos = 0;
677  }
678  */
679 
680 };
681 
682 
683 } // namespace internal
684 
685 
686 
687 }// namespace gismo
688 
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
bool operator!=(gsVertex< T > const &lhs, gsVertex< T > const &rhs)
Definition: gsVertex.h:240
EIGEN_STRONG_INLINE mult_expr< E1, E2 > const operator*(_expr< E1 > const &u, _expr< E2 > const &v)
Multiplication operator for expressions.
Definition: gsExpressions.h:4559
EIGEN_STRONG_INLINE add_expr< E1, E2 > const operator+(_expr< E1 > const &u, _expr< E2 > const &v)
Addition operator for expressions.
Definition: gsExpressions.h:4607