30 class Tube :
public AbstractSlicedTube,
public AbstractConstTube<T,Tube<T>>,
public Domain
34 explicit Tube(
const std::shared_ptr<TDomain>& tdomain) :
38 explicit Tube(
const std::shared_ptr<TDomain>& tdomain,
const AnalyticFunction<
typename ValueType<T>::Type>& f) :
39 Tube(tdomain, (std::is_same<T,Interval>::value ? T() : T(f.image_dim())))
41 assert(f.nb_var() == 0 &&
"function's inputs must be limited to system variable");
42 if constexpr(std::is_same<T,Interval>::value) {
43 assert(f.image_dim() == 1);
48 if constexpr(std::is_same<T,Interval>::value)
49 s.set(f.eval(s.t0_tf()));
52 s.set(to_codac2(f.eval_vector(s.t0_tf())));
55 std::cout <<
"IS EMPTY: " << s << std::endl;
59 explicit Tube(
const std::shared_ptr<TDomain>& tdomain,
const T& default_value) :
60 AbstractSlicedTube(tdomain)
62 for(std::list<TSlice>::iterator it = _tdomain->_tslices.begin();
63 it != _tdomain->_tslices.end(); ++it)
66 std::pair<const AbstractSlicedTube*,std::shared_ptr<Slice<T>>>(this,
67 std::make_shared<Slice<T>>(default_value, *this, it)));
71 Tube(
const Tube<T>& x) :
72 AbstractSlicedTube(x.tdomain())
74 for(std::list<TSlice>::iterator it = _tdomain->_tslices.begin();
75 it != _tdomain->_tslices.end(); ++it)
77 std::shared_ptr<Slice<T>> s_ptr = std::make_shared<Slice<T>>(x(it), *this);
78 it->_slices.insert(std::pair<const AbstractSlicedTube*,std::shared_ptr<Slice<T>>>(this, s_ptr));
84 for(
auto& s : _tdomain->_tslices)
85 s._slices.erase(
this);
88 Tube& operator=(
const Tube& x)
90 if(_tdomain != x._tdomain)
91 throw std::exception();
93 for(
auto it = _tdomain->_tslices.begin();
94 it != _tdomain->_tslices.end(); ++it)
95 (*this)(it).set(x(it).codomain());
100 virtual Interval t0_tf()
const
102 return AbstractSlicedTube::t0_tf();
108 if constexpr(std::is_same<T,Interval>::value)
111 return first_slice().size();
114 size_t nb_slices()
const
116 return _tdomain->nb_tslices();
119 double volume()
const
122 for(
const auto& s : *
this)
123 volume += s.volume();
127 virtual const std::shared_ptr<AbstractSlice>& first_abstract_slice_ptr()
const
129 return _tdomain->tslices().front().slices().at(
this);
132 virtual const std::shared_ptr<AbstractSlice>& last_abstract_slice_ptr()
const
134 return _tdomain->tslices().back().slices().at(
this);
137 const std::shared_ptr<Slice<T>> first_slice_ptr()
const
139 return std::static_pointer_cast<Slice<T>>(first_abstract_slice_ptr());
142 const Slice<T>& first_slice()
const
144 return *first_slice_ptr();
147 Slice<T>& first_slice()
149 return const_cast<Slice<T>&
>(
150 static_cast<const Tube&
>(*this).first_slice());
153 const std::shared_ptr<Slice<T>> last_slice_ptr()
const
155 return std::static_pointer_cast<Slice<T>>(last_abstract_slice_ptr());
158 const Slice<T>& last_slice()
const
160 return *last_slice_ptr();
163 Slice<T>& last_slice()
165 return const_cast<Slice<T>&
>(
166 static_cast<const Tube&
>(*this).last_slice());
169 bool is_empty()
const
173 for(
const auto& s : *
this)
174 if(s.is_gate() && s.is_empty())
176 for(
const auto& s : *
this)
177 if(!s.is_gate() && s.is_empty())
182 bool is_unbounded()
const
184 for(
const auto& s : *
this)
208 T codomain = first_slice().codomain();
209 codomain.set_empty();
210 for(
const auto& s : *
this)
211 codomain |= s.codomain();
216 std::shared_ptr<Slice<T>> slice_ptr(
const std::list<TSlice>::iterator& it)
218 return std::static_pointer_cast<Slice<T>>(it->slices().at(
this));
221 Slice<T>& operator()(
const std::list<TSlice>::iterator& it)
223 return const_cast<Slice<T>&
>(
224 static_cast<const Tube&
>(*this).operator()(it));
227 const Slice<T>& operator()(
const std::list<TSlice>::iterator& it)
const
229 return *std::static_pointer_cast<Slice<T>>(it->slices().at(
this));
232 T eval(
double t)
const
234 if(!tdomain()->t0_tf().contains(t))
236 if constexpr(!std::is_same<T,codac2::IntervalVector>::value)
241 std::list<TSlice>::iterator it_t = _tdomain->iterator_tslice(t);
242 assert(it_t != _tdomain->_tslices.end());
243 T x = std::static_pointer_cast<Slice<T>>(it_t->_slices.at(
this))->codomain();
244 if(!it_t->is_gate() && t==it_t->t0_tf().lb() && it_t!=_tdomain->_tslices.begin())
245 x &= std::static_pointer_cast<Slice<T>>((--it_t)->_slices.at(
this))->codomain();
249 T eval(
const Interval& t)
const
251 if(!tdomain()->t0_tf().is_superset(t))
253 if constexpr(!std::is_same<T,codac2::IntervalVector>::value)
259 if(t.is_degenerated())
262 std::list<TSlice>::iterator it = _tdomain->iterator_tslice(t.lb());
263 T codomain = std::static_pointer_cast<Slice<T>>(it->_slices.at(
this))->codomain();
265 while(it != std::next(_tdomain->iterator_tslice(t.ub())))
267 if(it->t0_tf().lb() == t.ub())
break;
268 codomain |= std::static_pointer_cast<Slice<T>>(it->_slices.at(
this))->codomain();
275 void set(
const T& codomain)
277 if constexpr(std::is_same<T,codac2::IntervalVector>::value) {
278 assert((
size_t)codomain.size() == size());
288 void set(
const T& codomain,
double t)
290 if constexpr(std::is_same<T,codac2::IntervalVector>::value) {
291 assert((
size_t)codomain.size() == size());
293 std::list<TSlice>::iterator it = _tdomain->sample(t,
true);
294 (*this)(it).set(codomain);
297 const Tube<T>& inflate(
double rad)
314 bool operator==(
const Tube& x)
const
316 if(!TDomain::are_same(tdomain(), x.tdomain()))
319 std::list<TSlice>::iterator it_this = _tdomain->_tslices.begin();
320 std::list<TSlice>::const_iterator it_x = x.tdomain()->tslices().cbegin();
322 while(it_this != _tdomain->tslices().end())
324 if(*std::static_pointer_cast<Slice<T>>(it_this->_slices.at(
this)) !=
325 *std::static_pointer_cast<Slice<T>>(it_x->slices().at(&x)))
333 bool operator!=(
const Tube& x)
const
335 return !operator==(x);
339 Tube operator&=(
const Tube& x)
341 assert(TDomain::are_same(tdomain(), x.tdomain()));
342 std::list<TSlice>::iterator it_this = _tdomain->_tslices.begin();
343 std::list<TSlice>::const_iterator it_x = x.tdomain()->tslices().cbegin();
345 while(it_this != _tdomain->tslices().end())
347 std::shared_ptr<Slice<T>> s = std::static_pointer_cast<Slice<T>>(it_this->_slices.at(
this));
348 s->set(s->codomain() & std::static_pointer_cast<Slice<T>>(it_x->slices().at(&x))->codomain());
352 assert(it_x == x.tdomain()->tslices().cend());
356 friend std::ostream& operator<<(std::ostream& os,
const Tube<T>& x)
358 x.AbstractConstTube<T,Tube<T>>::print(os);
360 os <<
", " << x.nb_slices()
361 <<
" slice" << (x.nb_slices() > 1 ?
"s" :
"")
369 using base_container = std::list<TSlice>;
371 struct iterator :
public base_container::iterator
373 using iterator_category =
typename base_container::iterator::iterator_category;
374 using difference_type =
typename base_container::iterator::difference_type;
376 using value_type = Slice<T>;
377 using pointer = Slice<T>*;
378 using reference = Slice<T>&;
382 iterator(
const Tube& x, base_container::iterator it) :
383 base_container::iterator(it), _x(x) { }
385 reference operator*()
387 return static_cast<reference
>(*((*this)->_slices.at(&_x)));
395 iterator begin() {
return iterator(*
this, _tdomain->_tslices.begin()); }
396 iterator end() {
return iterator(*
this, _tdomain->_tslices.end()); }
398 struct reverse_iterator :
public base_container::reverse_iterator
400 using iterator_category =
typename base_container::reverse_iterator::iterator_category;
401 using difference_type =
typename base_container::reverse_iterator::difference_type;
403 using value_type = Slice<T>;
404 using pointer = Slice<T>*;
405 using reference = Slice<T>&;
409 reverse_iterator(
const Tube& x, base_container::reverse_iterator it) :
410 base_container::reverse_iterator(it), _x(x) { }
412 reference operator*()
414 return static_cast<reference
>(*((*this)->_slices.at(&_x)));
422 reverse_iterator rbegin() {
return reverse_iterator(*
this, _tdomain->_tslices.rbegin()); }
423 reverse_iterator rend() {
return reverse_iterator(*
this, _tdomain->_tslices.rend()); }
425 struct const_iterator :
public base_container::const_iterator
427 using iterator_category =
typename base_container::const_iterator::iterator_category;
428 using difference_type =
typename base_container::const_iterator::difference_type;
430 using value_type = Slice<T>;
431 using pointer =
const Slice<T>*;
432 using reference =
const Slice<T>&;
436 const_iterator(
const Tube& x, base_container::const_iterator it) :
437 base_container::const_iterator(it), _x(x) { }
439 reference operator*()
const
441 return static_cast<reference
>(*((*this)->_slices.at(&_x)));
449 const_iterator begin()
const {
return const_iterator(*
this, _tdomain->_tslices.cbegin()); }
450 const_iterator end()
const {
return const_iterator(*
this, _tdomain->_tslices.cend()); }