3#ifndef LALA_CORE_PRIMITIVE_UPSET_HPP
4#define LALA_CORE_PRIMITIVE_UPSET_HPP
17#include "battery/memory.hpp"
44template<
class PreUniverse,
class Mem>
47template<
class PreUniverse,
class Mem>
52template<
class VT,
class Mem>
57template<
class VT,
class Mem>
62template<
class VT,
class Mem>
67template<
class VT,
class Mem>
91 struct is_primitive_upset {
92 static constexpr bool value =
false;
95 template<
class PreUniverse,
class Mem>
96 struct is_primitive_upset<PrimitiveUpset<PreUniverse, Mem>> {
97 static constexpr bool value =
true;
101 inline constexpr bool is_primitive_upset_v = is_primitive_upset<T>::value;
109template <
class LDual,
class L>
110CUDA
constexpr LDual
dual(
const L& x) {
111 if(x.is_bot())
return LDual::bot();
112 if(x.is_top())
return LDual::top();
113 return LDual(x.value());
116template<
class PreUniverse,
class Mem>
119 using U = PreUniverse;
145 constexpr static const bool increasing = pre_universe::increasing;
146 constexpr static const char*
name = pre_universe::name;
150 static_assert(
is_totally_ordered,
"The underlying pre-universe must be totally ordered.");
160 "The pre-interpreted formula x >= k is only available over arithmetic universe such as integers, floating-point numbers and Boolean.\
161 Moreover, the underlying abstract universe must be increasing, otherwise this formula is not supported.");
171 "The pre-interpreted formula x <= k is only available over arithmetic universe such as integers, floating-point numbers and Boolean.\
172 Moreover, the underlying abstract universe must be decreasing, otherwise this formula is not supported.");
177 using atomic_type = memory_type::template atomic_type<value_type>;
201 memory_type::store(val, other.
value());
205 static_assert(
sequential,
"The operator= in `PrimitiveUpset` can only be used when the underlying memory is `sequential`.");
211 memory_type::store(val, other.
value());
215 static_assert(
sequential,
"The operator= in `PrimitiveUpset` can only be used when the underlying memory is `sequential`.");
225 return value() == U::top();
230 return value() == U::bot();
234 memory_type::store(val, U::top());
238 template<
class M1,
class M2>
242 if(U::strict_order(r1, r2)) {
243 memory_type::store(val, r2);
253 if(U::strict_order(r1, r2)) {
254 memory_type::store(val, r2);
260 memory_type::store(val, U::bot());
264 template<
class M1,
class M2>
268 if(U::strict_order(r2, r1)) {
269 memory_type::store(val, r2);
279 if(U::strict_order(r2, r1)) {
280 memory_type::store(val, r2);
293 return F::make_false();
296 return F::make_true();
298 return F::make_binary(
308 return pre_universe::template deinterpret<F>(
value());
333 template<
bool diagnose = false,
class F,
class M2>
334 CUDA NI
static bool interpret_tell_k_op_x(
const F& f,
const F& k,
Sig sig, this_type2<M2>&
tell,
IDiagnostics& diagnostics) {
336 bool res = pre_universe::template interpret_tell<diagnose>(k,
value, diagnostics);
338 if(sig ==
EQ || sig == U::sig_order()) {
341 else if(sig == U::sig_strict_order()) {
357 template<
bool diagnose = false,
class F,
class M2>
358 CUDA NI
static bool interpret_ask_k_op_x(
const F& f,
const F& k,
Sig sig, this_type2<M2>&
tell, IDiagnostics& diagnostics) {
360 bool res = pre_universe::template interpret_ask<diagnose>(k,
value, diagnostics);
362 if(sig == U::sig_order()) {
365 else if(sig ==
NEQ || sig == U::sig_strict_order()) {
377 template<
bool diagnose = false,
class F,
class M2>
378 CUDA NI
static bool interpret_tell_set(
const F& f,
const F& k, this_type2<M2>&
tell, IDiagnostics& diagnostics) {
379 const auto& set = k.s();
380 if(set.size() == 0) {
385 constexpr int bound_index =
increasing ? 0 : 1;
387 for(
int i = 0; i < set.size(); ++i) {
388 auto bound = battery::get<bound_index>(set[i]);
390 bool res = pre_universe::template interpret_tell<diagnose>(bound, set_element, diagnostics);
394 meet_s = pre_universe::meet(meet_s, set_element);
405 template<
bool diagnose = false,
class F,
class Env,
class M2>
408 typename U::value_type val;
409 bool res = pre_universe::template interpret_type<diagnose>(f, val, diagnostics);
417 int idx_constant = f.seq(0).is_constant() ? 0 : (f.seq(1).is_constant() ? 1 : 100);
418 int idx_variable = f.seq(0).is_variable() ? 0 : (f.seq(1).is_variable() ? 1 : 100);
419 if(idx_constant + idx_variable != 1) {
420 RETURN_INTERPRETATION_ERROR(
"Only binary formulas of the form `t1 <sig> t2` where if t1 is a constant and t2 is a variable (or conversely) are supported.")
422 const auto& k = f.seq(idx_constant);
424 if(idx_constant == 0) {
428 return interpret_tell_set<diagnose>(f, k,
tell, diagnostics);
433 return interpret_tell_k_op_x<diagnose>(f, k, sig,
tell, diagnostics);
448 template<
bool diagnose = false,
class F,
class Env,
class M2>
451 int idx_constant = f.seq(0).is_constant() ? 0 : (f.seq(1).is_constant() ? 1 : 100);
452 int idx_variable = f.seq(0).is_variable() ? 0 : (f.seq(1).is_variable() ? 1 : 100);
453 if(idx_constant + idx_variable != 1) {
454 RETURN_INTERPRETATION_ERROR(
"Only binary formulas of the form `t1 <sig> t2` where if t1 is a constant and t2 is a variable (or conversely) are supported.");
456 const auto& k = f.seq(idx_constant);
459 return interpret_ask_k_op_x<diagnose>(f, k, sig, ask, diagnostics);
470 template<IKind kind,
bool diagnose = false,
class F,
class Env,
class M2>
473 return interpret_tell<diagnose>(f, env,
value, diagnostics);
476 return interpret_ask<diagnose>(f, env,
value, diagnostics);
481 return pre_universe::is_supported_fun(sig);
498 template <Sig sig,
class M>
501 local_flat_type r1(a);
505 else if(r1.is_bot()) {
508 return pre_universe::template fun<sig>(r1);
516 template<Sig sig,
class M1,
class M2>
519 local_flat_type r1(a);
520 local_flat_type r2(b);
521 if(r1.is_top() || r2.is_top()) {
524 else if(r1.is_bot() || r2.is_bot()) {
528 if(r2.value() == pre_universe::zero()) {
532 return pre_universe::template fun<sig>(r1, r2);
546 template<Sig sig,
class Pre1,
class Mem1,
class Pre2,
class Mem2>
553 local_flat_type r1(a);
554 local_flat_type r2(b);
555 if (r2 != B::pre_universe::zero())
557 return fun<sig>(r1, r2);
560 if constexpr(B::preserve_concrete_covers) {
562 return fun<sig>(r1, local_flat_type(B::next(r2.value())));
565 (A::increasing && B::increasing ==
increasing) ||
566 (!A::increasing && !B::increasing &&
increasing) ||
567 (!A::increasing && B::increasing && !
increasing))
577 template <Sig sig,
class M1,
class M2>
580 static_assert(pre_universe::is_supported_fun(sig),
"Function unsupported by the current upset universe.");
581 static_assert(sig ==
MIN || sig ==
MAX,
"Only MIN and MAX are supported on Upset elements.");
583 local_flat_type r1(a);
584 local_flat_type r2(b);
585 if (r1.is_top() || r2.is_top())
589 else if (r1.is_bot() || r2.is_bot())
592 return r1.is_bot() ? b : a;
598 return pre_universe::template fun<sig>(r1, r2);
601 template<
class Pre2,
class Mem2>
607template<
class Pre,
class M1,
class M2>
609 return Pre::join(a, b);
612template<
class Pre,
class M1,
class M2>
614 return Pre::meet(a, b);
617template<
class Pre,
class M1,
class M2>
618CUDA
constexpr bool operator<=(
const PrimitiveUpset<Pre, M1>& a,
const PrimitiveUpset<Pre, M2>& b) {
619 return Pre::order(a, b);
622template<
class Pre,
class M1,
class M2>
624 return Pre::strict_order(a, b);
627template<
class Pre,
class M1,
class M2>
628CUDA
constexpr bool operator>=(
const PrimitiveUpset<Pre, M1>& a,
const PrimitiveUpset<Pre, M2>& b) {
629 return Pre::order(b, a);
632template<
class Pre,
class M1,
class M2>
634 return Pre::strict_order(b, a);
637template<
class Pre,
class M1,
class M2>
642template<
class Pre,
class M1,
class M2>
643CUDA
constexpr bool operator!=(
const PrimitiveUpset<Pre, M1>& a,
const PrimitiveUpset<Pre, M2>& b) {
644 return a.value() != b.value();
647template<
class Pre,
class M>
Definition flat_universe.hpp:30
Definition diagnostics.hpp:19
Definition primitive_upset.hpp:118
static constexpr const bool is_totally_ordered
Definition primitive_upset.hpp:137
static constexpr const bool increasing
Definition primitive_upset.hpp:145
CUDA constexpr this_type & operator=(const this_type &other)
Definition primitive_upset.hpp:209
CUDA static NI bool interpret_ask(const F &f, const Env &, this_type2< M2 > &ask, IDiagnostics &diagnostics)
Definition primitive_upset.hpp:449
CUDA constexpr this_type & operator=(const this_type2< M > &other)
Definition primitive_upset.hpp:199
CUDA constexpr PrimitiveUpset(const this_type2< M > &other)
Definition primitive_upset.hpp:194
static CUDA constexpr local_type guarded_div(const PrimitiveUpset< Pre1, Mem1 > &a, const PrimitiveUpset< Pre2, Mem2 > &b)
Definition primitive_upset.hpp:547
CUDA constexpr local::BInc is_top() const
Definition primitive_upset.hpp:224
CUDA NI void print() const
Definition primitive_upset.hpp:319
CUDA constexpr value_type value() const
Definition primitive_upset.hpp:219
CUDA constexpr PrimitiveUpset(value_type x)
Definition primitive_upset.hpp:189
static constexpr const bool is_abstract_universe
Definition primitive_upset.hpp:135
CUDA constexpr this_type & dtell(const this_type2< M1 > &other, BInc< M2 > &has_changed)
Definition primitive_upset.hpp:265
CUDA constexpr bool extract(local_type &ua) const
Definition primitive_upset.hpp:313
static constexpr const char * name
Definition primitive_upset.hpp:146
CUDA NI F deinterpret() const
Definition primitive_upset.hpp:307
CUDA constexpr PrimitiveUpset(const this_type &other)
Definition primitive_upset.hpp:190
static CUDA constexpr local_type prev(const this_type2< Mem > &a)
Definition primitive_upset.hpp:489
static CUDA constexpr local_type fun(const flat_type< M > &a)
Definition primitive_upset.hpp:499
CUDA constexpr this_type & tell(const this_type2< M1 > &other)
Definition primitive_upset.hpp:250
static CUDA constexpr this_type geq_k(value_type k)
Definition primitive_upset.hpp:154
static CUDA constexpr local_type fun(const flat_type< M1 > &a, const flat_type< M2 > &b)
Definition primitive_upset.hpp:517
static CUDA constexpr local_type bot()
Definition primitive_upset.hpp:182
constexpr PrimitiveUpset(this_type &&other)=default
static CUDA constexpr this_type leq_k(value_type k)
Definition primitive_upset.hpp:165
CUDA constexpr local::BDec is_bot() const
Definition primitive_upset.hpp:229
CUDA constexpr this_type & dtell(const this_type2< M1 > &other)
Definition primitive_upset.hpp:276
static constexpr const bool preserve_meet
Definition primitive_upset.hpp:141
CUDA constexpr this_type & dtell_bot()
Definition primitive_upset.hpp:259
static CUDA constexpr local_type fun(const this_type2< M1 > &a, const this_type2< M2 > &b)
Definition primitive_upset.hpp:578
static CUDA constexpr local_type next(const this_type2< Mem > &a)
Definition primitive_upset.hpp:485
typename pre_universe::value_type value_type
Definition primitive_upset.hpp:122
static CUDA constexpr bool is_supported_fun(Sig sig)
Definition primitive_upset.hpp:480
CUDA constexpr PrimitiveUpset()
Definition primitive_upset.hpp:187
PreUniverse pre_universe
Definition primitive_upset.hpp:121
CUDA static NI bool interpret(const F &f, const Env &env, this_type2< M2 > &value, IDiagnostics &diagnostics)
Definition primitive_upset.hpp:471
Mem memory_type
Definition primitive_upset.hpp:123
static constexpr const bool complemented
Definition primitive_upset.hpp:144
static constexpr const bool preserve_bot
Definition primitive_upset.hpp:138
this_type2< battery::local_memory > local_type
Definition primitive_upset.hpp:130
static CUDA constexpr local_type top()
Definition primitive_upset.hpp:185
CUDA NI TFormula< typename Env::allocator_type > deinterpret(AVar avar, const Env &env) const
Definition primitive_upset.hpp:290
CUDA static NI bool interpret_tell(const F &f, const Env &, this_type2< M2 > &tell, IDiagnostics &diagnostics)
Definition primitive_upset.hpp:406
PrimitiveUpset< pre_universe, memory_type > this_type
Definition primitive_upset.hpp:124
static constexpr const bool is_arithmetic
Definition primitive_upset.hpp:148
static constexpr const bool preserve_join
Definition primitive_upset.hpp:140
static constexpr const bool sequential
Definition primitive_upset.hpp:136
CUDA constexpr this_type & tell_top()
Definition primitive_upset.hpp:233
static constexpr const bool injective_concretization
Definition primitive_upset.hpp:142
static constexpr const bool preserve_top
Definition primitive_upset.hpp:139
static constexpr const bool preserve_concrete_covers
Definition primitive_upset.hpp:143
CUDA constexpr this_type & tell(const this_type2< M1 > &other, BInc< M2 > &has_changed)
Definition primitive_upset.hpp:239
#define RETURN_INTERPRETATION_ERROR(MSG)
Definition diagnostics.hpp:155
CUDA NI void print(const lala::Sig &sig)
Definition ast.hpp:212
Definition abstract_deps.hpp:14
std::ostream & operator<<(std::ostream &s, const CartesianProduct< A, As... > &cp)
Definition cartesian_product.hpp:597
CUDA constexpr LDual dual(const L &x)
Definition primitive_upset.hpp:110
CUDA NI Sig converse_comparison(Sig sig)
Definition algorithm.hpp:377
CUDA constexpr bool operator==(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:572
@ NEQ
Equality relations.
Definition ast.hpp:112
@ EQ
Unary arithmetic function symbols.
Definition ast.hpp:112
@ IN
Set membership predicate.
Definition ast.hpp:108
@ MIN
Unary arithmetic function symbols.
Definition ast.hpp:97
@ MAX
Binary arithmetic function symbols.
Definition ast.hpp:97
CUDA constexpr auto join(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:534
CUDA constexpr auto meet(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:541
CUDA constexpr bool operator<(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:554
CUDA NI bool is_comparison(const F &f)
Definition algorithm.hpp:356
CUDA NI const char * string_of_sig(Sig sig)
Definition ast.hpp:121
CUDA NI constexpr bool is_division(Sig sig)
Definition ast.hpp:196
CUDA constexpr bool operator>(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:566
#define UNTYPED
Definition sort.hpp:21