20 class SlicedTube :
public SlicedTubeBase
24 explicit SlicedTube(
const std::shared_ptr<TDomain>& tdomain,
26 : SlicedTubeBase(tdomain)
28 for(
auto it = _tdomain->begin(); it != _tdomain->end(); ++it)
31 std::make_shared<Slice<T>>(*this, it, codomain)
35 explicit SlicedTube(
const std::shared_ptr<TDomain>& tdomain,
36 const AnalyticFunction<
typename ExprType<T>::Type>& f)
37 : SlicedTubeBase(tdomain)
39 assert_release(f.args().size() == 1
40 &&
"function's inputs must be limited to one system variable");
42 for(
auto it = _tdomain->begin(); it != _tdomain->end(); ++it)
45 std::make_shared<Slice<T>>(*
this, it, f.eval((Interval)*it))
49 SlicedTube(
const SlicedTube<T>& x)
50 : SlicedTubeBase(x.tdomain())
52 for(
auto it = _tdomain->begin(); it != _tdomain->end(); ++it)
55 std::make_shared<Slice<T>>(*x(it), *this)
59 inline SlicedTube& operator=(
const SlicedTube& x)
61 assert_release(_tdomain == x._tdomain);
63 for(
auto it = _tdomain->begin(); it != _tdomain->end(); ++it)
64 (*this)(it).set(x(it)->codomain(),
false);
69 inline Index size()
const
71 return first_slice()->size();
74 inline double volume()
const
77 for(
const auto& s : *
this)
82 inline std::shared_ptr<Slice<T>> first_slice()
84 return std::const_pointer_cast<Slice<T>>(
85 static_cast<const SlicedTube&
>(*this).first_slice());
88 inline std::shared_ptr<const Slice<T>> first_slice()
const
90 return std::static_pointer_cast<const Slice<T>>(
91 this->SlicedTubeBase::first_slice());
94 inline std::shared_ptr<Slice<T>> last_slice()
96 return std::const_pointer_cast<Slice<T>>(
97 static_cast<const SlicedTube&
>(*this).last_slice());
100 inline std::shared_ptr<const Slice<T>> last_slice()
const
102 return std::static_pointer_cast<const Slice<T>>(
103 this->SlicedTubeBase::last_slice());
106 inline bool is_empty()
const
110 for(
const auto& s : *
this)
111 if(s.is_gate() && s.is_empty())
113 for(
const auto& s : *
this)
114 if(!s.is_gate() && s.is_empty())
119 inline bool is_unbounded()
const
121 for(
const auto& s : *
this)
127 inline T codomain()
const
129 T x = first_slice()->codomain();
130 for(
const auto& s : *
this)
135 inline std::shared_ptr<Slice<T>> operator()(
const std::list<TSlice>::iterator& it)
137 return std::const_pointer_cast<Slice<T>>(
138 static_cast<const SlicedTube&
>(*this).operator()(it));
141 inline std::shared_ptr<const Slice<T>> operator()(
const std::list<TSlice>::const_iterator& it)
const
143 return std::static_pointer_cast<const Slice<T>>(
144 it->slices().at(
this));
147 inline std::shared_ptr<Slice<T>> operator()(
const std::list<TSlice>::reverse_iterator& it)
149 return std::const_pointer_cast<Slice<T>>(
150 static_cast<const SlicedTube&
>(*this).operator()(it));
153 inline std::shared_ptr<const Slice<T>> operator()(
const std::list<TSlice>::const_reverse_iterator& it)
const
155 return std::static_pointer_cast<const Slice<T>>(
156 it->slices().at(
this));
159 inline T operator()(
double t)
const
161 if(!tdomain()->t0_tf().contains(t))
162 return all_reals_codomain();
164 auto it_t = _tdomain->tslice(t);
165 assert(it_t != _tdomain->end());
166 T x = (*this)(it_t)->codomain();
167 if(!it_t->is_gate() && t==it_t->lb() && it_t!=_tdomain->begin())
168 x &= (*this)(--it_t)->codomain();
172 inline T operator()(
const Interval& t)
const
174 if(!tdomain()->t0_tf().is_superset(t))
175 return all_reals_codomain();
177 if(t.is_degenerated())
178 return (*
this)(t.lb());
180 auto t_ = t & _tdomain->t0_tf();
182 auto it = _tdomain->tslice(t_.lb());
183 T codomain = (*this)(it)->codomain();
185 while(it != std::next(_tdomain->tslice(t_.ub())))
187 if(it->lb() == t_.ub())
break;
188 codomain |= (*this)(it)->codomain();
195 std::pair<T,T> enclosed_bounds(
const Interval& t)
const
197 auto x = this->empty_codomain();
198 auto bounds = std::make_pair(x,x);
200 if(t.lb() < _tdomain->t0_tf().lb() || t.ub() > _tdomain->t0_tf().ub())
202 x.init(Interval(-oo,0));
204 x.init(Interval(0,oo));
208 Interval t_inter = t & _tdomain->t0_tf();
209 auto si = (*this)(_tdomain->tslice(t_inter.lb()));
211 while(si && si->t0_tf().lb() <= t_inter.ub())
213 auto slice_bounds = si->enclosed_bounds(t_inter & si->t0_tf());
214 bounds.first |= slice_bounds.first;
215 bounds.second |= slice_bounds.second;
216 si = si->next_slice();
222 inline void set(
const T& codomain)
224 assert_release(codomain.size() == this->size());
228 s.set(codomain,
false);
232 s.set(codomain,
false);
235 inline void set(
const T& codomain,
double t)
237 assert_release(codomain.size() == this->size());
238 (*this)(_tdomain->sample(t,
true))->set(codomain);
241 inline void set(
const T& codomain,
const Interval& t)
243 auto it_lb = _tdomain->sample(t.lb(), t.is_degenerated());
244 std::list<TSlice>::iterator it_ub;
246 if(!t.is_degenerated())
248 it_ub = _tdomain->sample(t.ub(),
false);
250 if(it_ub->lb() == t.ub())
253 if(it_lb->ub() == t.lb())
262 (*this)(it_lb)->set(codomain);
263 }
while(it_lb != it_ub && (++it_lb) != _tdomain->end());
266 inline void set_ith_slice(
const T& codomain, Index i)
269 for(
auto& si : *
this)
277 const SlicedTube<T>& inflate(
double rad)
279 assert_release(rad >= 0.);
283 s.set(T(s.codomain()).inflate(rad),
false);
287 s.set(T(s.codomain()).inflate(rad),
false);
292 inline bool operator==(
const SlicedTube& x)
const
294 if(!TDomain::are_same(tdomain(), x.tdomain()))
297 auto it_this = _tdomain->begin();
298 auto it_x = x.tdomain()->cbegin();
300 while(it_this != _tdomain->end())
301 if(*(*
this)(it_this++) != *x(it_x++))
307 inline SlicedTube operator&=(
const SlicedTube& x)
309 assert(TDomain::are_same(tdomain(), x.tdomain()));
310 auto it_this = _tdomain->begin();
311 auto it_x = x.tdomain()->cbegin();
313 while(it_this != _tdomain->end())
315 auto s = (*this)(it_this);
316 s->set(s->codomain() & x(it_x)->codomain());
320 assert(it_x == x.tdomain()->cend());
324 friend inline std::ostream& operator<<(std::ostream& os,
const SlicedTube<T>& x)
327 <<
"↦" << x.codomain()
328 <<
", " << x.nb_slices()
329 <<
" slice" << (x.nb_slices() > 1 ?
"s" :
"")
336 T integral(
const Interval& t)
const;
337 T integral(
const Interval& t1,
const Interval& t2)
const;
338 std::pair<T,T> partial_integral(
const Interval& t)
const;
339 std::pair<T,T> partial_integral(
const Interval& t1,
const Interval& t2)
const;
344 using base_container = std::list<TSlice>;
346 struct iterator :
public base_container::iterator
350 iterator(SlicedTube& x, base_container::iterator it)
351 : base_container::iterator(it), _x(x) { }
353 std::shared_ptr<Slice<T>> operator->()
358 Slice<T>& operator*()
360 return *operator->();
368 iterator begin() {
return { *
this, _tdomain->begin() }; }
369 iterator end() {
return { *
this, _tdomain->end() }; }
371 struct reverse_iterator :
public base_container::reverse_iterator
375 reverse_iterator(SlicedTube& x, base_container::reverse_iterator it)
376 : base_container::reverse_iterator(it), _x(x) { }
378 std::shared_ptr<Slice<T>> operator->()
383 Slice<T>& operator*()
385 return *operator->();
393 reverse_iterator rbegin() {
return { *
this, _tdomain->rbegin() }; }
394 reverse_iterator rend() {
return { *
this, _tdomain->rend() }; }
396 struct const_iterator :
public base_container::const_iterator
400 const_iterator(
const SlicedTube& x, base_container::const_iterator it)
401 : base_container::const_iterator(it), _x(x) { }
403 std::shared_ptr<const Slice<T>> operator->()
408 const Slice<T>& operator*()
410 return *operator->();
415 const SlicedTube& _x;
418 const_iterator begin()
const {
return { *
this, _tdomain->cbegin() }; }
419 const_iterator end()
const {
return { *
this, _tdomain->cend() }; }
423 inline T all_reals_codomain()
const
425 T x = first_slice()->codomain();
430 inline T empty_codomain()
const
432 T x = first_slice()->codomain();
441 SlicedTube(
const std::shared_ptr<TDomain>& tdomain,
const AnalyticFunction<T>& f) ->
442 SlicedTube<typename Wrapper<T>::Domain>;