Lattice Land Core Library
Loading...
Searching...
No Matches
interval.hpp
Go to the documentation of this file.
1// Copyright 2021 Pierre Talbot
2
3#ifndef LALA_CORE_INTERVAL_HPP
4#define LALA_CORE_INTERVAL_HPP
5
8
9namespace lala {
10
11template <class U>
12class Interval;
13
14template<class L, class K>
15CUDA constexpr auto meet(const Interval<L>&, const Interval<K>&);
16
17namespace impl {
18 template <class LB, class UB>
19 constexpr typename Interval<LB>::local_type make_itv(CartesianProduct<LB, UB> cp) {
20 return typename Interval<LB>::local_type(project<0>(cp), project<1>(cp));
21 }
22
23 template <class U> constexpr const typename Interval<U>::LB& lb(const Interval<U>& itv) { return itv.lb(); }
24 template <class L> constexpr const L& lb(const L& other) { return other; }
25 template <class U> constexpr const typename Interval<U>::UB& ub(const Interval<U>& itv) { return itv.ub(); }
26 template <class L> constexpr const L& ub(const L& other) { return other; }
27}
28
29/** An interval is a Cartesian product of a lower and upper bounds, themselves represented as lattices.
30 One difference, is that the \f$ \top \f$ can be represented by multiple interval elements, whenever \f$ l > u \f$, therefore some operations are different than on the Cartesian product, e.g., \f$ [3..2] \equiv [4..1] \f$ in the interval lattice. */
31template <class U>
32class Interval {
33public:
34 using LB = U;
35 using UB = typename LB::dual_type;
39 using value_type = typename CP::value_type;
40 using memory_type = typename CP::memory_type;
41
42 template <class A>
43 friend class Interval;
44
45 constexpr static const bool is_abstract_universe = true;
46 constexpr static const bool sequential = CP::sequential;
47 constexpr static const bool is_totally_ordered = false;
48 constexpr static const bool preserve_top = CP::preserve_top;
49 constexpr static const bool preserve_bot = true;
50 constexpr static const bool preserve_meet = true;
51 constexpr static const bool preserve_join = false;
54 constexpr static const bool complemented = false;
55 constexpr static const bool is_arithmetic = LB::is_arithmetic;
56 constexpr static const char* name = "Interval";
57
58private:
59 using LB2 = typename LB::local_type;
60 using UB2 = typename UB::local_type;
61 CP cp;
62 CUDA constexpr Interval(const CP& cp): cp(cp) {}
63 CUDA constexpr local_type lb2() const { return local_type(lb(), dual<UB2>(lb())); }
64 CUDA constexpr local_type ub2() const { return local_type(dual<LB2>(ub()), ub()); }
65public:
66 /** Initialize the interval to top using the default constructor of the bounds. */
67 CUDA constexpr Interval() {}
68 /** Given a value \f$ x \in U \f$ where \f$ U \f$ is the universe of discourse, we initialize a singleton interval \f$ [x..x] \f$. */
69 CUDA constexpr Interval(const typename U::value_type& x): cp(x, x) {}
70 CUDA constexpr Interval(const LB& lb, const UB& ub): cp(lb, ub) {}
71
72 template<class A>
73 CUDA constexpr Interval(const Interval<A>& other): cp(other.cp) {}
74
75 template<class A>
76 CUDA constexpr Interval(Interval<A>&& other): cp(std::move(other.cp)) {}
77
78 /** The assignment operator can only be used in a sequential context.
79 * It is monotone but not extensive. */
80 template <class A>
81 CUDA constexpr this_type& operator=(const Interval<A>& other) {
82 cp = other.cp;
83 return *this;
84 }
85
86 CUDA constexpr this_type& operator=(const this_type& other) {
87 cp = other.cp;
88 return *this;
89 }
90
91 /** Pre-interpreted formula `x == 0`. */
92 CUDA constexpr static local_type eq_zero() { return local_type(LB::geq_k(LB::pre_universe::zero()), UB::leq_k(UB::pre_universe::zero())); }
93 /** Pre-interpreted formula `x == 1`. */
94 CUDA constexpr static local_type eq_one() { return local_type(LB::geq_k(LB::pre_universe::one()), UB::leq_k(UB::pre_universe::one())); }
95
96 CUDA constexpr static local_type bot() { return Interval(CP::bot()); }
97 CUDA constexpr static local_type top() { return Interval(CP::top()); }
98 CUDA constexpr local::B is_bot() const { return cp.is_bot() || (!lb().is_top() && dual<UB2>(lb()) > ub()); }
99 CUDA constexpr local::B is_top() const { return cp.is_top(); }
100 CUDA constexpr const CP& as_product() const { return cp; }
101 CUDA constexpr value_type value() const { return cp.value(); }
102
103private:
104 template<class A, class B>
105 CUDA constexpr void flat_fun(Sig fun, const Interval<A>& a, const Interval<B>& b) {
106 lb().project(fun,
107 typename A::template flat_type<battery::local_memory>(a.lb()),
108 typename B::template flat_type<battery::local_memory>(b.lb()));
109 ub().project(fun,
110 typename A::template flat_type<battery::local_memory>(a.ub()),
111 typename B::template flat_type<battery::local_memory>(b.ub()));
112 }
113
114 template<class A>
115 CUDA constexpr void flat_fun(Sig fun, const Interval<A>& a) {
116 lb().project(fun, typename A::template flat_type<battery::local_memory>(a.lb()));
117 ub().project(fun, typename A::template flat_type<battery::local_memory>(a.ub()));
118 }
119
120public:
121 /** Support the same language than the Cartesian product, and more:
122 * * `var x:B` when the underlying universe is arithmetic and preserve concrete covers.
123 * Therefore, the element `k` is always in \f$ \gamma(lb) \cap \gamma(ub) \f$. */
124 template<bool diagnose = false, class F, class Env, class U2>
125 CUDA NI static bool interpret_tell(const F& f, const Env& env, Interval<U2>& k, IDiagnostics& diagnostics) {
126 if constexpr(LB::preserve_concrete_covers && LB::is_arithmetic) {
127 if(f.is(F::E)) {
128 auto sort = f.sort();
129 if(sort.has_value() && sort->is_bool()) {
130 k.meet(local_type(LB::geq_k(LB::pre_universe::zero()), UB::leq_k(UB::pre_universe::one())));
131 return true;
132 }
133 }
134 }
135 return CP::template interpret_tell<diagnose>(f, env, k.cp, diagnostics);
136 }
137
138 /** Support the same language than the Cartesian product, and more:
139 * * `x != k` is under-approximated by interpreting `x != k` in the lower bound.
140 * * `x == k` is interpreted by over-approximating `x == k` in both bounds and then verifying both bounds are the same.
141 * * `x in {[l..u]} is interpreted by under-approximating `x >= l` and `x <= u`. */
142 template<bool diagnose = false, class F, class Env, class U2>
143 CUDA NI static bool interpret_ask(const F& f, const Env& env, Interval<U2>& k, IDiagnostics& diagnostics) {
145 if(f.is_binary() && f.sig() == NEQ) {
146 return LB::template interpret_ask<diagnose>(f, env, k.lb(), diagnostics);
147 }
148 else if(f.is_binary() && f.sig() == EQ) {
150 "When interpreting equality, the underlying bounds LB and UB failed to agree on the same value.",
151 (LB::template interpret_tell<diagnose>(f, env, itv.lb(), diagnostics) &&
152 UB::template interpret_tell<diagnose>(f, env, itv.ub(), diagnostics) &&
153 itv.lb() == itv.ub()),
154 (k.meet(itv)));
155 }
156 else if(f.is_binary() && f.sig() == IN && f.seq(0).is_variable()
157 && f.seq(1).is(F::S) && f.seq(1).s().size() == 1)
158 {
159 const auto& lb = battery::get<0>(f.seq(1).s()[0]);
160 const auto& ub = battery::get<1>(f.seq(1).s()[0]);
161 if(lb == ub) {
163 "Failed to interpret the decomposition of set membership `x in {[v..v]}` into equality `x == v`.",
164 (interpret_ask<diagnose>(F::make_binary(f.seq(0), EQ, lb), env, k, diagnostics)));
165 }
167 "Failed to interpret the decomposition of set membership `x in {[l..u]}` into `x >= l /\\ x <= u`.",
168 (LB::template interpret_ask<diagnose>(F::make_binary(f.seq(0), geq_of_constant(lb), lb), env, itv.lb(), diagnostics) &&
169 UB::template interpret_ask<diagnose>(F::make_binary(f.seq(0), leq_of_constant(ub), ub), env, itv.ub(), diagnostics)),
170 (k.meet(itv))
171 );
172 }
173 return CP::template interpret_ask<diagnose>(f, env, k.cp, diagnostics);
174 }
175
176 template<IKind kind, bool diagnose = false, class F, class Env, class U2>
177 CUDA NI static bool interpret(const F& f, const Env& env, Interval<U2>& k, IDiagnostics& diagnostics) {
178 if constexpr(kind == IKind::ASK) {
179 return interpret_ask<diagnose>(f, env, k, diagnostics);
180 }
181 else {
182 return interpret_tell<diagnose>(f, env, k, diagnostics);
183 }
184 }
185
186 /** You must use the lattice interface (join/meet methods) to modify the lower and upper bounds, if you use assignment you violate the PCCP model. */
187 CUDA constexpr LB& lb() { return cp.template project<0>(); }
188 CUDA constexpr UB& ub() { return cp.template project<1>(); }
189
190 CUDA constexpr const LB& lb() const { return cp.template project<0>(); }
191 CUDA constexpr const UB& ub() const { return cp.template project<1>(); }
192
193 CUDA constexpr void join_top() {
194 cp.join_top();
195 }
196
197 template<class A>
198 CUDA constexpr bool join_lb(const A& lb) {
199 return cp.template join<0>(lb);
200 }
201
202 template<class A>
203 CUDA constexpr bool join_ub(const A& ub) {
204 return cp.template join<1>(ub);
205 }
206
207 template<class A>
208 CUDA constexpr bool join(const Interval<A>& other) {
209 return cp.join(other.cp);
210 }
211
212 CUDA constexpr void meet_bot() {
213 cp.meet_bot();
214 }
215
216 template<class A>
217 CUDA constexpr bool meet_lb(const A& lb) {
218 return cp.template meet<0>(lb);
219 }
220
221 template<class A>
222 CUDA constexpr bool meet_ub(const A& ub) {
223 return cp.template meet<1>(ub);
224 }
225
226 template<class A>
227 CUDA constexpr bool meet(const Interval<A>& other) {
228 return cp.meet(other.cp);
229 }
230
231 template <class A>
232 CUDA constexpr bool extract(Interval<A>& ua) const {
233 return cp.extract(ua.cp);
234 }
235
236 template<class Env, class Allocator = typename Env::allocator_type>
237 CUDA TFormula<Allocator> deinterpret(AVar x, const Env& env, const Allocator& allocator = Allocator()) const {
238 using F = TFormula<Allocator>;
239 if(is_bot()) {
240 return F::make_false();
241 }
242 if(lb().is_top() || ub().is_top() || lb().is_bot() || ub().is_bot()) {
243 return cp.deinterpret(x, env);
244 }
245 F logical_lb = lb().template deinterpret<F>();
246 F logical_ub = ub().template deinterpret<F>();
247 logic_set<F> logical_set(1, allocator);
248 logical_set[0] = battery::make_tuple(std::move(logical_lb), std::move(logical_ub));
249 F set = F::make_set(std::move(logical_set));
250 F var = F::make_avar(x);
251 return F::make_binary(var, IN, std::move(set), UNTYPED, allocator);
252 }
253
254 /** Deinterpret the current value to a logical constant.
255 * The lower bound is deinterpreted, and it is up to the user to check that interval is a singleton.
256 * A special case is made for real numbers where the both bounds are used, since the logical interpretation uses interval.
257 */
258 template<class F>
259 CUDA NI F deinterpret() const {
260 F logical_lb = lb().template deinterpret<F>();
261 if(logical_lb.is(F::R)) {
262 F logical_ub = ub().template deinterpret<F>();
263 battery::get<1>(logical_lb.r()) = battery::get<0>(logical_ub.r());
264 }
265 else {
266 assert(lb() == dual<LB>(ub()));
267 }
268 return logical_lb;
269 }
270
271 CUDA NI void print() const {
272 printf("[");
273 lb().print();
274 printf("..");
275 ub().print();
276 printf("]");
277 }
278
279 /** The additive inverse is obtained by pairwise negation of the components.
280 * Equivalent to `neg(reverse(x))`.
281 * Note that the inverse of `bot` is `bot`, simply because `bot` has no mathematical inverse. */
282 CUDA constexpr void additive_inverse(const this_type& x) {
283 flat_fun(NEG, x);
284 }
285
286 template<class L>
287 CUDA constexpr static local_type reverse(const Interval<L>& x) {
288 return local_type(dual<LB2>(x.ub()), dual<UB2>(x.lb()));
289 }
290
291 CUDA constexpr void neg(const local_type& x) {
292 flat_fun(NEG, reverse(x));
293 }
294
295 // This operation preserves top, i.e., \f$ abs(x) \in [\top] \f$ if \f$ x \in [\top] \f$, \f$ [\top] \f$ being the equivalence class of top elements.
296 CUDA constexpr void abs(const local_type& x) {
297 local_type nx{};
298 nx.neg(x);
299 nx.meet_lb(LB2::geq_k(LB2::pre_universe::zero()));
300 meet_lb(fmeet(x.lb(), nx.lb()));
301 meet_ub(fjoin(x.ub(), nx.ub()));
302 }
303
304 CUDA constexpr void project(Sig fun, const local_type& x) {
305 switch(fun) {
306 case NEG: neg(x); break;
307 case ABS: abs(x); break;
308 }
309 }
310
311 CUDA constexpr void add(const local_type& x, const local_type& y) {
312 flat_fun(ADD, x, y);
313 }
314
315 CUDA constexpr void sub(const local_type& x, const local_type& y) {
316 local_type ny{};
317 ny.neg(y);
318 add(x, ny);
319 }
320
321private:
322 /** Characterization of the sign of the bounds (e.g., NP = lower bound is negative, upper bound is positive).
323 * It can viewed as a lattice with the order NP < PP < PN and NP < NN < PN. */
324 enum bounds_sign {
325 PP, NN, NP, PN
326 };
327
328 /** The sign function is monotone w.r.t. the order of `Interval<A>` and `bounds_sign`. */
329 template<class A>
330 CUDA constexpr static bounds_sign sign(const Interval<A>& a) {
331 if(a.lb() >= LB2::geq_k(LB2::pre_universe::zero())) {
332 if(a.ub() > UB2::leq_k(UB2::pre_universe::zero())) {
333 return PN;
334 }
335 else {
336 return PP;
337 }
338 }
339 else {
340 if(a.ub() >= UB2::leq_k(UB2::pre_universe::zero())) {
341 return NN;
342 }
343 else {
344 return NP;
345 }
346 }
347 }
348
349 /** This is a generic implementation of interval piecewise monotone function, where the function is monotone for each pair of bounds.
350 * Let `fun` be a monotone binary operation such as multiplication: [rl..ru] = [al..au] * [bl..bu]
351 where:
352 (1) rl = min(al*bl, al*bu, au*bl, au*bu)
353 (2) ru = max(al*bl, al*bu, au*bl, au*bu)
354 In the discrete case, we can precompute the products in `l` and `u`.
355 Otherwise, due to rounding, al*bl can be rounded downwards or upwards, and therefore must be computed differently for (1) and (2).
356
357 We do not check if a and b are bot. This is the responsibility of the caller depending if it could pose issues with the function `fun`.
358 */
359 CUDA constexpr void piecewise_monotone_fun(Sig fun, const local_type& a, const local_type& b) {
360 using PLB = typename LB::pre_universe;
361 using PUB = typename UB::pre_universe;
362 using value_t = typename PUB::value_type;
364 value_t x1 = PUB::project(fun, a.lb().value(), b.lb().value());
365 value_t x2 = PUB::project(fun, a.lb().value(), b.ub().value());
366 value_t x3 = PUB::project(fun, a.ub().value(), b.lb().value());
367 value_t x4 = PUB::project(fun, a.ub().value(), b.ub().value());
368 meet_lb(LB(PLB::join(PLB::join(x1, x2), PLB::join(x3, x4))));
369 meet_ub(UB(PUB::join(PUB::join(x1, x2), PUB::join(x3, x4))));
370 }
371 else {
372 value_t x1 = PLB::project(fun, a.lb().value(), b.lb().value());
373 value_t x2 = PLB::project(fun, a.lb().value(), b.ub().value());
374 value_t x3 = PLB::project(fun, a.ub().value(), b.lb().value());
375 value_t x4 = PLB::project(fun, a.ub().value(), b.ub().value());
376 meet_lb(LB(PLB::join(PLB::join(x1, x2), PLB::join(x3, x4))));
377
378 x1 = PUB::project(fun, a.lb().value(), b.lb().value());
379 x2 = PUB::project(fun, a.lb().value(), b.ub().value());
380 x3 = PUB::project(fun, a.ub().value(), b.lb().value());
381 x4 = PUB::project(fun, a.ub().value(), b.ub().value());
382 meet_ub(UB(PUB::join(PUB::join(x1, x2), PUB::join(x3, x4))));
383 }
384 }
385
386public:
387 CUDA constexpr void mul(const local_type& a, const local_type& b) {
388 if(a.is_bot() || b.is_bot()) { meet_bot(); return; } // Perhaps not necessary?
389 piecewise_monotone_fun(MUL, a, b);
390 }
391
392 // Interval division, [al..au] / [bl..bu]
393 CUDA constexpr void div(Sig divfun, const local_type& a, const local_type& b) {
394 constexpr auto zero = LB2::pre_universe::zero();
395 using flat_type = LB2::local_flat_type;
396 constexpr auto fzero = flat_type::eq_k(zero);
397 if(a.is_bot() || b.is_bot() || (b.lb().value() == zero && b.ub().value() == zero)) { meet_bot(); return; }
398 // Interval division, [rl..ru] = [al..au] / [bl..bu]
399 if constexpr(preserve_concrete_covers) {
400 // Remove 0 from the bounds of b if any is equal to it.
401 piecewise_monotone_fun(divfun, a,
402 local_type((b.lb().value() == zero) ? LB2(1) : b.lb(),
403 (b.ub().value() == zero) ? UB2(-1) : b.ub()));
404 }
405 else {
406 flat_type al(a.lb());
407 flat_type au(a.ub());
408 flat_type bl(b.lb());
409 flat_type bu(b.ub());
410
411 // The case where 0 in [bl, bu].
412 if(bl <= fzero && bu >= fzero) {
413 if(bl == fzero && bu == fzero) { meet_bot(); return; } // b is a singleton equal to zero.
414 if(al == fzero && au == fzero) { meet_lb(LB2::geq_k(zero)); meet_ub(UB2::leq_k(zero)); return; } // 0 / b = 0 (b != 0)
415 if(bl == fzero) { lb().project(divfun, al, bu); return; } // If bl is 0, then the upper bound is infinite.
416 ub().project(divfun, al, bl); // if bu is 0, then the lower bound is infinite.
417 return;
418 }
419 else {
420 piecewise_monotone_fun(divfun, a, b);
421 }
422 }
423 }
424
425 CUDA constexpr void mod(Sig modfun, const local_type& a, const local_type& b) {
426 if(a.is_bot() || b.is_bot()) { meet_bot(); return; }
427 if(a.lb() == dual<LB2>(a.ub()) && b.lb() == dual<LB2>(b.ub())) {
428 flat_fun(modfun, a, b);
429 }
430 }
431
432 CUDA constexpr void pow(const local_type& a, const local_type& b) {
433 if(a.is_bot() || b.is_bot()) { meet_bot(); return; }
434 if(a.lb() == dual<LB2>(a.ub()) && b.lb() == dual<LB2>(b.ub())) {
435 flat_fun(POW, a, b);
436 }
437 }
438
439 CUDA static constexpr bool is_trivial_fun(Sig fun) {
440 return LB2::is_trivial_fun(fun) && UB2::is_trivial_fun(fun)
441 && fun != MUL && !is_division(fun) && fun != ABS && fun != SUB && fun != POW && !is_modulo(fun);
442 }
443
444 CUDA constexpr void project(Sig fun, const local_type& x, const local_type& y) {
445 if(LB2::is_order_preserving_fun(fun) && UB2::is_order_preserving_fun(fun)) {
446 cp.project(fun, x.as_product(), y.as_product());
447 }
448 else if constexpr(LB::is_arithmetic) {
449 if (fun == SUB) { sub(x, y); }
450 else if (fun == MUL) { mul(x, y); }
451 else if (is_division(fun)) { div(fun, x, y); }
452 else if (is_modulo(fun)) { mod(fun, x, y); }
453 else if (fun == POW) { pow(x, y); }
454 }
455 }
456
457 CUDA constexpr local_type width() const {
458 static_assert(LB::is_totally_ordered && LB::is_arithmetic,
459 "Width is only defined for totally ordered arithmetic intervals.");
461 width.sub(ub2(), lb2());
462 return width;
463 }
464
465 /** \return The median value of the interval, which is computed by `lb() + ((ub() - lb()) / 2)`. */
466 CUDA constexpr local_type median() const {
467 static_assert(LB::is_totally_ordered && LB::is_arithmetic,
468 "Median function is only defined for totally ordered arithmetic intervals.");
469 if(is_bot()) { return local_type::bot(); }
470 if(lb().is_top() || ub().is_top()) { return local_type::top(); }
471 auto l = lb().value();
472 auto u = ub().value();
473 return local_type(l + battery::fdiv((u - l), 2), l + battery::cdiv((u - l), 2));
474 }
475};
476
477// Lattice operations
478
479template<class L, class K>
480CUDA constexpr auto fjoin(const Interval<L>& a, const Interval<K>& b)
481{
482 if(a.is_bot()) { return b; }
483 if(b.is_bot()) { return a; }
484 return impl::make_itv(fjoin(a.as_product(), b.as_product()));
485}
486
487template<class L, class K>
488CUDA constexpr auto fmeet(const Interval<L>& a, const Interval<K>& b)
489{
490 return impl::make_itv(fmeet(a.as_product(), b.as_product()));
491}
492
493template<class L, class K>
494CUDA constexpr bool operator<=(const Interval<L>& a, const Interval<K>& b)
495{
496 return a.is_bot() || a.as_product() <= b.as_product();
497}
498
499template<class L, class K>
500CUDA constexpr bool operator<(const Interval<L>& a, const Interval<K>& b)
501{
502 return (a.is_bot() && !b.is_bot()) || a.as_product() < b.as_product();
503}
504
505template<class L, class K>
506CUDA constexpr bool operator>=(const Interval<L>& a, const Interval<K>& b)
507{
508 return b <= a;
509}
510
511template<class L, class K>
512CUDA constexpr bool operator>(const Interval<L>& a, const Interval<K>& b)
513{
514 return b < a;
515}
516
517template<class L, class K>
518CUDA constexpr bool operator==(const Interval<L>& a, const Interval<K>& b)
519{
520 return a.as_product() == b.as_product() || (a.is_bot() && b.is_bot());
521}
522
523template<class L, class K>
524CUDA constexpr bool operator!=(const Interval<L>& a, const Interval<K>& b)
525{
526 return a.as_product() != b.as_product() && !(a.is_bot() && b.is_bot());
527}
528
529template<class L>
530std::ostream& operator<<(std::ostream &s, const Interval<L> &itv) {
531 return s << "[" << itv.lb() << ".." << itv.ub() << "]";
532}
533
534} // namespace lala
535
536#endif
Definition ast.hpp:38
Definition b.hpp:10
Definition cartesian_product.hpp:62
CUDA constexpr bool join(const CartesianProduct< Bs... > &other)
Definition cartesian_product.hpp:276
CUDA TFormula< Allocator > deinterpret(AVar x, const Env &env, const Allocator &allocator=Allocator()) const
Definition cartesian_product.hpp:386
CUDA constexpr bool extract(CartesianProduct< Bs... > &ua) const
Definition cartesian_product.hpp:301
CUDA constexpr local::B is_bot() const
Definition cartesian_product.hpp:214
CUDA constexpr local::B is_top() const
Definition cartesian_product.hpp:207
CUDA constexpr type_of< i > & project()
Definition cartesian_product.hpp:193
CUDA constexpr value_type value() const
Definition cartesian_product.hpp:202
static constexpr const bool injective_concretization
Definition cartesian_product.hpp:83
CUDA constexpr bool meet(const CartesianProduct< Bs... > &other)
Definition cartesian_product.hpp:290
CUDA constexpr void meet_bot()
Definition cartesian_product.hpp:285
static constexpr const bool sequential
Definition cartesian_product.hpp:77
CUDA constexpr void join_top()
Definition cartesian_product.hpp:271
battery::tuple< typename As::value_type... > value_type
Definition cartesian_product.hpp:74
static CUDA constexpr local_type top()
Definition cartesian_product.hpp:122
typename type_of< 0 >::memory_type memory_type
Definition cartesian_product.hpp:70
static constexpr const bool preserve_concrete_covers
Definition cartesian_product.hpp:84
static constexpr const bool preserve_top
Definition cartesian_product.hpp:80
static CUDA constexpr local_type bot()
Definition cartesian_product.hpp:117
Definition diagnostics.hpp:19
Definition interval.hpp:32
CUDA constexpr this_type & operator=(const this_type &other)
Definition interval.hpp:86
CUDA constexpr bool meet(const Interval< A > &other)
Definition interval.hpp:227
typename LB::dual_type UB
Definition interval.hpp:35
typename CP::value_type value_type
Definition interval.hpp:39
CUDA static NI bool interpret(const F &f, const Env &env, Interval< U2 > &k, IDiagnostics &diagnostics)
Definition interval.hpp:177
CUDA constexpr bool meet_ub(const A &ub)
Definition interval.hpp:222
CUDA static constexpr local_type eq_one()
Definition interval.hpp:94
CUDA static constexpr local_type bot()
Definition interval.hpp:96
CUDA constexpr void mul(const local_type &a, const local_type &b)
Definition interval.hpp:387
static constexpr const bool sequential
Definition interval.hpp:46
CUDA constexpr bool extract(Interval< A > &ua) const
Definition interval.hpp:232
CUDA static constexpr local_type reverse(const Interval< L > &x)
Definition interval.hpp:287
CUDA constexpr Interval()
Definition interval.hpp:67
CUDA constexpr void mod(Sig modfun, const local_type &a, const local_type &b)
Definition interval.hpp:425
CUDA constexpr UB & ub()
Definition interval.hpp:188
static constexpr const bool is_arithmetic
Definition interval.hpp:55
static constexpr const bool injective_concretization
Definition interval.hpp:52
static constexpr const bool preserve_concrete_covers
Definition interval.hpp:53
CUDA constexpr local::B is_bot() const
Definition interval.hpp:98
CUDA constexpr void div(Sig divfun, const local_type &a, const local_type &b)
Definition interval.hpp:393
static CUDA constexpr bool is_trivial_fun(Sig fun)
Definition interval.hpp:439
CUDA constexpr void project(Sig fun, const local_type &x)
Definition interval.hpp:304
CUDA constexpr bool join_ub(const A &ub)
Definition interval.hpp:203
typename CP::memory_type memory_type
Definition interval.hpp:40
CUDA constexpr void additive_inverse(const this_type &x)
Definition interval.hpp:282
CUDA constexpr bool join(const Interval< A > &other)
Definition interval.hpp:208
static constexpr const bool is_totally_ordered
Definition interval.hpp:47
U LB
Definition interval.hpp:34
static constexpr const char * name
Definition interval.hpp:56
CUDA static constexpr local_type eq_zero()
Definition interval.hpp:92
static constexpr const bool preserve_top
Definition interval.hpp:48
static constexpr const bool preserve_join
Definition interval.hpp:51
CUDA constexpr Interval(const typename U::value_type &x)
Definition interval.hpp:69
CUDA constexpr const UB & ub() const
Definition interval.hpp:191
CUDA constexpr void pow(const local_type &a, const local_type &b)
Definition interval.hpp:432
CUDA NI void print() const
Definition interval.hpp:271
CUDA TFormula< Allocator > deinterpret(AVar x, const Env &env, const Allocator &allocator=Allocator()) const
Definition interval.hpp:237
static constexpr const bool preserve_meet
Definition interval.hpp:50
Interval< typename LB::local_type > local_type
Definition interval.hpp:37
CUDA constexpr Interval(const LB &lb, const UB &ub)
Definition interval.hpp:70
CUDA static constexpr local_type top()
Definition interval.hpp:97
CUDA constexpr void meet_bot()
Definition interval.hpp:212
CUDA constexpr void add(const local_type &x, const local_type &y)
Definition interval.hpp:311
CUDA constexpr void join_top()
Definition interval.hpp:193
CUDA constexpr void abs(const local_type &x)
Definition interval.hpp:296
static constexpr const bool is_abstract_universe
Definition interval.hpp:45
CUDA constexpr void project(Sig fun, const local_type &x, const local_type &y)
Definition interval.hpp:444
CUDA static NI bool interpret_ask(const F &f, const Env &env, Interval< U2 > &k, IDiagnostics &diagnostics)
Definition interval.hpp:143
CUDA constexpr local_type width() const
Definition interval.hpp:457
static constexpr const bool complemented
Definition interval.hpp:54
CUDA constexpr local_type median() const
Definition interval.hpp:466
CUDA constexpr value_type value() const
Definition interval.hpp:101
friend class Interval
Definition interval.hpp:43
CUDA constexpr void sub(const local_type &x, const local_type &y)
Definition interval.hpp:315
CUDA constexpr bool join_lb(const A &lb)
Definition interval.hpp:198
CUDA constexpr local::B is_top() const
Definition interval.hpp:99
CUDA NI F deinterpret() const
Definition interval.hpp:259
CUDA constexpr LB & lb()
Definition interval.hpp:187
CUDA constexpr Interval(const Interval< A > &other)
Definition interval.hpp:73
CUDA constexpr Interval(Interval< A > &&other)
Definition interval.hpp:76
CUDA constexpr void neg(const local_type &x)
Definition interval.hpp:291
CUDA constexpr this_type & operator=(const Interval< A > &other)
Definition interval.hpp:81
CUDA constexpr bool meet_lb(const A &lb)
Definition interval.hpp:217
CUDA static NI bool interpret_tell(const F &f, const Env &env, Interval< U2 > &k, IDiagnostics &diagnostics)
Definition interval.hpp:125
CUDA constexpr const CP & as_product() const
Definition interval.hpp:100
CUDA constexpr const LB & lb() const
Definition interval.hpp:190
static constexpr const bool preserve_bot
Definition interval.hpp:49
Definition ast.hpp:234
#define CALL_WITH_ERROR_CONTEXT(MSG, CALL)
Definition diagnostics.hpp:180
#define CALL_WITH_ERROR_CONTEXT_WITH_MERGE(MSG, CALL, MERGE)
Definition diagnostics.hpp:167
Definition abstract_deps.hpp:14
std::ostream & operator<<(std::ostream &s, const CartesianProduct< A, As... > &cp)
Definition cartesian_product.hpp:530
battery::vector< battery::tuple< F, F >, typename F::allocator_type > logic_set
Definition sort.hpp:127
CUDA constexpr LDual dual(const L &x)
Definition arith_bound.hpp:110
CUDA constexpr auto fjoin(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:463
CUDA constexpr bool operator==(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:503
Sig
Definition ast.hpp:94
@ NEQ
Equality relations.
Definition ast.hpp:112
@ EQ
Unary arithmetic function symbols.
Definition ast.hpp:112
@ ADD
Unary arithmetic function symbols.
Definition ast.hpp:97
@ IN
Set membership predicate.
Definition ast.hpp:108
@ POW
Unary arithmetic function symbols.
Definition ast.hpp:97
@ ABS
Unary arithmetic function symbols.
Definition ast.hpp:96
@ SUB
Unary arithmetic function symbols.
Definition ast.hpp:97
@ MUL
Unary arithmetic function symbols.
Definition ast.hpp:97
@ NEG
Unary arithmetic function symbols.
Definition ast.hpp:96
CUDA Sig leq_of_constant(const TFormula< Allocator > &f)
Definition algorithm.hpp:60
CUDA constexpr bool operator<(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:484
CUDA NI constexpr bool is_division(Sig sig)
Definition ast.hpp:196
CUDA constexpr auto fmeet(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:470
CUDA constexpr bool operator>(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:497
CUDA constexpr auto meet(const Interval< L > &, const Interval< K > &)
CUDA Sig geq_of_constant(const TFormula< Allocator > &f)
Definition algorithm.hpp:53
CUDA NI constexpr bool is_modulo(Sig sig)
Definition ast.hpp:200
CUDA constexpr const CartesianProduct< As... >::template type_of< i > & project(const CartesianProduct< As... > &cp)
Similar to cp.template project<i>(), just to avoid the ".template" syntax.
Definition cartesian_product.hpp:412
#define UNTYPED
Definition sort.hpp:21