Lattice land propagators completion library
Loading...
Searching...
No Matches
terms.hpp
Go to the documentation of this file.
1// Copyright 2021 Pierre Talbot
2
3#ifndef LALA_PC_TERMS_HPP
4#define LALA_PC_TERMS_HPP
5
6#include "battery/vector.hpp"
7#include "lala/universes/arith_bound.hpp"
8
9namespace lala {
10namespace pc {
11
12template <class AD, class Allocator>
13class Term;
14
15template <class AD, class Allocator>
16class Formula;
17
18template <class AD>
19class Constant {
20public:
21 using A = AD;
22 using U = typename A::local_universe;
23
24private:
25 U k;
26
27public:
28 CUDA Constant(U&& k) : k(k) {}
29 Constant(Constant<A>&& other) = default;
30
31 template <class A2, class Alloc>
32 CUDA Constant(const Constant<A2>& other, const Alloc&): k(other.k) {}
33
34 CUDA bool embed(A&, const U&) const { return false; }
35 CUDA void project(const A&, U& r) const { r.meet(k); }
36 CUDA void print(const A&) const { ::battery::print(k); }
37 template <class Env, class Allocator = typename Env::allocator_type>
38 CUDA TFormula<Allocator> deinterpret(const A&, const Env&, AType, Allocator allocator = Allocator()) const {
39 return k.template deinterpret<TFormula<Allocator>>();
40 }
41 CUDA size_t length() const { return 1; }
42
43 template <class A2>
44 friend class Constant;
45};
46
47template <class AD>
48class Variable {
49public:
50 using A = AD;
51 using U = typename A::local_universe;
52
53private:
54 AVar avar;
55
56public:
57 CUDA Variable() {}
58 CUDA Variable(AVar avar) : avar(avar) {}
59 Variable(Variable<A>&& other) = default;
60 Variable<A>& operator=(Variable<A>&& other) = default;
61
62 template <class A2, class Alloc>
63 CUDA Variable(const Variable<A2>& other, const Alloc&): avar(other.avar) {}
64
65 CUDA bool embed(A& a, const U& u) const {
66 return a.embed(avar, u);
67 }
68
69 CUDA void project(const A& a, U& r) const {
70 return a.project(avar, r);
71 }
72
73 CUDA void print(const A& a) const { printf("(%d,%d)", avar.aty(), avar.vid()); }
74
75 template <class Env, class Allocator = typename Env::allocator_type>
76 CUDA TFormula<Allocator> deinterpret(const A&, const Env& env, AType, Allocator allocator = Allocator()) const {
77 using F = TFormula<Allocator>;
78 return F::make_lvar(avar.aty(), LVar<Allocator>(env.name_of(avar), allocator));
79 }
80
81 CUDA size_t length() const { return 1; }
82
83 template <class A2>
84 friend class Variable;
85};
86
87template<class Universe>
88struct NegOp {
89 using U = Universe;
90
91 CUDA static void project(const U& a, U& r) {
92 r.project(NEG, a);
93 }
94
95 CUDA static void residual(const U& a, U& r) {
96 project(a, r); // negation is its own residual.
97 }
98
99 static constexpr bool function_symbol = false;
100 CUDA static const char* symbol() { return "-"; }
101 CUDA static Sig sig() { return NEG; }
102};
103
104template<class Universe>
105struct AbsOp {
106 using U = Universe;
107
108 CUDA static void project(const U& a, U& r) {
109 r.project(ABS, a);
110 }
111
112 CUDA static void residual(const U& a, U& r) {
113 r.meet(fjoin(a, project_fun(NEG, a)));
114 }
115
116 static constexpr bool function_symbol = true;
117 CUDA static const char* symbol() { return "abs"; }
118 CUDA static Sig sig() { return ABS; }
119};
120
121template <class AD, class UnaryOp, class Allocator>
122class Unary {
123public:
124 using allocator_type = Allocator;
125 using A = AD;
126 using U = typename A::local_universe;
128
129 template <class A2, class UnaryOp2, class Alloc2>
130 friend class Unary;
131
132private:
134 battery::unique_ptr<sub_type, allocator_type> x_term;
135
136 CUDA INLINE const sub_type& x() const {
137 return *x_term;
138 }
139
140public:
141 CUDA Unary(battery::unique_ptr<sub_type, allocator_type>&& x_term): x_term(std::move(x_term)) {}
142 CUDA Unary(this_type&& other): Unary(std::move(other.x_term)) {}
143
144 template <class A2, class UnaryOp2, class Alloc2>
145 CUDA Unary(const Unary<A2, UnaryOp2, Alloc2>& other, const allocator_type& allocator):
146 x_term(battery::allocate_unique<sub_type>(allocator, *other.x_term))
147 {}
148
149 CUDA bool embed(A& a, const U& u) const {
150 U tmp{};
151 UnaryOp::residual(u, tmp);
152 return x().embed(a, tmp);
153 }
154
155 CUDA void project(const A& a, U& r) const {
156 U tmp{};
157 x().project(a, tmp);
158 UnaryOp::project(tmp, r);
159 }
160
161 CUDA NI void print(const A& a) const {
162 printf("%s", UnaryOp::symbol());
163 if constexpr(UnaryOp::function_symbol) { printf("("); }
164 x().print(a);
165 if constexpr(UnaryOp::function_symbol) { printf(")"); }
166 }
167
168 template <class Env, class Allocator2 = typename Env::allocator_type>
169 CUDA TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
170 using F = TFormula<Allocator2>;
171 return F::make_unary(UnaryOp::sig(), x().deinterpret(a, env, apc, allocator), apc, allocator);
172 }
173
174 CUDA size_t length() const { return 1 + x().length(); }
175};
176
177template<class Universe>
178struct GroupAdd {
179 using U = Universe;
180 static constexpr bool has_absorbing_element = false;
181
182 CUDA static void project(const U& a, const U& b, U& r) {
183 r.project(ADD, a, b);
184 }
185
186 CUDA static bool is_absorbing(const U& a) {
187 return false;
188 }
189
190 CUDA static void rev_op(const U& a, const U& b, U& r) {
191 U tmp{};
192 tmp.additive_inverse(b);
193 project(a, tmp, r);
194 }
195
196 CUDA static void left_residual(const U& a, const U& b, U& r) {
197 r.project(SUB, a, b);
198 }
199
200 CUDA static void right_residual(const U& a, const U& b, U& r) {
201 left_residual(a, b, r);
202 }
203
204 static constexpr bool prefix_symbol = false;
205 CUDA static char symbol() { return '+'; }
206 CUDA static constexpr Sig sig() { return ADD; }
207};
208
209template<class Universe>
210struct GroupSub {
211 using U = Universe;
212 static constexpr bool has_absorbing_element = false;
213
214 CUDA static void project(const U& a, const U& b, U& r) {
215 return r.project(SUB, a, b);
216 }
217
218 CUDA static void left_residual(const U& a, const U& b, U& r) {
219 return r.project(ADD, a, b);
220 }
221
222 CUDA static void right_residual(const U& a, const U& b, U& r) {
223 return r.project(SUB, b, a);
224 }
225
226 static constexpr bool prefix_symbol = false;
227 CUDA static char symbol() { return '-'; }
228 CUDA static constexpr Sig sig() { return SUB; }
229};
230
231template<class Universe, Sig divsig>
232struct GroupMul {
233 using U = Universe;
234
235 CUDA static void project(const U& a, const U& b, U& r) {
236 r.project(MUL, a, b);
237 }
238
239 CUDA static bool is_absorbing(const U& a) {
240 return a == U::eq_zero();
241 }
242
243 /** \pre `is_absorbing(b)` must be `false`. */
244 CUDA static void rev_op(const U& a, const U& b, U& r) {
245 return r.project(divsig, a, b);
246 }
247
248 /** If `a` and `b` contains 0, then we cannot say anything on the inverse since 0 is absorbing and the inverse could be anything. */
249 CUDA static void left_residual(const U& a, const U& b, U& r) {
250 if(!(a >= U::eq_zero() && b >= U::eq_zero())) {
251 r.project(divsig, a, b);
252 }
253 }
254
255 CUDA static void right_residual(const U& a, const U& b, U& r) {
256 left_residual(a, b, r);
257 }
258
259 static constexpr bool prefix_symbol = false;
260 CUDA static char symbol() { return '*'; }
261 CUDA static constexpr Sig sig() { return MUL; }
262};
263
264template<class Universe, Sig divsig>
265struct GroupDiv {
266 using U = Universe;
267
268 CUDA static void project(const U& a, const U& b, U& r) {
269 r.project(divsig, a, b);
270 }
271
272 CUDA static void left_residual(const U& a, const U& b, U& r) {
273 r.project(MUL, a, b);
274 if constexpr(U::preserve_concrete_covers) {
275 r.join_ub(U::UB::prev(b.ub()));
276 }
277 }
278
279 CUDA static void right_residual(const U& a, const U& b, U& r) {
280 /** In the discrete case, we can remove zero from `r` when it is possible. */
281 if constexpr(U::preserve_concrete_covers) {
282 if(r.lb().value() == 0) { r.meet_lb(typename U::LB::local_type(1)); }
283 if(r.ub().value() == 0) { r.meet_ub(typename U::UB::local_type(-1)); }
284 }
285 else if(r.lb().value() == 0 && r.ub().value() == 0) {
286 r.meet_bot();
287 return;
288 }
289 /** If `b` contains a zero, then any interval `r` can be used to have a = b / r. */
290 /** If `a` equals 0, the division would returns `bot`, which is incorrect in this case. */
291 if(!(b >= U::eq_zero()) && !(a.lb().value() == 0 && a.ub().value() == 0)) {
292 r.project(divsig, b, a);
293 }
294 }
295
296 static constexpr bool prefix_symbol = false;
297 CUDA static char symbol() { return '/'; }
298 CUDA static constexpr Sig sig() { return divsig; }
299};
300
301template<class Universe, Sig msig>
303 static_assert(msig == MIN || msig == MAX);
304
305 using U = Universe;
306 CUDA static void project(const U& a, const U& b, U& r) {
307 return r.project(msig, a, b);
308 }
309
310 CUDA static void left_residual(const U& a, const U& b, U& r) {
311 if(fmeet(a, b).is_bot()) {
312 r.meet(a);
313 }
314 else {
315 if constexpr(msig == MIN) {
316 r.meet_lb(a.lb());
317 }
318 else {
319 r.meet_ub(a.ub());
320 }
321 }
322 }
323
324 CUDA static void right_residual(const U& a, const U& b, U& r) {
325 left_residual(a, b, r);
326 }
327
328 static constexpr bool prefix_symbol = true;
329 CUDA static const char* symbol() { return msig == MIN ? "min" : "max"; }
330 CUDA static constexpr Sig sig() { return msig; }
331};
332
333template <class AD, class Group, class Allocator>
334class Binary {
335public:
336 using A = AD;
337 using allocator_type = Allocator;
338 using U = typename Group::U;
339 using G = Group;
341
342 template <class A2, class Group2, class Alloc2>
343 friend class Binary;
344
346 using sub_ptr = battery::unique_ptr<sub_type, allocator_type>;
347
348private:
349 sub_ptr x_term;
350 sub_ptr y_term;
351
352 CUDA INLINE const sub_type& x() const {
353 return *x_term;
354 }
355
356 CUDA INLINE const sub_type& y() const {
357 return *y_term;
358 }
359
360public:
361 CUDA Binary(sub_ptr&& x_term, sub_ptr&& y_term)
362 : x_term(std::move(x_term))
363 , y_term(std::move(y_term)) {}
364
365 CUDA Binary(this_type&& other)
366 : Binary(std::move(other.x_term), std::move(other.y_term)) {}
367
368 template <class A2, class Group2, class Alloc2>
369 CUDA Binary(const Binary<A2, Group2, Alloc2>& other, const allocator_type& allocator)
370 : x_term(battery::allocate_unique<sub_type>(allocator, *other.x_term))
371 , y_term(battery::allocate_unique<sub_type>(allocator, *other.y_term))
372 {}
373
374 /** Enforce `x <op> y <= u` where <= is the lattice order of the underlying abstract universe.
375 For instance, over the interval abstract universe, `x + y <= [2..5]` will ensure that `x + y` is eventually at least `2` and at most `5`. */
376 CUDA bool embed(A& a, const U& u) const {
377 U xt{};
378 U yt{};
379 U residual{};
380 bool has_changed = false;
381 if(!x().is(sub_type::IConstant)) {
382 y().project(a, yt);
383 G::left_residual(u, yt, residual);
384 has_changed |= x().embed(a, residual); // x <- u <residual> y
385 }
386 if(!y().is(sub_type::IConstant)) {
387 x().project(a, xt);
388 residual.join_top();
389 /** In the case of division, the right residual is important, as we read it to potentially remove 0. */
390 if(is_division(G::sig())) {
391 y().project(a, residual);
392 }
393 G::right_residual(u, xt, residual);
394 has_changed |= y().embed(a, residual); // y <- u <residual> x
395 }
396 return has_changed;
397 }
398
399 CUDA void project(const A& a, U& r) const {
400 U xt{};
401 U yt{};
402 x().project(a, xt);
403 y().project(a, yt);
404 G::project(xt, yt, r);
405 }
406
407 CUDA NI void print(const A& a) const {
408 if constexpr(G::prefix_symbol) {
409 printf("%s(", G::symbol());
410 x().print(a);
411 printf(", ");
412 x().print(a);
413 printf(")");
414 }
415 else {
416 x().print(a);
417 printf(" %c ", G::symbol());
418 y().print(a);
419 }
420 }
421
422 template <class Env, class Allocator2 = typename Env::allocator_type>
423 CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
424 using F = TFormula<Allocator2>;
425 return F::make_binary(
426 x().deinterpret(a, env, apc, allocator),
427 G::sig(),
428 y().deinterpret(a, env, apc, allocator),
429 apc,
430 allocator);
431 }
432
433 CUDA size_t length() const { return 1 + x().length() + y().length(); }
434};
435
436// Nary is only valid for commutative group (e.g., addition and multiplication).
437template <class Combinator>
438class Nary {
439public:
441 using allocator_type = typename Combinator::allocator_type;
442 using A = typename Combinator::A;
443 using U = typename Combinator::U;
444 using G = typename Combinator::G;
445
446 template <class Combinator2>
447 friend class Nary;
448private:
450 battery::vector<sub_type, allocator_type> terms;
451
452 CUDA INLINE const sub_type& t(size_t i) const {
453 return terms[i];
454 }
455
456public:
457 CUDA Nary(battery::vector<sub_type, allocator_type>&& terms): terms(std::move(terms)) {}
458 CUDA Nary(this_type&& other): Nary(std::move(other.terms)) {}
459
460 template <class Combinator2>
461 CUDA Nary(const Nary<Combinator2>& other, const allocator_type& allocator)
462 : terms(other.terms, allocator)
463 {}
464
465 CUDA void project(const A& a, U& r) const {
466 U tmp{};
467 U tmp2{};
468 U accu{};
469 t(0).project(a, accu);
470 for(int i = 1; i < terms.size(); ++i) {
471 t(i).project(a, tmp);
472 G::project(accu, tmp, tmp2);
473 accu = tmp2;
474 tmp.join_top();
475 tmp2.join_top();
476 }
477 r.meet(accu);
478 }
479
480 CUDA bool embed(A& a, const U& u) const {
481 U all{};
482 U tmp{};
483 U tmp2{};
484 U residual{};
485 bool has_changed = false;
486 project(a, all);
487 if(!G::is_absorbing(all)) {
488 for(int i = 0; i < terms.size(); ++i) {
489 t(i).project(a, tmp);
490 G::rev_op(all, tmp, tmp2);
491 G::left_residual(u, tmp2, residual);
492 has_changed |= t(i).embed(a, residual);
493 tmp.join_top();
494 tmp2.join_top();
495 residual.join_top();
496 }
497 }
498 return has_changed;
499 }
500
501 CUDA NI void print(const A& a) const {
502 t(0).print(a);
503 for(int i = 1; i < terms.size(); ++i) {
504 printf(" %c ", G::symbol());
505 t(i).print(a);
506 }
507 }
508
509 template <class Env, class Allocator = typename Env::allocator_type>
510 CUDA NI TFormula<Allocator> deinterpret(const A& a, const Env& env, AType apc, Allocator allocator = Allocator()) const {
511 using F = TFormula<Allocator>;
512 typename F::Sequence seq = typename F::Sequence(allocator);
513 for(int i = 0; i < terms.size(); ++i) {
514 seq.push_back(t(i).deinterpret(a, env, apc, allocator));
515 }
516 return F::make_nary(G::sig(), std::move(seq), apc);
517 }
518
519 CUDA size_t length() const {
520 size_t len = 1;
521 for(int i = 0; i < terms.size(); ++i) {
522 len += t(i).length();
523 }
524 return len;
525 }
526};
527
528template <class AD, class Allocator>
529class Term {
530public:
531 using A = AD;
532 using U = typename A::local_universe;
533 using allocator_type = Allocator;
535 using this_ptr = battery::unique_ptr<Term<A, allocator_type>, allocator_type>;
536 using formula_ptr = battery::unique_ptr<Formula<A, allocator_type>, allocator_type>;
550
551 static constexpr size_t IVar = 0;
552 static constexpr size_t IConstant = IVar + 1;
553 static constexpr size_t IFormula = IConstant + 1;
554 static constexpr size_t INeg = IFormula + 1;
555 static constexpr size_t IAbs = INeg + 1;
556 static constexpr size_t IAdd = IAbs + 1;
557 static constexpr size_t ISub = IAdd + 1;
558 static constexpr size_t IMul = ISub + 1;
559 static constexpr size_t ITDiv = IMul + 1;
560 static constexpr size_t IFDiv = ITDiv + 1;
561 static constexpr size_t ICDiv = IFDiv + 1;
562 static constexpr size_t IEDiv = ICDiv + 1;
563 static constexpr size_t IMin = IEDiv + 1;
564 static constexpr size_t IMax = IMin + 1;
565 static constexpr size_t INaryAdd = IMax + 1;
566 static constexpr size_t INaryMul = INaryAdd + 1;
567
568 template <class A2, class Alloc2>
569 friend class Term;
570
571private:
572 using VTerm = battery::variant<
576 Neg,
577 Abs,
578 Add,
579 Sub,
580 Mul,
581 TDiv,
582 FDiv,
583 CDiv,
584 EDiv,
585 Min,
586 Max,
587 NaryAdd,
588 NaryMul
589 >;
590
591 VTerm term;
592
593 template <size_t I, class TermType, class A2, class Alloc2>
594 CUDA static VTerm create_one(const Term<A2, Alloc2>& other, const allocator_type& allocator) {
595 return VTerm::template create<I>(TermType(battery::get<I>(other.term), allocator));
596 }
597
598 template <class A2, class Alloc2>
599 CUDA NI static VTerm create(const Term<A2, Alloc2>& other, const allocator_type& allocator) {
600 switch(other.term.index()) {
601 case IVar: return create_one<IVar, Variable<A>>(other, allocator);
602 case IConstant: return create_one<IConstant, Constant<A>>(other, allocator);
603 case IFormula:
604 return VTerm::template create<IFormula>(battery::allocate_unique<Formula<A, allocator_type>>(
605 allocator, *battery::get<IFormula>(other.term)));
606 case INeg: return create_one<INeg, Neg>(other, allocator);
607 case IAbs: return create_one<IAbs, Abs>(other, allocator);
608 case IAdd: return create_one<IAdd, Add>(other, allocator);
609 case ISub: return create_one<ISub, Sub>(other, allocator);
610 case IMul: return create_one<IMul, Mul>(other, allocator);
611 case ITDiv: return create_one<ITDiv, TDiv>(other, allocator);
612 case IFDiv: return create_one<IFDiv, FDiv>(other, allocator);
613 case ICDiv: return create_one<ICDiv, CDiv>(other, allocator);
614 case IEDiv: return create_one<IEDiv, EDiv>(other, allocator);
615 case IMin: return create_one<IMin, Min>(other, allocator);
616 case IMax: return create_one<IMax, Max>(other, allocator);
617 case INaryAdd: return create_one<INaryAdd, NaryAdd>(other, allocator);
618 case INaryMul: return create_one<INaryMul, NaryMul>(other, allocator);
619 default:
620 printf("BUG: term not handled.\n");
621 assert(false);
622 return VTerm::template create<IVar>(Variable<A>());
623 }
624 }
625
626 CUDA Term(VTerm&& term): term(std::move(term)) {}
627
628 template <class F>
629 CUDA NI auto forward(F&& f) const {
630 switch(term.index()) {
631 case IVar: return f(battery::get<IVar>(term));
632 case IConstant: return f(battery::get<IConstant>(term));
633 case IFormula: return f(*battery::get<IFormula>(term));
634 case INeg: return f(battery::get<INeg>(term));
635 case IAbs: return f(battery::get<IAbs>(term));
636 case IAdd: return f(battery::get<IAdd>(term));
637 case ISub: return f(battery::get<ISub>(term));
638 case IMul: return f(battery::get<IMul>(term));
639 case ITDiv: return f(battery::get<ITDiv>(term));
640 case IFDiv: return f(battery::get<IFDiv>(term));
641 case ICDiv: return f(battery::get<ICDiv>(term));
642 case IEDiv: return f(battery::get<IEDiv>(term));
643 case IMin: return f(battery::get<IMin>(term));
644 case IMax: return f(battery::get<IMax>(term));
645 case INaryAdd: return f(battery::get<INaryAdd>(term));
646 case INaryMul: return f(battery::get<INaryMul>(term));
647 default:
648 printf("BUG: term not handled.\n");
649 assert(false);
650 return f(Variable<A>());
651 }
652 }
653
654public:
655 Term() = default;
656 Term(this_type&&) = default;
658
659 template <class A2, class Alloc2>
660 CUDA Term(const Term<A2, Alloc2>& other, const allocator_type& allocator = allocator_type())
661 : term(create(other, allocator))
662 {}
663
664 CUDA bool is(size_t kind) const {
665 return term.index() == kind;
666 }
667
668 template <size_t I, class SubTerm>
669 CUDA static this_type make(SubTerm&& sub_term) {
670 return Term(VTerm::template create<I>(std::move(sub_term)));
671 }
672
673 CUDA static this_type make_var(const AVar& avar) {
674 return make<IVar>(Variable<A>(avar));
675 }
676
677 CUDA static this_type make_constant(U&& sub_term) {
678 return make<IConstant>(Constant<A>(std::move(sub_term)));
679 }
680
681 CUDA static this_type make_formula(formula_ptr&& sub_term) {
682 return make<IFormula>(std::move(sub_term));
683 }
684
685 CUDA static this_type make_neg(this_ptr&& sub_term) {
686 return make<INeg>(Neg(std::move(sub_term)));
687 }
688
689 CUDA static this_type make_abs(this_ptr&& sub_term) {
690 return make<IAbs>(Abs(std::move(sub_term)));
691 }
692
693 CUDA static this_type make_add(this_ptr&& left, this_ptr&& right) {
694 return make<IAdd>(Add(std::move(left), std::move(right)));
695 }
696
697 CUDA static this_type make_sub(this_ptr&& left, this_ptr&& right) {
698 return make<ISub>(Sub(std::move(left), std::move(right)));
699 }
700
701 CUDA static this_type make_mul(this_ptr&& left, this_ptr&& right) {
702 return make<IMul>(Mul(std::move(left), std::move(right)));
703 }
704
705 CUDA static this_type make_tdiv(this_ptr&& left, this_ptr&& right) {
706 return make<ITDiv>(TDiv(std::move(left), std::move(right)));
707 }
708
709 CUDA static this_type make_fdiv(this_ptr&& left, this_ptr&& right) {
710 return make<IFDiv>(FDiv(std::move(left), std::move(right)));
711 }
712
713 CUDA static this_type make_cdiv(this_ptr&& left, this_ptr&& right) {
714 return make<ICDiv>(CDiv(std::move(left), std::move(right)));
715 }
716
717 CUDA static this_type make_ediv(this_ptr&& left, this_ptr&& right) {
718 return make<IEDiv>(EDiv(std::move(left), std::move(right)));
719 }
720
721 CUDA static this_type make_min(this_ptr&& left, this_ptr&& right) {
722 return make<IMin>(Min(std::move(left), std::move(right)));
723 }
724
725 CUDA static this_type make_max(this_ptr&& left, this_ptr&& right) {
726 return make<IMax>(Max(std::move(left), std::move(right)));
727 }
728
729 CUDA static this_type make_naryadd(battery::vector<this_type, allocator_type>&& sub_terms) {
730 return make<INaryAdd>(NaryAdd(std::move(sub_terms)));
731 }
732
733 CUDA static this_type make_narymul(battery::vector<this_type, allocator_type>&& sub_terms) {
734 return make<INaryMul>(NaryMul(std::move(sub_terms)));
735 }
736
737 CUDA bool embed(A& a, const U& u) const {
738 return forward([&](const auto& t) { return t.embed(a, u); });
739 }
740
741 CUDA void project(const A& a, U& r) const {
742 return forward([&](const auto& t) { t.project(a, r); });
743 }
744
745 CUDA void print(const A& a) const {
746 forward([&](const auto& t) { t.print(a); });
747 }
748
749 template <class Env, class Allocator2 = typename Env::allocator_type>
750 CUDA TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
751 return forward([&](const auto& t) { return t.deinterpret(a, env, apc, allocator); });
752 }
753
754 CUDA size_t length() const {
755 return forward([&](const auto& t) { return t.length(); });
756 }
757};
758
759} // namespace pc
760} // namespace lala
761
762#endif
Definition terms.hpp:334
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition terms.hpp:423
CUDA bool embed(A &a, const U &u) const
Definition terms.hpp:376
CUDA void project(const A &a, U &r) const
Definition terms.hpp:399
CUDA size_t length() const
Definition terms.hpp:433
CUDA Binary(const Binary< A2, Group2, Alloc2 > &other, const allocator_type &allocator)
Definition terms.hpp:369
CUDA Binary(sub_ptr &&x_term, sub_ptr &&y_term)
Definition terms.hpp:361
AD A
Definition terms.hpp:336
battery::unique_ptr< sub_type, allocator_type > sub_ptr
Definition terms.hpp:346
CUDA Binary(this_type &&other)
Definition terms.hpp:365
Allocator allocator_type
Definition terms.hpp:337
Group G
Definition terms.hpp:339
Term< A, allocator_type > sub_type
Definition terms.hpp:345
typename Group::U U
Definition terms.hpp:338
CUDA NI void print(const A &a) const
Definition terms.hpp:407
Definition terms.hpp:19
CUDA bool embed(A &, const U &) const
Definition terms.hpp:34
CUDA Constant(const Constant< A2 > &other, const Alloc &)
Definition terms.hpp:32
CUDA void project(const A &, U &r) const
Definition terms.hpp:35
CUDA TFormula< Allocator > deinterpret(const A &, const Env &, AType, Allocator allocator=Allocator()) const
Definition terms.hpp:38
CUDA size_t length() const
Definition terms.hpp:41
CUDA void print(const A &) const
Definition terms.hpp:36
Constant(Constant< A > &&other)=default
AD A
Definition terms.hpp:21
typename A::local_universe U
Definition terms.hpp:22
CUDA Constant(U &&k)
Definition terms.hpp:28
Definition formula.hpp:864
Definition terms.hpp:438
CUDA size_t length() const
Definition terms.hpp:519
CUDA Nary(this_type &&other)
Definition terms.hpp:458
CUDA Nary(const Nary< Combinator2 > &other, const allocator_type &allocator)
Definition terms.hpp:461
CUDA NI void print(const A &a) const
Definition terms.hpp:501
typename Combinator::G G
Definition terms.hpp:444
CUDA bool embed(A &a, const U &u) const
Definition terms.hpp:480
typename Combinator::A A
Definition terms.hpp:442
typename Combinator::U U
Definition terms.hpp:443
CUDA NI TFormula< Allocator > deinterpret(const A &a, const Env &env, AType apc, Allocator allocator=Allocator()) const
Definition terms.hpp:510
CUDA Nary(battery::vector< sub_type, allocator_type > &&terms)
Definition terms.hpp:457
typename Combinator::allocator_type allocator_type
Definition terms.hpp:441
CUDA void project(const A &a, U &r) const
Definition terms.hpp:465
Binary< A, GroupDiv< U, FDIV >, allocator_type > FDiv
Definition terms.hpp:543
static CUDA this_type make_constant(U &&sub_term)
Definition terms.hpp:677
battery::unique_ptr< Formula< A, allocator_type >, allocator_type > formula_ptr
Definition terms.hpp:536
static constexpr size_t IEDiv
Definition terms.hpp:562
Term()=default
Binary< A, GroupDiv< U, EDIV >, allocator_type > EDiv
Definition terms.hpp:545
static constexpr size_t IFDiv
Definition terms.hpp:560
static CUDA this_type make_abs(this_ptr &&sub_term)
Definition terms.hpp:689
CUDA TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition terms.hpp:750
Term(this_type &&)=default
static constexpr size_t INaryMul
Definition terms.hpp:566
static CUDA this_type make_max(this_ptr &&left, this_ptr &&right)
Definition terms.hpp:725
Binary< A, GroupAdd< U >, allocator_type > Add
Definition terms.hpp:539
static constexpr size_t IMax
Definition terms.hpp:564
Nary< Mul > NaryMul
Definition terms.hpp:549
Binary< A, GroupMinMax< U, MIN >, allocator_type > Min
Definition terms.hpp:546
static constexpr size_t ISub
Definition terms.hpp:557
CUDA Term(const Term< A2, Alloc2 > &other, const allocator_type &allocator=allocator_type())
Definition terms.hpp:660
static constexpr size_t INeg
Definition terms.hpp:554
CUDA void print(const A &a) const
Definition terms.hpp:745
Binary< A, GroupMinMax< U, MAX >, allocator_type > Max
Definition terms.hpp:547
static CUDA this_type make_mul(this_ptr &&left, this_ptr &&right)
Definition terms.hpp:701
friend class Term
Definition terms.hpp:569
static CUDA this_type make_min(this_ptr &&left, this_ptr &&right)
Definition terms.hpp:721
CUDA bool embed(A &a, const U &u) const
Definition terms.hpp:737
static constexpr size_t ITDiv
Definition terms.hpp:559
static CUDA this_type make(SubTerm &&sub_term)
Definition terms.hpp:669
battery::unique_ptr< Term< A, allocator_type >, allocator_type > this_ptr
Definition terms.hpp:535
static CUDA this_type make_cdiv(this_ptr &&left, this_ptr &&right)
Definition terms.hpp:713
static CUDA this_type make_neg(this_ptr &&sub_term)
Definition terms.hpp:685
static constexpr size_t INaryAdd
Definition terms.hpp:565
Binary< A, GroupSub< U >, allocator_type > Sub
Definition terms.hpp:540
static CUDA this_type make_tdiv(this_ptr &&left, this_ptr &&right)
Definition terms.hpp:705
static constexpr size_t IMin
Definition terms.hpp:563
static CUDA this_type make_naryadd(battery::vector< this_type, allocator_type > &&sub_terms)
Definition terms.hpp:729
Binary< A, GroupMul< U, EDIV >, allocator_type > Mul
Definition terms.hpp:541
Binary< A, GroupDiv< U, CDIV >, allocator_type > CDiv
Definition terms.hpp:544
Nary< Add > NaryAdd
Definition terms.hpp:548
static CUDA this_type make_ediv(this_ptr &&left, this_ptr &&right)
Definition terms.hpp:717
CUDA void project(const A &a, U &r) const
Definition terms.hpp:741
this_type & operator=(this_type &&)=default
static CUDA this_type make_fdiv(this_ptr &&left, this_ptr &&right)
Definition terms.hpp:709
CUDA bool is(size_t kind) const
Definition terms.hpp:664
static CUDA this_type make_sub(this_ptr &&left, this_ptr &&right)
Definition terms.hpp:697
static constexpr size_t ICDiv
Definition terms.hpp:561
static constexpr size_t IAdd
Definition terms.hpp:556
CUDA size_t length() const
Definition terms.hpp:754
static constexpr size_t IVar
Definition terms.hpp:551
static CUDA this_type make_formula(formula_ptr &&sub_term)
Definition terms.hpp:681
static constexpr size_t IFormula
Definition terms.hpp:553
AD A
Definition terms.hpp:531
Unary< A, NegOp< U >, allocator_type > Neg
Definition terms.hpp:537
static constexpr size_t IAbs
Definition terms.hpp:555
Unary< A, AbsOp< U >, allocator_type > Abs
Definition terms.hpp:538
static CUDA this_type make_var(const AVar &avar)
Definition terms.hpp:673
static constexpr size_t IMul
Definition terms.hpp:558
static CUDA this_type make_add(this_ptr &&left, this_ptr &&right)
Definition terms.hpp:693
static constexpr size_t IConstant
Definition terms.hpp:552
typename A::local_universe U
Definition terms.hpp:532
Allocator allocator_type
Definition terms.hpp:533
static CUDA this_type make_narymul(battery::vector< this_type, allocator_type > &&sub_terms)
Definition terms.hpp:733
Binary< A, GroupDiv< U, TDIV >, allocator_type > TDiv
Definition terms.hpp:542
Definition terms.hpp:122
CUDA Unary(this_type &&other)
Definition terms.hpp:142
typename A::local_universe U
Definition terms.hpp:126
CUDA Unary(const Unary< A2, UnaryOp2, Alloc2 > &other, const allocator_type &allocator)
Definition terms.hpp:145
CUDA bool embed(A &a, const U &u) const
Definition terms.hpp:149
CUDA NI void print(const A &a) const
Definition terms.hpp:161
Allocator allocator_type
Definition terms.hpp:124
CUDA void project(const A &a, U &r) const
Definition terms.hpp:155
CUDA Unary(battery::unique_ptr< sub_type, allocator_type > &&x_term)
Definition terms.hpp:141
AD A
Definition terms.hpp:125
CUDA size_t length() const
Definition terms.hpp:174
CUDA TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition terms.hpp:169
Definition terms.hpp:48
CUDA Variable(AVar avar)
Definition terms.hpp:58
CUDA Variable(const Variable< A2 > &other, const Alloc &)
Definition terms.hpp:63
CUDA bool embed(A &a, const U &u) const
Definition terms.hpp:65
AD A
Definition terms.hpp:50
Variable< A > & operator=(Variable< A > &&other)=default
CUDA Variable()
Definition terms.hpp:57
CUDA void project(const A &a, U &r) const
Definition terms.hpp:69
CUDA TFormula< Allocator > deinterpret(const A &, const Env &env, AType, Allocator allocator=Allocator()) const
Definition terms.hpp:76
CUDA size_t length() const
Definition terms.hpp:81
CUDA void print(const A &a) const
Definition terms.hpp:73
typename A::local_universe U
Definition terms.hpp:51
Variable(Variable< A > &&other)=default
Definition formula.hpp:8
Definition terms.hpp:105
static CUDA void project(const U &a, U &r)
Definition terms.hpp:108
static constexpr bool function_symbol
Definition terms.hpp:116
Universe U
Definition terms.hpp:106
static CUDA const char * symbol()
Definition terms.hpp:117
static CUDA Sig sig()
Definition terms.hpp:118
static CUDA void residual(const U &a, U &r)
Definition terms.hpp:112
Definition terms.hpp:178
static CUDA char symbol()
Definition terms.hpp:205
static CUDA void left_residual(const U &a, const U &b, U &r)
Definition terms.hpp:196
static CUDA void rev_op(const U &a, const U &b, U &r)
Definition terms.hpp:190
Universe U
Definition terms.hpp:179
static CUDA void project(const U &a, const U &b, U &r)
Definition terms.hpp:182
static constexpr bool has_absorbing_element
Definition terms.hpp:180
static CUDA bool is_absorbing(const U &a)
Definition terms.hpp:186
static CUDA void right_residual(const U &a, const U &b, U &r)
Definition terms.hpp:200
static constexpr bool prefix_symbol
Definition terms.hpp:204
static CUDA constexpr Sig sig()
Definition terms.hpp:206
Definition terms.hpp:265
static CUDA void project(const U &a, const U &b, U &r)
Definition terms.hpp:268
Universe U
Definition terms.hpp:266
static CUDA constexpr Sig sig()
Definition terms.hpp:298
static constexpr bool prefix_symbol
Definition terms.hpp:296
static CUDA void left_residual(const U &a, const U &b, U &r)
Definition terms.hpp:272
static CUDA char symbol()
Definition terms.hpp:297
static CUDA void right_residual(const U &a, const U &b, U &r)
Definition terms.hpp:279
Definition terms.hpp:302
static CUDA void right_residual(const U &a, const U &b, U &r)
Definition terms.hpp:324
Universe U
Definition terms.hpp:305
static CUDA const char * symbol()
Definition terms.hpp:329
static CUDA void project(const U &a, const U &b, U &r)
Definition terms.hpp:306
static constexpr bool prefix_symbol
Definition terms.hpp:328
static CUDA constexpr Sig sig()
Definition terms.hpp:330
static CUDA void left_residual(const U &a, const U &b, U &r)
Definition terms.hpp:310
Definition terms.hpp:232
Universe U
Definition terms.hpp:233
static CUDA void rev_op(const U &a, const U &b, U &r)
Definition terms.hpp:244
static CUDA bool is_absorbing(const U &a)
Definition terms.hpp:239
static CUDA void project(const U &a, const U &b, U &r)
Definition terms.hpp:235
static CUDA void right_residual(const U &a, const U &b, U &r)
Definition terms.hpp:255
static CUDA constexpr Sig sig()
Definition terms.hpp:261
static CUDA char symbol()
Definition terms.hpp:260
static CUDA void left_residual(const U &a, const U &b, U &r)
Definition terms.hpp:249
static constexpr bool prefix_symbol
Definition terms.hpp:259
Definition terms.hpp:210
static constexpr bool prefix_symbol
Definition terms.hpp:226
static CUDA void left_residual(const U &a, const U &b, U &r)
Definition terms.hpp:218
static constexpr bool has_absorbing_element
Definition terms.hpp:212
static CUDA char symbol()
Definition terms.hpp:227
static CUDA void project(const U &a, const U &b, U &r)
Definition terms.hpp:214
static CUDA constexpr Sig sig()
Definition terms.hpp:228
static CUDA void right_residual(const U &a, const U &b, U &r)
Definition terms.hpp:222
Universe U
Definition terms.hpp:211
Definition terms.hpp:88
static CUDA void project(const U &a, U &r)
Definition terms.hpp:91
static CUDA Sig sig()
Definition terms.hpp:101
static CUDA const char * symbol()
Definition terms.hpp:100
static CUDA void residual(const U &a, U &r)
Definition terms.hpp:95
static constexpr bool function_symbol
Definition terms.hpp:99
Universe U
Definition terms.hpp:89