Lattice Land Core Library
Loading...
Searching...
No Matches
nbitset.hpp
Go to the documentation of this file.
1// Copyright 2024 Pierre Talbot
2
3#ifndef LALA_CORE_NBITSET_HPP
4#define LALA_CORE_NBITSET_HPP
5
6#include "arith_bound.hpp"
7#include "battery/bitset.hpp"
8
9namespace lala {
10
11/** This class represents a set of integer values with a fixed-size bitset.
12 * In order to have well-defined arithmetic operations preserving bottom and top elements, the first and last bits (written L and R below) of the bitset are reserved.
13 * The meaning of L is to include all negative integers and the meaning of R is to include all integers greater than the size of the bitset.
14 * Given a bitset \f$ Lb_0b_1...b_nR \f$ of size n + 3, the concretization function is given as follows:
15 * \f$ \gamma(Lb_0b_1...b_nR) = \{ i \in \mathbb{Z} \mid 0 \leq i \leq n \land b_i = 1 \} \cup \{ i \in \mathbb{Z} \;|\; i < 0 \land L = 1 \} \cup \{ i \in \mathbb{Z} \;|\; i > n \land R = 1 \} \f$
16 */
17template <size_t N, class Mem, class T = unsigned long long>
19{
20public:
21 using memory_type = Mem;
22 using bitset_type = battery::bitset<N, Mem, T>;
24 template <class M> using this_type2 = NBitset<N, M, T>;
26
27 using LB = local::ZLB;
28 using UB = local::ZUB;
29 using value_type = typename LB::value_type;
30
31 template <size_t N2, class Mem2, class T2>
32 friend class NBitset;
33
34 constexpr static const bool is_abstract_universe = true;
35 constexpr static const bool sequential = Mem::sequential;
36 constexpr static const bool is_totally_ordered = false;
37 constexpr static const bool preserve_bot = true;
38 constexpr static const bool preserve_top = true;
39 constexpr static const bool preserve_join = true;
40 constexpr static const bool preserve_meet = true;
41 constexpr static const bool injective_concretization = true;
42 constexpr static const bool preserve_concrete_covers = false;
43 constexpr static const bool complemented = true;
44 constexpr static const bool is_arithmetic = true;
45 constexpr static const char* name = "NBitset";
46
47private:
48 bitset_type bits;
49
50 struct bot_constructor_tag {};
51 CUDA constexpr NBitset(bot_constructor_tag) {}
52
53public:
54 /** Initialize to top (all bits at `1`). */
55 CUDA constexpr NBitset() {
56 bits.set();
57 }
58
59 CUDA constexpr static this_type from_set(const battery::vector<int>& values) {
60 this_type b(bot());
61 for(int i = 0; i < values.size(); ++i) {
62 b.bits.set(battery::min(static_cast<int>(N)-1, battery::max(values[i]+1,0)), true);
63 }
64 return b;
65 }
66
67 CUDA constexpr NBitset(const this_type& other): NBitset(other.bits) {}
68 constexpr NBitset(this_type&&) = default;
69
70 /** Given a value \f$ x \in U \f$ where \f$ U \f$ is the universe of discourse, we initialize a singleton bitset \f$ 0_0..1_{x+1}...0_n \f$. */
71 CUDA constexpr NBitset(value_type x) {
72 bits.set(battery::min(static_cast<int>(N)-1, battery::max(0, x+1)));
73 }
74
75 CUDA constexpr NBitset(value_type lb, value_type ub): bits(
76 battery::min(static_cast<int>(N)-1, battery::max(lb+1,0)),
77 battery::min(static_cast<int>(N)-1, battery::max(ub+1, 0)))
78 {}
79
80 template<class M>
81 CUDA constexpr NBitset(const this_type2<M>& other): bits(other.bits) {}
82
83 template<class M>
84 CUDA constexpr NBitset(this_type2<M>&& other): bits(std::move(other.bits)) {}
85
86 template<class M>
87 CUDA constexpr NBitset(const battery::bitset<N, M, T>& bits): bits(bits) {}
88
89 /** The assignment operator can only be used in a sequential context.
90 * It is monotone but not extensive. */
91 template <class M>
92 CUDA constexpr this_type& operator=(const this_type2<M>& other) {
93 bits = other.bits;
94 return *this;
95 }
96
97 CUDA constexpr this_type& operator=(const this_type& other) {
98 bits = other.bits;
99 return *this;
100 }
101
102 /** Pre-interpreted formula `x == 0`. */
103 CUDA constexpr static local_type eq_zero() { return local_type(0); }
104 /** Pre-interpreted formula `x == 1`. */
105 CUDA constexpr static local_type eq_one() { return local_type(1); }
106
107 CUDA constexpr static local_type bot() { return NBitset(bot_constructor_tag{}); }
108 CUDA constexpr static local_type top() { return NBitset(); }
109 CUDA constexpr local::B is_top() const { return bits.all(); }
110 CUDA constexpr local::B is_bot() const { return bits.none(); }
111 CUDA constexpr const bitset_type& value() const { return bits; }
112
113private:
114 template<bool diagnose, class F, class Env, class M>
115 CUDA NI static bool interpret_existential(const F& f, const Env& env, this_type2<M>& k, IDiagnostics& diagnostics) {
116 const auto& sort = battery::get<1>(f.exists());
117 if(sort.is_int()) {
118 return true;
119 }
120 else if(sort.is_bool()) {
121 k.meet(local_type(0,1));
122 return true;
123 }
124 else {
125 const auto& vname = battery::get<0>(f.exists());
126 RETURN_INTERPRETATION_ERROR(("NBitset only supports variables of type `Int` or `Bool`, but `" + vname + "` has another sort."));
127 }
128 }
129
130 template<bool diagnose, bool negated, class F, class M>
131 CUDA NI static bool interpret_tell_set(const F& f, const F& k, this_type2<M>& tell, IDiagnostics& diagnostics) {
132 using sort_type = Sort<typename F::allocator_type>;
133 std::optional<sort_type> sort = f.seq(1).sort();
134 if(sort.has_value() &&
135 (sort.value() == sort_type(sort_type::Set, sort_type(sort_type::Int))
136 || sort.value() == sort_type(sort_type::Set, sort_type(sort_type::Bool))))
137 {
138 const auto& set = f.seq(1).s();
139 local_type join_s(bot_constructor_tag{});
140 bool over_appx = false;
141 for(int i = 0; i < set.size(); ++i) {
142 int l = battery::get<0>(set[i]).to_z();
143 int u = battery::get<1>(set[i]).to_z();
144 join_s.join(local_type(l, u));
145 if(l < 0 || u >= join_s.bits.size() - 2) {
146 over_appx = true;
147 }
148 }
149 if constexpr(negated) {
150 join_s = join_s.complement();
151 // In any case it must be set to true: if no element is below zero, then some elements in the negation are; and if some elements are below zero it's not all of them.
152 join_s.bits.set(0, true);
153 join_s.bits.set(join_s.bits.size()-1, true);
154 }
155 tell.meet(join_s);
156 if(over_appx) {
157 RETURN_INTERPRETATION_WARNING("Constraint `x in S` is over-approximated because some elements of `S` fall outside the bitset.");
158 }
159 return true;
160 }
161 else {
162 RETURN_INTERPRETATION_ERROR("NBitset only supports membership (`x in S`) where `S` is a set of integers.");
163 }
164 }
165
166 template<bool diagnose, class F, class M>
167 CUDA NI static bool interpret_tell_x_op_k(const F& f, logic_int k, Sig sig, this_type2<M>& tell, IDiagnostics& diagnostics) {
168 if(sig == LT) {
169 return interpret_tell_x_op_k<diagnose>(f, k-1, LEQ, tell, diagnostics);
170 }
171 else if(sig == GT) {
172 return interpret_tell_x_op_k<diagnose>(f, k+1, GEQ, tell, diagnostics);
173 }
174 else if(k < 0 || k >= tell.bits.size() - 2) {
175 if((k == -1 && sig == LEQ) || (k == tell.bits.size() - 2 && sig == GEQ)) {
176 // this is fine because x <= -1 and x >= n-2 can be represented exactly.
177 }
178 else {
179 INTERPRETATION_WARNING("Constraint `x <op> k` is over-approximated because `k` is not representable in the bitset. Note that for a bitset of size `n`, the only values representable exactly are in the interval `[0, n-3]` because two bits are used to represent all negative values and all values exceeding the size of the bitset.");
180 // If it is NEQ, we can't give a better approximation than top.
181 if(sig == NEQ) {
182 return true;
183 }
184 }
185 }
186 switch(sig) {
187 case EQ: tell.meet(local_type(k, k)); break;
188 case NEQ: tell.meet(local_type(k, k).complement()); break;
189 case LEQ: tell.meet(local_type(-1, k)); break;
190 case GEQ: tell.meet(local_type(k, tell.bits.size())); break;
191 default: RETURN_INTERPRETATION_ERROR("This symbol is not supported.");
192 }
193 return true;
194 }
195
196 template<bool diagnose, bool negated, class F, class Env, class M>
197 CUDA NI static bool interpret_binary(const F& f, const Env& env, this_type2<M>& tell, IDiagnostics& diagnostics) {
198 if(f.sig() == IN) {
199 return interpret_tell_set<diagnose, negated>(f, f.seq(1), tell, diagnostics);
200 }
201 else if(f.seq(1).is(F::Z) || f.seq(1).is(F::B)) {
202 return interpret_tell_x_op_k<diagnose>(f, f.seq(1).to_z(), f.sig(), tell, diagnostics);
203 }
204 else {
205 RETURN_INTERPRETATION_ERROR("Only integer and Boolean constants are supported in NBitset.");
206 }
207 }
208
209public:
210 /** Support the following language where all constants `k` are integer or Boolean values:
211 * * `var x:Z`
212 * * `var x:B`
213 * * `x <op> k` where `k` is an integer constant and `<op>` in {==, !=, <, <=, >, >=}.
214 * * `x in S` where `S` is a set of integers.
215 * It can be over-approximated if the element `k` falls out of the bitset. */
216 template<bool diagnose = false, class F, class Env, class M>
217 CUDA NI static bool interpret_tell(const F& f, const Env& env, this_type2<M>& tell, IDiagnostics& diagnostics) {
218 using sort_type = Sort<typename F::allocator_type>;
219 if(f.is(F::E)) {
220 return interpret_existential<diagnose>(f, env, tell, diagnostics);
221 }
222 else if(f.is_unary() && f.sig() == NOT && f.seq(0).is_binary()) {
223 return interpret_binary<diagnose, true>(f.seq(0), env, tell, diagnostics);
224 }
225 else if(f.is_binary() && f.seq(0).is_variable() && f.seq(1).is_constant()) {
226 return interpret_binary<diagnose, false>(f, env, tell, diagnostics);
227 }
228 else {
229 RETURN_INTERPRETATION_ERROR("Only binary formulas of the form `x <sig> k` where if x is a variable and k is a constant are supported. We also supports existential quantifier and membership in a set of integers (x in S).");
230 }
231 }
232
233 /** Support the same language than the "tell language" without existential. */
234 template<bool diagnose = false, class F, class Env, class M>
235 CUDA NI static bool interpret_ask(const F& f, const Env& env, this_type2<M>& k, IDiagnostics& diagnostics) {
237 auto nf = negate(f);
238 if(!nf.has_value()) {
239 RETURN_INTERPRETATION_ERROR("Could not negate the formula in order to interpret_ask it.");
240 }
241 if(f.is(F::E)) {
242 RETURN_INTERPRETATION_ERROR("Existential quantification is not supported in ask interpretation.");
243 }
244 if(interpret_tell<diagnose>(nf.value(), env, b, diagnostics)) {
245 k.meet(b.complement());
246 return true;
247 }
248 else {
249 return false;
250 }
251 }
252
253 template<IKind kind, bool diagnose = false, class F, class Env, class M>
254 CUDA NI static bool interpret(const F& f, const Env& env, this_type2<M>& k, IDiagnostics& diagnostics) {
255 if constexpr(kind == IKind::ASK) {
256 return interpret_ask<diagnose>(f, env, k, diagnostics);
257 }
258 else {
259 return interpret_tell<diagnose>(f, env, k, diagnostics);
260 }
261 }
262
263 CUDA constexpr LB lb() const {
264 value_type l = bits.countr_zero();
265 return l == 0 ? LB::top() :
266 (l == bits.size() ? LB::bot() : LB::geq_k(l-1));
267 }
268
269 CUDA constexpr UB ub() const {
270 value_type r = bits.countl_zero();
271 return r == 0 ? UB::top() :
272 (r == bits.size() ? UB::bot() : UB::leq_k(bits.size() - r - 2));
273 }
274
275 CUDA constexpr local_type complement() const {
276 local_type c(bits);
277 c.bits.flip();
278 return c;
279 }
280
281 CUDA constexpr void join_top() {
282 bits.set();
283 }
284
285 template<class A>
286 CUDA constexpr bool join_lb(const A& lb) {
287 return join(local_type(lb.value(), bits.size()));
288 }
289
290 template<class A>
291 CUDA constexpr bool join_ub(const A& ub) {
292 return join(local_type(-1, ub.value()));
293 }
294
295 template<class M>
296 CUDA constexpr bool join(const this_type2<M>& other) {
297 if(!other.bits.is_subset_of(bits)) {
298 bits |= other.bits;
299 return true;
300 }
301 return false;
302 }
303
304 CUDA constexpr void meet_bot() {
305 bits.reset();
306 }
307
308 template<class A>
309 CUDA constexpr bool meet_lb(const A& lb) {
310 return meet(local_type(lb.value(), bits.size()));
311 }
312
313 template<class A>
314 CUDA constexpr bool meet_ub(const A& ub) {
315 return meet(local_type(-1, ub.value()));
316 }
317
318 template<class M>
319 CUDA constexpr bool meet(const this_type2<M>& other) {
320 if(!bits.is_subset_of(other.bits)) {
321 bits &= other.bits;
322 return true;
323 }
324 return false;
325 }
326
327 template <class M>
328 CUDA constexpr bool extract(this_type2<M>& ua) const {
329 ua.bits = bits;
330 return true;
331 }
332
333 template<class Env, class Allocator = typename Env::allocator_type>
334 CUDA TFormula<Allocator> deinterpret(AVar x, const Env& env, const Allocator& allocator = Allocator()) const {
335 using F = TFormula<Allocator>;
336 if(is_bot()) {
337 return F::make_false();
338 }
339 else if(is_top()) {
340 return F::make_true();
341 }
342 else {
343 typename F::Sequence seq{allocator};
344 if(bits.test(0)) {
345 seq.push_back(F::make_binary(F::make_avar(x), LEQ, F::make_z(-1), UNTYPED, allocator));
346 }
347 if(bits.test(bits.size()-1)) {
348 seq.push_back(F::make_binary(F::make_avar(x), GEQ, F::make_z(bits.size()-2), UNTYPED, allocator));
349 }
350 logic_set<F> logical_set(allocator);
351 for(int i = 1; i < bits.size()-1; ++i) {
352 if(bits.test(i)) {
353 int l = i - 1;
354 for(i = i + 1; i < bits.size()-1 && bits.test(i); ++i) {}
355 int u = i - 2;
356 logical_set.push_back(battery::make_tuple(F::make_z(l), F::make_z(u)));
357 }
358 }
359 if(logical_set.size() > 0) {
360 seq.push_back(F::make_binary(F::make_avar(x), IN, F::make_set(std::move(logical_set)), UNTYPED, allocator));
361 }
362 if(seq.size() == 1) {
363 return std::move(seq[0]);
364 }
365 else {
366 return F::make_nary(OR, std::move(seq));
367 }
368 }
369 }
370
371 /** Deinterpret the current value to a logical constant.
372 * The lower bound is deinterpreted, and it is up to the user to check that interval is a singleton.
373 */
374 template<class F>
375 CUDA NI F deinterpret() const {
376 return lb().template deinterpret<F>();
377 }
378
379 CUDA NI void print() const {
380 printf("{");
381 bool comma_needed = false;
382 if(bits.test(0)) {
383 printf(".., -1");
384 comma_needed = true;
385 }
386 for(int i = 1; i < bits.size() - 1; ++i) {
387 if(bits.test(i)) {
388 if(comma_needed) { printf(", "); }
389 printf("%d", i-1);
390 comma_needed = true;
391 }
392 }
393 if(bits.test(bits.size()-1)) {
394 if(comma_needed) { printf(", "); }
395 printf("%d, ..", static_cast<int>(bits.size())-2);
396 }
397 printf("}");
398 }
399
400 CUDA NI constexpr static bool is_trivial_fun(Sig sig) {
401 switch(sig) {
402 case ABS:
403 case NEG: return false;
404 default: return true;
405 }
406 }
407
408public:
409 CUDA constexpr void neg(const local_type& x) {
410 // if `x` represents all negative numbers, then the negation is all positive numbers.
411 if(x.bits.test(0)) {
412 if(x.bits.count() == 1) {
413 bits.set(0, false);
414 }
415 }
416 else if(x.bits.count() == 0) {
417 meet_bot();
418 }
419 else {
420 meet(local_type(-1));
421 }
422 }
423
424 CUDA constexpr void abs(const local_type& x) {
425 // If the first bit is set, it means all negative numbers are represented, so it only constrains the current value to be positive. Otherwise, we just take the meet with `x`.
426 if(x.bits.test(0)) {
427 bits.set(0, false);
428 }
429 else {
430 meet(x);
431 }
432 }
433
434 CUDA constexpr void project(Sig fun, const local_type& x) {
435 switch(fun) {
436 case NEG: neg(x); break;
437 case ABS: abs(x); break;
438 }
439 }
440
441 CUDA constexpr void additive_inverse(const local_type& x) {
442 printf("%% additive_inverse is unsupported\n");
443 int* ptr = nullptr;
444 ptr[1] = 193;
445 }
446
447 CUDA constexpr void project(Sig fun, const local_type& x, const local_type& y) {
448 printf("%% binary functions %s are unsupported\n", string_of_sig(fun));
449 int* ptr = nullptr;
450 ptr[1] = 193;
451 }
452
453 CUDA constexpr local_type width() const {
454 if(bits.test(0) || bits.test(bits.size() - 1)) { return top(); }
455 else { return local_type(bits.count()); }
456 }
457
458 /** \return The median value of the bitset. */
459 CUDA constexpr local_type median() const {
460 if(is_bot()) { return local_type::bot(); }
461 int total = bits.count();
462 int current = 0;
463 for(int i = 0; i < bits.size(); ++i) {
464 if(bits.test(i)) {
465 ++current;
466 if(current == total/2 || total == 1) {
467 return local_type(i-1);
468 }
469 }
470 }
471 return local_type::bot();
472 }
473};
474
475// Lattice operations
476
477template<size_t N, class M1, class M2, class T>
482
483template<size_t N, class M1, class M2, class T>
488
489template<size_t N, class M1, class M2, class T>
490CUDA constexpr bool operator<=(const NBitset<N, M1, T>& a, const NBitset<N, M2, T>& b)
491{
492 return a.value().is_subset_of(b.value());
493}
494
495template<size_t N, class M1, class M2, class T>
496CUDA constexpr bool operator<(const NBitset<N, M1, T>& a, const NBitset<N, M2, T>& b)
497{
498 return a.value().is_proper_subset_of(b.value());
499}
500
501template<size_t N, class M1, class M2, class T>
502CUDA constexpr bool operator>=(const NBitset<N, M1, T>& a, const NBitset<N, M2, T>& b)
503{
504 return b <= a;
505}
506
507template<size_t N, class M1, class M2, class T>
508CUDA constexpr bool operator>(const NBitset<N, M1, T>& a, const NBitset<N, M2, T>& b)
509{
510 return b < a;
511}
512
513template<size_t N, class M1, class M2, class T>
514CUDA constexpr bool operator==(const NBitset<N, M1, T>& a, const NBitset<N, M2, T>& b)
515{
516 return a.value() == b.value();
517}
518
519template<size_t N, class M1, class M2, class T>
520CUDA constexpr bool operator!=(const NBitset<N, M1, T>& a, const NBitset<N, M2, T>& b)
521{
522 return a.value() != b.value();
523}
524
525template<size_t N, class M, class T>
526std::ostream& operator<<(std::ostream &s, const NBitset<N, M, T> &a) {
527 s << "{";
528 bool comma_needed = false;
529 if(a.value().test(0)) {
530 s << ".., -1";
531 comma_needed = true;
532 }
533 for(int i = 1; i < a.value().size() - 1; ++i) {
534 if(a.value().test(i)) {
535 if(comma_needed) { s << ", "; }
536 s << (i-1);
537 comma_needed = true;
538 }
539 }
540 if(a.value().test(a.value().size()-1)) {
541 if(comma_needed) { s << ", "; }
542 s << a.value().size()-2 << ", ..";
543 }
544 s << "}";
545 return s;
546}
547
548} // end namespace lala
549
550#endif
Definition ast.hpp:38
Definition arith_bound.hpp:118
static CUDA constexpr this_type leq_k(value_type k)
Definition arith_bound.hpp:166
CUDA constexpr value_type value() const
Definition arith_bound.hpp:209
static CUDA constexpr local_type bot()
Definition arith_bound.hpp:182
static CUDA constexpr this_type geq_k(value_type k)
Definition arith_bound.hpp:156
typename pre_universe::value_type value_type
Definition arith_bound.hpp:122
static CUDA constexpr local_type top()
Definition arith_bound.hpp:185
Definition b.hpp:10
Definition diagnostics.hpp:19
Definition nbitset.hpp:19
CUDA static NI bool interpret(const F &f, const Env &env, this_type2< M > &k, IDiagnostics &diagnostics)
Definition nbitset.hpp:254
static constexpr const bool complemented
Definition nbitset.hpp:43
CUDA constexpr bool join_lb(const A &lb)
Definition nbitset.hpp:286
static constexpr const char * name
Definition nbitset.hpp:45
CUDA constexpr void join_top()
Definition nbitset.hpp:281
CUDA constexpr void project(Sig fun, const local_type &x, const local_type &y)
Definition nbitset.hpp:447
battery::bitset< N, Mem, T > bitset_type
Definition nbitset.hpp:22
CUDA static NI bool interpret_tell(const F &f, const Env &env, this_type2< M > &tell, IDiagnostics &diagnostics)
Definition nbitset.hpp:217
friend class NBitset
Definition nbitset.hpp:32
static constexpr const bool preserve_join
Definition nbitset.hpp:39
static constexpr const bool is_abstract_universe
Definition nbitset.hpp:34
CUDA constexpr bool meet_lb(const A &lb)
Definition nbitset.hpp:309
CUDA static constexpr local_type eq_zero()
Definition nbitset.hpp:103
CUDA constexpr NBitset(value_type x)
Definition nbitset.hpp:71
static constexpr const bool preserve_concrete_covers
Definition nbitset.hpp:42
static constexpr const bool preserve_top
Definition nbitset.hpp:38
CUDA static constexpr local_type top()
Definition nbitset.hpp:108
static constexpr const bool injective_concretization
Definition nbitset.hpp:41
CUDA constexpr void meet_bot()
Definition nbitset.hpp:304
CUDA constexpr NBitset(const battery::bitset< N, M, T > &bits)
Definition nbitset.hpp:87
CUDA constexpr LB lb() const
Definition nbitset.hpp:263
CUDA static constexpr local_type bot()
Definition nbitset.hpp:107
CUDA constexpr local::B is_bot() const
Definition nbitset.hpp:110
CUDA constexpr void abs(const local_type &x)
Definition nbitset.hpp:424
CUDA constexpr void project(Sig fun, const local_type &x)
Definition nbitset.hpp:434
CUDA constexpr this_type & operator=(const this_type2< M > &other)
Definition nbitset.hpp:92
static constexpr const bool is_arithmetic
Definition nbitset.hpp:44
CUDA NI static constexpr bool is_trivial_fun(Sig sig)
Definition nbitset.hpp:400
CUDA constexpr bool join_ub(const A &ub)
Definition nbitset.hpp:291
CUDA constexpr bool join(const this_type2< M > &other)
Definition nbitset.hpp:296
constexpr NBitset(this_type &&)=default
CUDA constexpr bool extract(this_type2< M > &ua) const
Definition nbitset.hpp:328
static constexpr const bool is_totally_ordered
Definition nbitset.hpp:36
CUDA NI void print() const
Definition nbitset.hpp:379
CUDA NI F deinterpret() const
Definition nbitset.hpp:375
NBitset< N, M, T > this_type2
Definition nbitset.hpp:24
CUDA TFormula< Allocator > deinterpret(AVar x, const Env &env, const Allocator &allocator=Allocator()) const
Definition nbitset.hpp:334
CUDA constexpr NBitset(value_type lb, value_type ub)
Definition nbitset.hpp:75
CUDA constexpr bool meet_ub(const A &ub)
Definition nbitset.hpp:314
CUDA constexpr NBitset(this_type2< M > &&other)
Definition nbitset.hpp:84
CUDA static constexpr local_type eq_one()
Definition nbitset.hpp:105
CUDA static NI bool interpret_ask(const F &f, const Env &env, this_type2< M > &k, IDiagnostics &diagnostics)
Definition nbitset.hpp:235
CUDA constexpr void additive_inverse(const local_type &x)
Definition nbitset.hpp:441
CUDA constexpr void neg(const local_type &x)
Definition nbitset.hpp:409
static constexpr const bool preserve_bot
Definition nbitset.hpp:37
static constexpr const bool preserve_meet
Definition nbitset.hpp:40
CUDA constexpr UB ub() const
Definition nbitset.hpp:269
Mem memory_type
Definition nbitset.hpp:21
CUDA constexpr local::B is_top() const
Definition nbitset.hpp:109
this_type2< battery::local_memory > local_type
Definition nbitset.hpp:25
CUDA constexpr local_type median() const
Definition nbitset.hpp:459
CUDA static constexpr this_type from_set(const battery::vector< int > &values)
Definition nbitset.hpp:59
CUDA constexpr NBitset(const this_type &other)
Definition nbitset.hpp:67
typename LB::value_type value_type
Definition nbitset.hpp:29
CUDA constexpr local_type complement() const
Definition nbitset.hpp:275
CUDA constexpr bool meet(const this_type2< M > &other)
Definition nbitset.hpp:319
CUDA constexpr local_type width() const
Definition nbitset.hpp:453
CUDA constexpr this_type & operator=(const this_type &other)
Definition nbitset.hpp:97
static constexpr const bool sequential
Definition nbitset.hpp:35
CUDA constexpr NBitset()
Definition nbitset.hpp:55
CUDA constexpr NBitset(const this_type2< M > &other)
Definition nbitset.hpp:81
CUDA constexpr const bitset_type & value() const
Definition nbitset.hpp:111
Definition ast.hpp:234
#define INTERPRETATION_WARNING(MSG)
Definition diagnostics.hpp:150
#define RETURN_INTERPRETATION_WARNING(MSG)
Definition diagnostics.hpp:159
#define RETURN_INTERPRETATION_ERROR(MSG)
Definition diagnostics.hpp:155
Definition ast.hpp:210
::lala::ZLB< int, battery::local_memory > ZLB
Definition arith_bound.hpp:68
::lala::ZUB< int, battery::local_memory > ZUB
Definition arith_bound.hpp:69
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 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
@ LEQ
Unary arithmetic function symbols.
Definition ast.hpp:113
@ NOT
Unary arithmetic function symbols.
Definition ast.hpp:114
@ OR
Unary arithmetic function symbols.
Definition ast.hpp:114
@ EQ
Unary arithmetic function symbols.
Definition ast.hpp:112
@ GEQ
Unary arithmetic function symbols.
Definition ast.hpp:113
@ IN
Set membership predicate.
Definition ast.hpp:108
@ GT
Arithmetic comparison predicates. When applied to set, it corresponds to the lexicographic ordering o...
Definition ast.hpp:113
@ LT
Unary arithmetic function symbols.
Definition ast.hpp:113
@ ABS
Unary arithmetic function symbols.
Definition ast.hpp:96
@ NEG
Unary arithmetic function symbols.
Definition ast.hpp:96
CUDA NI std::optional< F > negate(const F &f)
Definition algorithm.hpp:266
long long int logic_int
Definition sort.hpp:114
CUDA constexpr bool operator<(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:484
CUDA NI const char * string_of_sig(Sig sig)
Definition ast.hpp:121
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
#define UNTYPED
Definition sort.hpp:21
Definition sort.hpp:26