Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
p_double.hh
1 // Copyright (C) 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_CORE_SITE_SET_P_DOUBLE_HH
27 # define MLN_CORE_SITE_SET_P_DOUBLE_HH
28 
38 # include <mln/core/internal/pseudo_site_base.hh>
39 # include <mln/core/internal/site_set_iterator_base.hh>
40 
41 
42 namespace mln
43 {
44 
45  // p_double_psite<S,Sp>
46 
47  template <typename S, typename Sp>
48  class p_double_psite : public internal::pseudo_site_base_< const mln_psite(Sp)&,
49  p_double_psite<S,Sp> >
50  {
51  public:
52 
53  p_double_psite();
54 
55  // Target associated type.
56  typedef S target;
57 
58  const S* target_() const;
59 
60  void change_target(const S& newtarget);
61 
62  bool is_valid() const;
63 
64  unsigned index() const;
65  const mln_psite(Sp)& p() const;
66 
67  void change_i(unsigned i);
68 
69  void change_p(const mln_psite(Sp)& p);
70 
71  // As a Proxy:
72  const mln_psite(Sp)& subj_();
73 
74  private:
75 
76  const target* s_;
77  mutable unsigned i_;
78  mutable mln_psite(Sp) p_;
79  };
80 
81 
82 
83  // p_double_piter<S,I1,I2>
84 
85  template <typename S, typename I1, typename I2>
86  class p_double_piter
87  :
88  public internal::site_set_iterator_base< S,
89  p_double_piter<S,I1,I2> >
90  {
91  typedef p_double_piter<S,I1,I2> self_;
92  typedef internal::site_set_iterator_base<S,self_> super_;
93  public:
94 
96  p_double_piter();
97 
99  p_double_piter(const S& s);
100 
102  void change_target(const S& newtarget);
103 
105  bool is_valid_() const;
106 
108  void invalidate_();
109 
111  void start_();
112 
114  void next_();
115 
116  protected:
117  using super_::p_;
118  using super_::s_;
119 
120  private:
121  I1 i1_;
122  I2 i2_;
123 
124  // Progress to the next valid state if it exists.
125  void progress_();
126 
127  };
128 
129 
130 
131 # ifndef MLN_INCLUDE_ONLY
132 
133 
134  // p_double_psite<S,Sp>
135 
136  template <typename S, typename Sp>
137  inline
138  p_double_psite<S,Sp>::p_double_psite()
139  {
140  }
141 
142  template <typename S, typename Sp>
143  inline
144  const mln_psite(Sp)&
145  p_double_psite<S,Sp>::subj_()
146  {
147  return p_;
148  }
149 
150  template <typename S, typename Sp>
151  inline
152  const S*
153  p_double_psite<S,Sp>::target_() const
154  {
155  return s_;
156  }
157 
158  template <typename S, typename Sp>
159  inline
160  void
161  p_double_psite<S,Sp>::change_target(const S& s)
162  {
163  s_ = & s;
164  }
165 
166  template <typename S, typename Sp>
167  inline
168  bool
169  p_double_psite<S,Sp>::is_valid() const
170  {
171  return s_ != 0 && p_.is_valid();
172  }
173 
174  template <typename S, typename Sp>
175  inline
176  unsigned
177  p_double_psite<S,Sp>::index() const
178  {
179  return i_;
180  }
181 
182  template <typename S, typename Sp>
183  inline
184  const mln_psite(Sp)&
185  p_double_psite<S,Sp>::p() const
186  {
187  return p_;
188  }
189 
190  template <typename S, typename Sp>
191  inline
192  void
193  p_double_psite<S,Sp>::change_i(unsigned i)
194  {
195  i_ = i;
196  }
197 
198  template <typename S, typename Sp>
199  inline
200  void
201  p_double_psite<S,Sp>::change_p(const mln_psite(Sp)& p)
202  {
203  p_ = p;
204  }
205 
206 
207  // p_double_piter<S,I1,I2>
208 
209  template <typename S, typename I1, typename I2>
210  inline
211  p_double_piter<S,I1,I2>::p_double_piter()
212  {
213  }
214 
215  template <typename S, typename I1, typename I2>
216  inline
217  p_double_piter<S,I1,I2>::p_double_piter(const S& s)
218  {
219  this->change_target(s);
220  }
221 
222  template <typename S, typename I1, typename I2>
223  inline
224  void
225  p_double_piter<S,I1,I2>::change_target(const S& newtarget)
226  {
227  this->super_::change_target(newtarget);
228  i1_.change_target(newtarget.set_1_());
229  invalidate_();
230  }
231 
232  template <typename S, typename I1, typename I2>
233  inline
234  bool
235  p_double_piter<S,I1,I2>::is_valid_() const
236  {
237  return i2_.is_valid();
238  }
239 
240  template <typename S, typename I1, typename I2>
241  inline
242  void
243  p_double_piter<S,I1,I2>::invalidate_()
244  {
245  i2_.invalidate();
246  }
247 
248  template <typename S, typename I1, typename I2>
249  inline
250  void
251  p_double_piter<S,I1,I2>::start_()
252  {
253  i1_.start();
254  if (i1_.is_valid())
255  {
256  i2_.change_target(s_->set_2_(i1_));
257  i2_.start();
258  if (! i2_.is_valid())
259  progress_();
260  else
261  {
262  p_.change_i(i1_.index_());
263  p_.change_p(i2_);
264  }
265  }
266  else
267  i2_.invalidate();
268  mln_postcondition(implies(i2_.is_valid(), i1_.is_valid()));
269  }
270 
271  template <typename S, typename I1, typename I2>
272  inline
273  void
274  p_double_piter<S,I1,I2>::next_()
275  {
276  i2_.next();
277  if (! i2_.is_valid())
278  progress_();
279  else
280  p_.change_p(i2_);
281  mln_postcondition(implies(i2_.is_valid(), i1_.is_valid()));
282  }
283 
284  template <typename S, typename I1, typename I2>
285  inline
286  void
287  p_double_piter<S,I1,I2>::progress_()
288  {
289  // This routine is general; it does not make the assumption that
290  // the site set type features is_empty().
291  while (! i2_.is_valid() && i1_.is_valid())
292  {
293  i1_.next();
294  if (! i1_.is_valid())
295  {
296  // End of iterations.
297  i2_.invalidate(); // Safety.
298  return;
299  }
300  i2_.change_target(s_->set_2_(i1_));
301  i2_.start();
302  }
303  if (i2_.is_valid())
304  {
305  p_.change_i(i1_.index_());
306  p_.change_p(i2_);
307  }
308  }
309 
310 # endif // ! MLN_INCLUDE_ONLY
311 
312 } // end of namespace mln
313 
314 
315 #endif // ! MLN_CORE_SITE_SET_P_DOUBLE_HH