Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
p_array.hh
1 // Copyright (C) 2007, 2008, 2009, 2010, 2011 EPITA Research and
2 // Development Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_CORE_SITE_SET_P_ARRAY_HH
28 # define MLN_CORE_SITE_SET_P_ARRAY_HH
29 
40 
41 # include <vector>
42 
43 # include <mln/core/internal/site_set_base.hh>
44 # include <mln/core/internal/site_set_iterator_base.hh>
45 # include <mln/core/internal/pseudo_site_base.hh>
46 # include <mln/util/index.hh>
47 
48 
49 namespace mln
50 {
51 
52  // Forward declarations.
53  template <typename P> class p_array;
54 
55  template <typename S> class p_indexed_psite;
56  template <typename S> class p_indexed_fwd_piter;
57  template <typename S> class p_indexed_bkd_piter;
58 
59 
60 
61  namespace trait
62  {
63 
64  template <typename P>
65  struct site_set_< p_array<P> >
66  {
67  typedef trait::site_set::nsites::known nsites;
68  typedef trait::site_set::bbox::unknown bbox;
69  typedef trait::site_set::contents::growing contents;
70  typedef trait::site_set::arity::multiple arity;
71  };
72 
73  } // end of namespace trait
74 
75 
76 
82  //
83  template <typename P>
84  class p_array : public internal::site_set_base_< P, p_array<P> >
85  {
86  typedef p_array<P> self_;
87  public:
88  typedef typename std::vector<P>::size_type size_type;
89 
91  typedef P element;
92 
95 
98 
101 
103  typedef fwd_piter piter;
104 
105 
107  p_array();
108 
110  p_array(const std::vector<P>& vect);
111 
112 
114  void reserve(size_type n);
115 
116 
118  bool has(const psite& p) const;
119 
121  bool has(const util::index& i) const;
122 
124  bool is_valid() const;
125 
126 
128  void change(const psite& p, const P& new_p);
129 
131  unsigned nsites() const;
132 
133 
135  p_array<P>& append(const P& p);
136 
138  p_array<P>& append(const p_array<P>& other);
139 
141  typedef P i_element;
142 
144  void insert(const P& p);
145 
147  void clear();
148 
150  void resize(size_t size);
151 
152 
154  const P& operator[](unsigned i) const;
155 
157  P& operator[](unsigned i);
158 
160  const P& operator[](const util::index& i) const;
161  // FIXME: Is-it useful? (redundant with 'int'?)
162 
163 
165  std::size_t memory_size() const;
166 
168  const std::vector<P>& std_vector() const;
169 
171  std::vector<P>& hook_std_vector_();
172 
173  protected:
174 
175  std::vector<P> vect_;
176  };
177 
178 
179 
182  template <typename S>
183  class p_indexed_psite : public internal::pseudo_site_base_< const mln_element(S)&,
184  p_indexed_psite<S> >
185  {
186  public:
187 
188  typedef mln_element(S) element;
189 
190  // This associated type is important to know that this particular
191  // pseudo site knows the site set it refers to.
192  typedef S target;
193 
194  typedef S target_t; // To please g++-2.95.
195  // Also read the 'todo' in mln/core/concept/pseudo_site.hh.
196 
197  // As a Proxy:
198  const element& subj_();
199 
200  // As Itself.
201 
202  p_indexed_psite();
203 
204  p_indexed_psite(const S& s, int i);
205 
206  const util::index& index() const;
207 
208  void change_index(int i);
209  void inc_index();
210  void dec_index();
211 
212  const S* target_() const;
213  void change_target(const S& newtarget);
214 
215  bool is_valid() const;
216 
217  operator util::index() const;
218  operator int() const; // To interoperate, e.g., with fun::i2v expecting an int.
219  operator unsigned() const; // To avoid ambiguity when an unsigned is expected.
220 
221  void update_() const;
222 
223  private:
224 
225  const S* s_;
226  util::index i_;
227  mutable element p_;
228  };
229 
230 
231 
233 
234  template <typename S>
236  :
237  public internal::site_set_iterator_base< S,
238  p_indexed_fwd_piter<S> >
239  {
240  typedef p_indexed_fwd_piter<S> self;
241  typedef internal::site_set_iterator_base<S, self> super;
242 
243  public:
244 
247 
249  p_indexed_fwd_piter(const S& s);
250 
252  bool is_valid_() const;
253 
255  void invalidate_();
256 
258  void start_();
259 
261  void next_();
262 
264  int index() const;
265 
266  protected:
267  using super::p_;
268  using super::s_;
269  };
270 
271 
272 
274 
275  template <typename S>
277  :
278  public internal::site_set_iterator_base< S,
279  p_indexed_bkd_piter<S> >
280  {
281  typedef p_indexed_bkd_piter<S> self;
282  typedef internal::site_set_iterator_base<S, self> super;
283 
284  public:
285 
288 
290  p_indexed_bkd_piter(const S& s);
291 
293  bool is_valid_() const;
294 
296  void invalidate_();
297 
299  void start_();
300 
302  void next_();
303 
305  int index() const;
306 
307  protected:
308  using super::p_;
309  using super::s_;
310  };
311 
312 
313 
314  // Procedures.
315 
316  template <typename P, typename S>
317  int index_of_in(const P&, const S&);
318 
319  template <typename S>
320  int index_of_in(const p_indexed_psite<S>& p, const S& s);
321 
322  template <typename S, typename A>
323  int index_of_in(const p_indexed_psite<S>& p, const A& a);
324 
325  template <typename S, typename A>
326  int index_of_in(const p_indexed_fwd_piter<S>& p, const A& arr);
327 
328  template <typename S, typename A>
329  int index_of_in(const p_indexed_bkd_piter<S>& p, const A& arr);
330 
331 
332 
333 # ifndef MLN_INCLUDE_ONLY
334 
335 
336  // p_array<P>
337 
338  template <typename P>
339  inline
341  {
342  }
343 
344  template <typename P>
345  inline
346  p_array<P>::p_array(const std::vector<P>& vect)
347  : vect_(vect)
348  {
349  }
350 
351  template <typename P>
352  inline
353  void
354  p_array<P>::reserve(size_type n)
355  {
356  vect_.reserve(n);
357  }
358 
359  template <typename P>
360  inline
361  bool
362  p_array<P>::has(const psite& p) const
363  {
364  mln_precondition(p.target_() == this); // FIXME: Refine.
365  if (! has(p.index()))
366  return false;
367  // The type of rhs below is mln_site(p_array<P>).
368  mln_invariant(p == static_cast<P>((*this)[p.index()]));
369  return true;
370  }
371 
372  template <typename P>
373  inline
374  bool
375  p_array<P>::has(const util::index& i) const
376  {
377  return i >= 0 && unsigned(i) < nsites();
378  }
379 
380  template <typename P>
381  inline
382  bool
384  {
385  return true;
386  }
387 
388  template <typename P>
389  inline
390  const P&
391  p_array<P>::operator[](const util::index& i) const
392  {
393  mln_precondition(has(i));
394  return vect_[i];
395  }
396 
397  template <typename P>
398  inline
399  unsigned
401  {
402  return vect_.size();
403  }
404 
405  template <typename P>
406  inline
407  p_array<P>&
408  p_array<P>::append(const P& p)
409  {
410  vect_.push_back(p);
411  return *this;
412  }
413 
414  template <typename P>
415  inline
416  void
417  p_array<P>::insert(const P& p)
418  {
419  vect_.push_back(p);
420  }
421 
422  template <typename P>
423  inline
424  p_array<P>&
426  {
427  vect_.insert(vect_.end(),
428  other.std_vector().begin(),
429  other.std_vector().end());
430  return *this;
431  }
432 
433  template <typename P>
434  inline
435  void
437  {
438  vect_.clear();
439  mln_postcondition(this->is_empty());
440  }
441 
442  template <typename P>
443  inline
444  void
445  p_array<P>::resize(size_t size)
446  {
447  mln_precondition(size >= 0);
448  vect_.resize(size);
449  }
450 
451  template <typename P>
452  inline
453  const P&
454  p_array<P>::operator[](unsigned i) const
455  {
456  mln_precondition(i < nsites());
457  return vect_[i];
458  }
459 
460  template <typename P>
461  inline
462  P&
464  {
465  mln_precondition(i < nsites());
466  return vect_[i];
467  }
468 
469  template <typename P>
470  inline
471  void
472  p_array<P>::change(const psite& p, const P& new_p)
473  {
474  mln_precondition(has(p));
475  vect_[p.index()] = new_p;
476  }
477 
478  template <typename P>
479  inline
480  std::size_t
482  {
483  return sizeof(*this) + nsites() * sizeof(P);
484  }
485 
486  template <typename P>
487  inline
488  const std::vector<P>&
490  {
491  return vect_;
492  }
493 
494  template <typename P>
495  inline
496  std::vector<P>&
498  {
499  return vect_;
500  }
501 
502 
503 
504  // p_indexed_psite<S>
505 
506  template <typename S>
507  inline
508  p_indexed_psite<S>::p_indexed_psite()
509  : s_(0),
510  i_(0)
511  {
512  }
513 
514  template <typename S>
515  inline
516  p_indexed_psite<S>::p_indexed_psite(const S& s, int i)
517  : s_(& s),
518  i_(i)
519  {
520  update_();
521  }
522 
523  template <typename S>
524  inline
525  const util::index&
526  p_indexed_psite<S>::index() const
527  {
528  return i_;
529  }
530 
531  template <typename S>
532  inline
533  void
534  p_indexed_psite<S>::change_index(int i)
535  {
536  i_ = i;
537  update_();
538  }
539 
540  template <typename S>
541  inline
542  void
543  p_indexed_psite<S>::dec_index()
544  {
545  --i_;
546  update_();
547  }
548 
549  template <typename S>
550  inline
551  void
552  p_indexed_psite<S>::inc_index()
553  {
554  ++i_;
555  update_();
556  }
557 
558  template <typename S>
559  inline
560  void
561  p_indexed_psite<S>::change_target(const S& newtarget)
562  {
563  s_ = & newtarget;
564  i_ = -1; // Invalidate.
565  }
566 
567  template <typename S>
568  inline
569  bool
570  p_indexed_psite<S>::is_valid() const
571  {
572  return s_ != 0 && s_->has(i_);
573  }
574 
575  template <typename S>
576  inline
577  const S*
578  p_indexed_psite<S>::target_() const
579  {
580  return s_;
581  }
582 
583  template <typename S>
584  inline
585  const mln_element(S)&
586  p_indexed_psite<S>::subj_()
587  {
588  if (is_valid())
589  mln_invariant(p_ == (*s_)[i_]);
590  return p_;
591  }
592 
593  template <typename S>
594  inline
595  void
596  p_indexed_psite<S>::update_() const
597  {
598  if (is_valid())
599  p_ = (*s_)[i_];
600  }
601 
602  template <typename S>
603  inline
604  p_indexed_psite<S>::operator util::index() const
605  {
606  return i_;
607  }
608 
609  template <typename S>
610  inline
611  p_indexed_psite<S>::operator int() const
612  {
613  return i_;
614  }
615 
616  template <typename S>
617  inline
618  p_indexed_psite<S>::operator unsigned() const
619  {
620  mln_precondition(i_ >= 0);
621  return i_;
622  }
623 
624 
625  // p_indexed_fwd_piter<S>.
626 
627  template <typename S>
628  inline
630  {
631  }
632 
633  template <typename S>
634  inline
636  {
637  this->change_target(s);
638  }
639 
640  template <typename S>
641  inline
642  bool
644  {
645  mln_invariant(p_.index() >= 0);
646  return p_.index() < int(s_->nsites());
647  }
648 
649  template <typename S>
650  inline
651  void
652  p_indexed_fwd_piter<S>::invalidate_()
653  {
654  p_.change_index(s_->nsites());
655  }
656 
657  template <typename S>
658  inline
659  void
660  p_indexed_fwd_piter<S>::start_()
661  {
662  p_.change_index(0);
663  }
664 
665  template <typename S>
666  inline
667  void
668  p_indexed_fwd_piter<S>::next_()
669  {
670  p_.inc_index();
671  }
672 
673  template <typename S>
674  inline
675  int
677  {
678  return p_.index();
679  }
680 
681 
682  // p_indexed_bkd_piter<S>.
683 
684  template <typename S>
685  inline
687  {
688  }
689 
690  template <typename S>
691  inline
693  {
694  this->change_target(s);
695  }
696 
697  template <typename S>
698  inline
699  bool
701  {
702  mln_invariant(p_.index() < int(s_->nsites()));
703  return p_.index() >= 0;
704  }
705 
706  template <typename S>
707  inline
708  void
709  p_indexed_bkd_piter<S>::invalidate_()
710  {
711  p_.change_index(-1);
712  }
713 
714  template <typename S>
715  inline
716  void
717  p_indexed_bkd_piter<S>::start_()
718  {
719  p_.change_index(s_->nsites() - 1);
720  }
721 
722  template <typename S>
723  inline
724  void
725  p_indexed_bkd_piter<S>::next_()
726  {
727  p_.dec_index();
728  }
729 
730  template <typename S>
731  inline
732  int
734  {
735  return p_.index();
736  }
737 
738 
739  // Procedures
740 
741  template <typename P, typename S>
742  int index_of_in(const P&, const S&)
743  {
744  return -1;
745  }
746 
747  template <typename S>
748  int index_of_in(const p_indexed_psite<S>& p, const S& s)
749  {
750  if ((void*)(p.target_()) == (void*)(&s))
751  return p.index();
752  else
753  return index_of_in(p.unproxy_(), s);
754  }
755 
756  template <typename S, typename A>
757  int index_of_in(const p_indexed_psite<S>& p, const A& a)
758  {
759  return index_of_in(p.unproxy_(), a);
760  }
761 
762  template <typename S, typename A>
763  inline
764  int
765  index_of_in(const p_indexed_fwd_piter<S>& p, const A& arr)
766  {
767  return index_of_in(p.unproxy_(), arr);
768  }
769 
770  template <typename S, typename A>
771  inline
772  int
773  index_of_in(const p_indexed_bkd_piter<S>& p, const A& arr)
774  {
775  return index_of_in(p.unproxy_(), arr);
776  }
777 
778 # endif // ! MLN_INCLUDE_ONLY
779 
780 } // end of namespace mln
781 
782 
783 #endif // ! MLN_CORE_SITE_SET_P_ARRAY_HH