Lattice land propagators completion library
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 
9 namespace lala {
10 namespace pc {
11 
12 template <class AD, class Allocator>
13 class Term;
14 
15 template <class AD, class Allocator>
16 class Formula;
17 
18 template <class AD>
19 class Constant {
20 public:
21  using A = AD;
22  using U = typename A::local_universe;
23 
24 private:
25  U k;
26 
27 public:
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 
47 template <class AD>
48 class Variable {
49 public:
50  using A = AD;
51  using U = typename A::local_universe;
52 
53 private:
54  AVar avar;
55 
56 public:
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 
87 template<class Universe>
88 struct 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 
104 template<class Universe>
105 struct 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 
121 template <class AD, class UnaryOp, class Allocator>
122 class Unary {
123 public:
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 
132 private:
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 
140 public:
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 
177 template<class Universe>
178 struct 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 Sig sig() { return ADD; }
207 };
208 
209 template<class Universe>
210 struct 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 Sig sig() { return SUB; }
229 };
230 
231 template<class Universe, Sig divsig>
232 struct 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 Sig sig() { return MUL; }
262 };
263 
264 template<class Universe, Sig divsig>
265 struct GroupDiv {
266  using U = Universe;
267 
268  CUDA static void project(const U& a, const U& b, U& r) {
269  return r.project(divsig, a, b);
270  }
271 
272  CUDA static void left_residual(const U& a, const U& b, U& r) {
273  return r.project(MUL, a, b);
274  }
275 
276  CUDA static void right_residual(const U& a, const U& b, U& r) {
277  if(!(b >= U::eq_zero())) {
278  r.project(divsig, b, a);
279  }
280  }
281 
282  static constexpr bool prefix_symbol = false;
283  CUDA static char symbol() { return '/'; }
284  CUDA static Sig sig() { return divsig; }
285 };
286 
287 template<class Universe, Sig msig>
288 struct GroupMinMax {
289  static_assert(msig == MIN || msig == MAX);
290 
291  using U = Universe;
292  CUDA static void project(const U& a, const U& b, U& r) {
293  return r.project(msig, a, b);
294  }
295 
296  CUDA static void left_residual(const U& a, const U& b, U& r) {
297  if(fmeet(a, b).is_bot()) {
298  r.meet(a);
299  }
300  else {
301  if constexpr(msig == MIN) {
302  r.meet_lb(a.lb());
303  }
304  else {
305  r.meet_ub(a.ub());
306  }
307  }
308  }
309 
310  CUDA static void right_residual(const U& a, const U& b, U& r) {
311  left_residual(a, b, r);
312  }
313 
314  static constexpr bool prefix_symbol = true;
315  CUDA static const char* symbol() { return msig == MIN ? "min" : "max"; }
316  CUDA static Sig sig() { return msig; }
317 };
318 
319 template <class AD, class Group, class Allocator>
320 class Binary {
321 public:
322  using A = AD;
323  using allocator_type = Allocator;
324  using U = typename Group::U;
325  using G = Group;
327 
328  template <class A2, class Group2, class Alloc2>
329  friend class Binary;
330 
332  using sub_ptr = battery::unique_ptr<sub_type, allocator_type>;
333 
334 private:
335  sub_ptr x_term;
336  sub_ptr y_term;
337 
338  CUDA INLINE const sub_type& x() const {
339  return *x_term;
340  }
341 
342  CUDA INLINE const sub_type& y() const {
343  return *y_term;
344  }
345 
346 public:
347  CUDA Binary(sub_ptr&& x_term, sub_ptr&& y_term)
348  : x_term(std::move(x_term))
349  , y_term(std::move(y_term)) {}
350 
351  CUDA Binary(this_type&& other)
352  : Binary(std::move(other.x_term), std::move(other.y_term)) {}
353 
354  template <class A2, class Group2, class Alloc2>
355  CUDA Binary(const Binary<A2, Group2, Alloc2>& other, const allocator_type& allocator)
356  : x_term(battery::allocate_unique<sub_type>(allocator, *other.x_term))
357  , y_term(battery::allocate_unique<sub_type>(allocator, *other.y_term))
358  {}
359 
360  /** Enforce `x <op> y <= u` where <= is the lattice order of the underlying abstract universe.
361  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`. */
362  CUDA bool embed(A& a, const U& u) const {
363  U xt{};
364  U yt{};
365  U residual{};
366  bool has_changed = false;
367  if(!x().is(sub_type::IConstant)) {
368  y().project(a, yt);
369  G::left_residual(u, yt, residual);
370  has_changed |= x().embed(a, residual); // x <- u <residual> y
371  }
372  if(!y().is(sub_type::IConstant)) {
373  x().project(a, xt);
374  residual.join_top();
375  G::right_residual(u, xt, residual);
376  has_changed |= y().embed(a, residual); // y <- u <residual> x
377  }
378  return has_changed;
379  }
380 
381  CUDA void project(const A& a, U& r) const {
382  U xt{};
383  U yt{};
384  x().project(a, xt);
385  y().project(a, yt);
386  G::project(xt, yt, r);
387  }
388 
389  CUDA NI void print(const A& a) const {
390  if constexpr(G::prefix_symbol) {
391  printf("%s(", G::symbol());
392  x().print(a);
393  printf(", ");
394  x().print(a);
395  printf(")");
396  }
397  else {
398  x().print(a);
399  printf(" %c ", G::symbol());
400  y().print(a);
401  }
402  }
403 
404  template <class Env, class Allocator2 = typename Env::allocator_type>
405  CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
406  using F = TFormula<Allocator2>;
407  return F::make_binary(
408  x().deinterpret(a, env, apc, allocator),
409  G::sig(),
410  y().deinterpret(a, env, apc, allocator),
411  apc,
412  allocator);
413  }
414 
415  CUDA size_t length() const { return 1 + x().length() + y().length(); }
416 };
417 
418 // Nary is only valid for commutative group (e.g., addition and multiplication).
419 template <class Combinator>
420 class Nary {
421 public:
423  using allocator_type = typename Combinator::allocator_type;
424  using A = typename Combinator::A;
425  using U = typename Combinator::U;
426  using G = typename Combinator::G;
427 
428  template <class Combinator2>
429  friend class Nary;
430 private:
432  battery::vector<sub_type, allocator_type> terms;
433 
434  CUDA INLINE const sub_type& t(size_t i) const {
435  return terms[i];
436  }
437 
438 public:
439  CUDA Nary(battery::vector<sub_type, allocator_type>&& terms): terms(std::move(terms)) {}
440  CUDA Nary(this_type&& other): Nary(std::move(other.terms)) {}
441 
442  template <class Combinator2>
443  CUDA Nary(const Nary<Combinator2>& other, const allocator_type& allocator)
444  : terms(other.terms, allocator)
445  {}
446 
447  CUDA void project(const A& a, U& r) const {
448  U tmp{};
449  U tmp2{};
450  U accu{};
451  t(0).project(a, accu);
452  for(int i = 1; i < terms.size(); ++i) {
453  t(i).project(a, tmp);
454  G::project(accu, tmp, tmp2);
455  accu = tmp2;
456  tmp.join_top();
457  tmp2.join_top();
458  }
459  r.meet(accu);
460  }
461 
462  CUDA bool embed(A& a, const U& u) const {
463  U all{};
464  U tmp{};
465  U tmp2{};
466  U residual{};
467  bool has_changed = false;
468  project(a, all);
469  if(!G::is_absorbing(all)) {
470  for(int i = 0; i < terms.size(); ++i) {
471  t(i).project(a, tmp);
472  G::rev_op(all, tmp, tmp2);
473  G::left_residual(u, tmp2, residual);
474  has_changed |= t(i).embed(a, residual);
475  tmp.join_top();
476  tmp2.join_top();
477  residual.join_top();
478  }
479  }
480  return has_changed;
481  }
482 
483  CUDA NI void print(const A& a) const {
484  t(0).print(a);
485  for(int i = 1; i < terms.size(); ++i) {
486  printf(" %c ", G::symbol());
487  t(i).print(a);
488  }
489  }
490 
491  template <class Env, class Allocator = typename Env::allocator_type>
492  CUDA NI TFormula<Allocator> deinterpret(const A& a, const Env& env, AType apc, Allocator allocator = Allocator()) const {
493  using F = TFormula<Allocator>;
494  typename F::Sequence seq = typename F::Sequence(allocator);
495  for(int i = 0; i < terms.size(); ++i) {
496  seq.push_back(t(i).deinterpret(a, env, apc, allocator));
497  }
498  return F::make_nary(G::sig(), std::move(seq), apc);
499  }
500 
501  CUDA size_t length() const {
502  size_t len = 1;
503  for(int i = 0; i < terms.size(); ++i) {
504  len += t(i).length();
505  }
506  return len;
507  }
508 };
509 
510 template <class AD, class Allocator>
511 class Term {
512 public:
513  using A = AD;
514  using U = typename A::local_universe;
515  using allocator_type = Allocator;
517  using this_ptr = battery::unique_ptr<Term<A, allocator_type>, allocator_type>;
518  using formula_ptr = battery::unique_ptr<Formula<A, allocator_type>, allocator_type>;
532 
533  static constexpr size_t IVar = 0;
534  static constexpr size_t IConstant = IVar + 1;
535  static constexpr size_t IFormula = IConstant + 1;
536  static constexpr size_t INeg = IFormula + 1;
537  static constexpr size_t IAbs = INeg + 1;
538  static constexpr size_t IAdd = IAbs + 1;
539  static constexpr size_t ISub = IAdd + 1;
540  static constexpr size_t IMul = ISub + 1;
541  static constexpr size_t ITDiv = IMul + 1;
542  static constexpr size_t IFDiv = ITDiv + 1;
543  static constexpr size_t ICDiv = IFDiv + 1;
544  static constexpr size_t IEDiv = ICDiv + 1;
545  static constexpr size_t IMin = IEDiv + 1;
546  static constexpr size_t IMax = IMin + 1;
547  static constexpr size_t INaryAdd = IMax + 1;
548  static constexpr size_t INaryMul = INaryAdd + 1;
549 
550  template <class A2, class Alloc2>
551  friend class Term;
552 
553 private:
554  using VTerm = battery::variant<
555  Variable<A>,
556  Constant<A>,
557  formula_ptr,
558  Neg,
559  Abs,
560  Add,
561  Sub,
562  Mul,
563  TDiv,
564  FDiv,
565  CDiv,
566  EDiv,
567  Min,
568  Max,
569  NaryAdd,
570  NaryMul
571  >;
572 
573  VTerm term;
574 
575  template <size_t I, class TermType, class A2, class Alloc2>
576  CUDA static VTerm create_one(const Term<A2, Alloc2>& other, const allocator_type& allocator) {
577  return VTerm::template create<I>(TermType(battery::get<I>(other.term), allocator));
578  }
579 
580  template <class A2, class Alloc2>
581  CUDA NI static VTerm create(const Term<A2, Alloc2>& other, const allocator_type& allocator) {
582  switch(other.term.index()) {
583  case IVar: return create_one<IVar, Variable<A>>(other, allocator);
584  case IConstant: return create_one<IConstant, Constant<A>>(other, allocator);
585  case IFormula:
586  return VTerm::template create<IFormula>(battery::allocate_unique<Formula<A, allocator_type>>(
587  allocator, *battery::get<IFormula>(other.term)));
588  case INeg: return create_one<INeg, Neg>(other, allocator);
589  case IAbs: return create_one<IAbs, Abs>(other, allocator);
590  case IAdd: return create_one<IAdd, Add>(other, allocator);
591  case ISub: return create_one<ISub, Sub>(other, allocator);
592  case IMul: return create_one<IMul, Mul>(other, allocator);
593  case ITDiv: return create_one<ITDiv, TDiv>(other, allocator);
594  case IFDiv: return create_one<IFDiv, FDiv>(other, allocator);
595  case ICDiv: return create_one<ICDiv, CDiv>(other, allocator);
596  case IEDiv: return create_one<IEDiv, EDiv>(other, allocator);
597  case IMin: return create_one<IMin, Min>(other, allocator);
598  case IMax: return create_one<IMax, Max>(other, allocator);
599  case INaryAdd: return create_one<INaryAdd, NaryAdd>(other, allocator);
600  case INaryMul: return create_one<INaryMul, NaryMul>(other, allocator);
601  default:
602  printf("BUG: term not handled.\n");
603  assert(false);
604  return VTerm::template create<IVar>(Variable<A>());
605  }
606  }
607 
608  CUDA Term(VTerm&& term): term(std::move(term)) {}
609 
610  template <class F>
611  CUDA NI auto forward(F&& f) const {
612  switch(term.index()) {
613  case IVar: return f(battery::get<IVar>(term));
614  case IConstant: return f(battery::get<IConstant>(term));
615  case IFormula: return f(*battery::get<IFormula>(term));
616  case INeg: return f(battery::get<INeg>(term));
617  case IAbs: return f(battery::get<IAbs>(term));
618  case IAdd: return f(battery::get<IAdd>(term));
619  case ISub: return f(battery::get<ISub>(term));
620  case IMul: return f(battery::get<IMul>(term));
621  case ITDiv: return f(battery::get<ITDiv>(term));
622  case IFDiv: return f(battery::get<IFDiv>(term));
623  case ICDiv: return f(battery::get<ICDiv>(term));
624  case IEDiv: return f(battery::get<IEDiv>(term));
625  case IMin: return f(battery::get<IMin>(term));
626  case IMax: return f(battery::get<IMax>(term));
627  case INaryAdd: return f(battery::get<INaryAdd>(term));
628  case INaryMul: return f(battery::get<INaryMul>(term));
629  default:
630  printf("BUG: term not handled.\n");
631  assert(false);
632  return f(Variable<A>());
633  }
634  }
635 
636 public:
637  Term() = default;
638  Term(this_type&&) = default;
640 
641  template <class A2, class Alloc2>
642  CUDA Term(const Term<A2, Alloc2>& other, const allocator_type& allocator = allocator_type())
643  : term(create(other, allocator))
644  {}
645 
646  CUDA bool is(size_t kind) const {
647  return term.index() == kind;
648  }
649 
650  template <size_t I, class SubTerm>
651  CUDA static this_type make(SubTerm&& sub_term) {
652  return Term(VTerm::template create<I>(std::move(sub_term)));
653  }
654 
655  CUDA static this_type make_var(const AVar& avar) {
656  return make<IVar>(Variable<A>(avar));
657  }
658 
659  CUDA static this_type make_constant(U&& sub_term) {
660  return make<IConstant>(Constant<A>(std::move(sub_term)));
661  }
662 
663  CUDA static this_type make_formula(formula_ptr&& sub_term) {
664  return make<IFormula>(std::move(sub_term));
665  }
666 
667  CUDA static this_type make_neg(this_ptr&& sub_term) {
668  return make<INeg>(Neg(std::move(sub_term)));
669  }
670 
671  CUDA static this_type make_abs(this_ptr&& sub_term) {
672  return make<IAbs>(Abs(std::move(sub_term)));
673  }
674 
675  CUDA static this_type make_add(this_ptr&& left, this_ptr&& right) {
676  return make<IAdd>(Add(std::move(left), std::move(right)));
677  }
678 
679  CUDA static this_type make_sub(this_ptr&& left, this_ptr&& right) {
680  return make<ISub>(Sub(std::move(left), std::move(right)));
681  }
682 
683  CUDA static this_type make_mul(this_ptr&& left, this_ptr&& right) {
684  return make<IMul>(Mul(std::move(left), std::move(right)));
685  }
686 
687  CUDA static this_type make_tdiv(this_ptr&& left, this_ptr&& right) {
688  return make<ITDiv>(TDiv(std::move(left), std::move(right)));
689  }
690 
691  CUDA static this_type make_fdiv(this_ptr&& left, this_ptr&& right) {
692  return make<IFDiv>(FDiv(std::move(left), std::move(right)));
693  }
694 
695  CUDA static this_type make_cdiv(this_ptr&& left, this_ptr&& right) {
696  return make<ICDiv>(CDiv(std::move(left), std::move(right)));
697  }
698 
699  CUDA static this_type make_ediv(this_ptr&& left, this_ptr&& right) {
700  return make<IEDiv>(EDiv(std::move(left), std::move(right)));
701  }
702 
703  CUDA static this_type make_min(this_ptr&& left, this_ptr&& right) {
704  return make<IMin>(Min(std::move(left), std::move(right)));
705  }
706 
707  CUDA static this_type make_max(this_ptr&& left, this_ptr&& right) {
708  return make<IMax>(Max(std::move(left), std::move(right)));
709  }
710 
711  CUDA static this_type make_naryadd(battery::vector<this_type, allocator_type>&& sub_terms) {
712  return make<INaryAdd>(NaryAdd(std::move(sub_terms)));
713  }
714 
715  CUDA static this_type make_narymul(battery::vector<this_type, allocator_type>&& sub_terms) {
716  return make<INaryMul>(NaryMul(std::move(sub_terms)));
717  }
718 
719  CUDA bool embed(A& a, const U& u) const {
720  return forward([&](const auto& t) { return t.embed(a, u); });
721  }
722 
723  CUDA void project(const A& a, U& r) const {
724  return forward([&](const auto& t) { t.project(a, r); });
725  }
726 
727  CUDA void print(const A& a) const {
728  forward([&](const auto& t) { t.print(a); });
729  }
730 
731  template <class Env, class Allocator2 = typename Env::allocator_type>
732  CUDA TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
733  return forward([&](const auto& t) { return t.deinterpret(a, env, apc, allocator); });
734  }
735 
736  CUDA size_t length() const {
737  return forward([&](const auto& t) { return t.length(); });
738  }
739 };
740 
741 } // namespace pc
742 } // namespace lala
743 
744 #endif
Definition: terms.hpp:320
CUDA bool embed(A &a, const U &u) const
Definition: terms.hpp:362
CUDA void project(const A &a, U &r) const
Definition: terms.hpp:381
CUDA size_t length() const
Definition: terms.hpp:415
CUDA Binary(const Binary< A2, Group2, Alloc2 > &other, const allocator_type &allocator)
Definition: terms.hpp:355
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: terms.hpp:405
CUDA Binary(sub_ptr &&x_term, sub_ptr &&y_term)
Definition: terms.hpp:347
AD A
Definition: terms.hpp:322
battery::unique_ptr< sub_type, allocator_type > sub_ptr
Definition: terms.hpp:332
CUDA Binary(this_type &&other)
Definition: terms.hpp:351
Allocator allocator_type
Definition: terms.hpp:323
Group G
Definition: terms.hpp:325
Term< A, allocator_type > sub_type
Definition: terms.hpp:331
typename Group::U U
Definition: terms.hpp:324
CUDA NI void print(const A &a) const
Definition: terms.hpp:389
Definition: terms.hpp:19
CUDA TFormula< Allocator > deinterpret(const A &, const Env &, AType, Allocator allocator=Allocator()) const
Definition: terms.hpp:38
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 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:420
CUDA size_t length() const
Definition: terms.hpp:501
CUDA Nary(this_type &&other)
Definition: terms.hpp:440
CUDA Nary(const Nary< Combinator2 > &other, const allocator_type &allocator)
Definition: terms.hpp:443
CUDA NI TFormula< Allocator > deinterpret(const A &a, const Env &env, AType apc, Allocator allocator=Allocator()) const
Definition: terms.hpp:492
CUDA NI void print(const A &a) const
Definition: terms.hpp:483
typename Combinator::G G
Definition: terms.hpp:426
CUDA bool embed(A &a, const U &u) const
Definition: terms.hpp:462
typename Combinator::A A
Definition: terms.hpp:424
typename Combinator::U U
Definition: terms.hpp:425
CUDA Nary(battery::vector< sub_type, allocator_type > &&terms)
Definition: terms.hpp:439
typename Combinator::allocator_type allocator_type
Definition: terms.hpp:423
CUDA void project(const A &a, U &r) const
Definition: terms.hpp:447
Binary< A, GroupDiv< U, FDIV >, allocator_type > FDiv
Definition: terms.hpp:525
static CUDA this_type make_constant(U &&sub_term)
Definition: terms.hpp:659
battery::unique_ptr< Formula< A, allocator_type >, allocator_type > formula_ptr
Definition: terms.hpp:518
static constexpr size_t IEDiv
Definition: terms.hpp:544
Term()=default
Binary< A, GroupDiv< U, EDIV >, allocator_type > EDiv
Definition: terms.hpp:527
static constexpr size_t IFDiv
Definition: terms.hpp:542
static CUDA this_type make_abs(this_ptr &&sub_term)
Definition: terms.hpp:671
Term(this_type &&)=default
static constexpr size_t INaryMul
Definition: terms.hpp:548
static CUDA this_type make_max(this_ptr &&left, this_ptr &&right)
Definition: terms.hpp:707
Binary< A, GroupAdd< U >, allocator_type > Add
Definition: terms.hpp:521
static constexpr size_t IMax
Definition: terms.hpp:546
Nary< Mul > NaryMul
Definition: terms.hpp:531
Binary< A, GroupMinMax< U, MIN >, allocator_type > Min
Definition: terms.hpp:528
static constexpr size_t ISub
Definition: terms.hpp:539
CUDA Term(const Term< A2, Alloc2 > &other, const allocator_type &allocator=allocator_type())
Definition: terms.hpp:642
static constexpr size_t INeg
Definition: terms.hpp:536
CUDA void print(const A &a) const
Definition: terms.hpp:727
Binary< A, GroupMinMax< U, MAX >, allocator_type > Max
Definition: terms.hpp:529
static CUDA this_type make_mul(this_ptr &&left, this_ptr &&right)
Definition: terms.hpp:683
friend class Term
Definition: terms.hpp:551
static CUDA this_type make_min(this_ptr &&left, this_ptr &&right)
Definition: terms.hpp:703
CUDA bool embed(A &a, const U &u) const
Definition: terms.hpp:719
static constexpr size_t ITDiv
Definition: terms.hpp:541
static CUDA this_type make(SubTerm &&sub_term)
Definition: terms.hpp:651
battery::unique_ptr< Term< A, allocator_type >, allocator_type > this_ptr
Definition: terms.hpp:517
static CUDA this_type make_cdiv(this_ptr &&left, this_ptr &&right)
Definition: terms.hpp:695
static CUDA this_type make_neg(this_ptr &&sub_term)
Definition: terms.hpp:667
static constexpr size_t INaryAdd
Definition: terms.hpp:547
Binary< A, GroupSub< U >, allocator_type > Sub
Definition: terms.hpp:522
static CUDA this_type make_tdiv(this_ptr &&left, this_ptr &&right)
Definition: terms.hpp:687
static constexpr size_t IMin
Definition: terms.hpp:545
static CUDA this_type make_naryadd(battery::vector< this_type, allocator_type > &&sub_terms)
Definition: terms.hpp:711
Binary< A, GroupMul< U, EDIV >, allocator_type > Mul
Definition: terms.hpp:523
CUDA TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: terms.hpp:732
Binary< A, GroupDiv< U, CDIV >, allocator_type > CDiv
Definition: terms.hpp:526
Nary< Add > NaryAdd
Definition: terms.hpp:530
static CUDA this_type make_ediv(this_ptr &&left, this_ptr &&right)
Definition: terms.hpp:699
CUDA void project(const A &a, U &r) const
Definition: terms.hpp:723
static CUDA this_type make_fdiv(this_ptr &&left, this_ptr &&right)
Definition: terms.hpp:691
CUDA bool is(size_t kind) const
Definition: terms.hpp:646
static CUDA this_type make_sub(this_ptr &&left, this_ptr &&right)
Definition: terms.hpp:679
static constexpr size_t ICDiv
Definition: terms.hpp:543
static constexpr size_t IAdd
Definition: terms.hpp:538
CUDA size_t length() const
Definition: terms.hpp:736
static constexpr size_t IVar
Definition: terms.hpp:533
static CUDA this_type make_formula(formula_ptr &&sub_term)
Definition: terms.hpp:663
static constexpr size_t IFormula
Definition: terms.hpp:535
AD A
Definition: terms.hpp:513
Unary< A, NegOp< U >, allocator_type > Neg
Definition: terms.hpp:519
static constexpr size_t IAbs
Definition: terms.hpp:537
Unary< A, AbsOp< U >, allocator_type > Abs
Definition: terms.hpp:520
static CUDA this_type make_var(const AVar &avar)
Definition: terms.hpp:655
static constexpr size_t IMul
Definition: terms.hpp:540
this_type & operator=(this_type &&)=default
static CUDA this_type make_add(this_ptr &&left, this_ptr &&right)
Definition: terms.hpp:675
static constexpr size_t IConstant
Definition: terms.hpp:534
typename A::local_universe U
Definition: terms.hpp:514
Allocator allocator_type
Definition: terms.hpp:515
static CUDA this_type make_narymul(battery::vector< this_type, allocator_type > &&sub_terms)
Definition: terms.hpp:715
Binary< A, GroupDiv< U, TDIV >, allocator_type > TDiv
Definition: terms.hpp:524
Definition: terms.hpp:122
CUDA Unary(this_type &&other)
Definition: terms.hpp:142
typename A::local_universe U
Definition: terms.hpp:126
CUDA TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: terms.hpp:169
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
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
CUDA TFormula< Allocator > deinterpret(const A &, const Env &env, AType, Allocator allocator=Allocator()) const
Definition: terms.hpp:76
AD A
Definition: terms.hpp:50
CUDA Variable()
Definition: terms.hpp:57
CUDA void project(const A &a, U &r) const
Definition: terms.hpp:69
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< A > & operator=(Variable< A > &&other)=default
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 Sig sig()
Definition: terms.hpp:118
static CUDA const char * symbol()
Definition: terms.hpp:117
static CUDA void residual(const U &a, U &r)
Definition: terms.hpp:112
Definition: terms.hpp:178
static CUDA Sig sig()
Definition: terms.hpp:206
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
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 constexpr bool prefix_symbol
Definition: terms.hpp:282
static CUDA void left_residual(const U &a, const U &b, U &r)
Definition: terms.hpp:272
static CUDA char symbol()
Definition: terms.hpp:283
static CUDA Sig sig()
Definition: terms.hpp:284
static CUDA void right_residual(const U &a, const U &b, U &r)
Definition: terms.hpp:276
Definition: terms.hpp:288
static CUDA void right_residual(const U &a, const U &b, U &r)
Definition: terms.hpp:310
static CUDA Sig sig()
Definition: terms.hpp:316
Universe U
Definition: terms.hpp:291
static CUDA void project(const U &a, const U &b, U &r)
Definition: terms.hpp:292
static constexpr bool prefix_symbol
Definition: terms.hpp:314
static CUDA const char * symbol()
Definition: terms.hpp:315
static CUDA void left_residual(const U &a, const U &b, U &r)
Definition: terms.hpp:296
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 char symbol()
Definition: terms.hpp:260
static CUDA void left_residual(const U &a, const U &b, U &r)
Definition: terms.hpp:249
static CUDA Sig sig()
Definition: terms.hpp:261
static constexpr bool prefix_symbol
Definition: terms.hpp:259
Definition: terms.hpp:210
static CUDA Sig sig()
Definition: terms.hpp:228
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 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