Lattice Land Core Library
Loading...
Searching...
No Matches
flat_universe.hpp
Go to the documentation of this file.
1// Copyright 2023 Pierre Talbot
2
3#ifndef LALA_CORE_FLAT_UNIVERSE_HPP
4#define LALA_CORE_FLAT_UNIVERSE_HPP
5
6#include "arith_bound.hpp"
7
8namespace lala {
9
10template<class PreUniverse, class Mem>
11class FlatUniverse;
12
13/** Lattice of flat integers. */
14template<class VT, class Mem>
16
17/** Lattice of flat floating-point numbers. */
18template<class VT, class Mem>
20
21/** Aliases for lattice allocated on the stack (as local variable) and accessed by only one thread.
22 * To make things simpler, the underlying type is also chosen (when required). */
23namespace local {
26}
27
28template<class PreUniverse, class Mem>
30{
31 using U = PreUniverse;
32public:
33 using pre_universe = PreUniverse;
34 using value_type = typename pre_universe::value_type;
35 using memory_type = Mem;
37 template <class M> using this_type2 = FlatUniverse<pre_universe, M>;
39
40 static_assert(pre_universe::is_upper_bound);
41 static_assert(pre_universe::preserve_bot && pre_universe::preserve_top,
42 "The Flat lattice construction reuse the bottom and top elements of the pre-universe.\
43 Therefore, it must preserve bottom and top.");
44
45 constexpr static const bool is_abstract_universe = true;
46 constexpr static const bool sequential = Mem::sequential;
47 constexpr static const bool is_totally_ordered = false;
48 constexpr static const bool preserve_bot = true;
49 constexpr static const bool preserve_top = true;
50 constexpr static const bool preserve_join = true;
51 constexpr static const bool preserve_meet = false;
52 constexpr static const bool injective_concretization = pre_universe::injective_concretization;
53 constexpr static const bool preserve_concrete_covers = true;
54 constexpr static const char* name = "Flat";
55 constexpr static const bool is_arithmetic = pre_universe::is_arithmetic;
56
57 /** A pre-interpreted formula `x = value` ready to use.
58 * This is mainly for optimization purpose to avoid calling `interpret` each time we need it. */
59 CUDA static constexpr local_type eq_k(value_type k) {
60 return local_type(k);
61 }
62
63private:
64 using atomic_type = memory_type::template atomic_type<value_type>;
65 atomic_type val;
66
67public:
68 /** Similar to \f$[\![\mathit{false}]\!]\f$. */
69 CUDA static constexpr local_type bot() {
70 return local_type(U::bot());
71 }
72
73 /** Similar to \f$[\![\mathit{true}]\!]\f$. */
74 CUDA static constexpr local_type top() {
75 return local_type();
76 }
77 /** Initialize to the top of the flat lattice. */
78 CUDA constexpr FlatUniverse(): val(U::top()) {}
79 /** Similar to \f$[\![x = k]\!]\f$ for any name `x` where \f$ = \f$ is the equality. */
80 CUDA constexpr FlatUniverse(value_type k): val(k) {}
81 CUDA constexpr FlatUniverse(const this_type& other): FlatUniverse(other.value()) {}
82 CUDA constexpr FlatUniverse(this_type&& other): val(std::move(other.val)) {}
83
84 template <class M>
85 CUDA constexpr FlatUniverse(const this_type2<M>& other): FlatUniverse(other.value()) {}
86
87 template <class M>
88 CUDA constexpr FlatUniverse(const ArithBound<pre_universe, M>& other)
89 : FlatUniverse(other.value()) {}
90
91 template <class M>
94
95 /** The assignment operator can only be used in a sequential context.
96 * It is monotone but not extensive. */
97 template <class M>
98 CUDA constexpr this_type& operator=(const this_type2<M>& other) {
99 memory_type::store(val, other.value());
100 return *this;
101 }
102
103 CUDA constexpr this_type& operator=(const this_type& other) {
104 memory_type::store(val, other.value());
105 return *this;
106 }
107
108 CUDA constexpr value_type value() const { return memory_type::load(val); }
109
110 CUDA constexpr operator value_type() const { return value(); }
111
112 /** \return `true` whenever \f$ a = \top \f$, `false` otherwise.
113 * @parallel @order-preserving @increasing
114 */
115 CUDA constexpr local::B is_top() const {
116 return value() == U::top();
117 }
118
119 /** \return `true` whenever \f$ a = \bot \f$, `false` otherwise.
120 * @parallel @order-preserving @decreasing
121 */
122 CUDA constexpr local::B is_bot() const {
123 return value() == U::bot();
124 }
125
126 CUDA constexpr void join_top() {
127 memory_type::store(val, U::top());
128 }
129
130 template<class M1>
131 CUDA constexpr bool join(const this_type2<M1>& other) {
132 if(other.is_bot() || *this == other || is_top()) {
133 return false;
134 }
135 if(is_bot()) {
136 memory_type::store(val, other.value());
137 }
138 else {
139 join_top();
140 }
141 return true;
142 }
143
144 CUDA constexpr void meet_bot() {
145 memory_type::store(val, U::bot());
146 }
147
148 template<class M1>
149 CUDA constexpr bool meet(const this_type2<M1>& other) {
150 if(is_bot() || *this == other || other.is_top()) {
151 return false;
152 }
153 if(is_top()) {
154 memory_type::store(val, other.value());
155 }
156 else {
157 meet_bot();
158 }
159 return true;
160 }
161
162 /** \return \f$ x = k \f$ where `x` is a variable's name and `k` the current value.
163 `true` is returned whenever \f$ a = \top \f$, and `false` is returned whenever \f$ a = \bot \f$.
164 We always return an exact approximation, hence for any formula \f$ \llbracket \varphi \rrbracket = a \f$, we must have \f$ a = \llbracket \rrbracket a \llbracket \rrbracket \f$ where \f$ \rrbracket a \llbracket \f$ is the deinterpretation function. */
165 template<class Env, class Allocator = typename Env::allocator_type>
166 CUDA NI TFormula<Allocator> deinterpret(AVar avar, const Env& env, const Allocator& allocator = Allocator()) const {
167 using F = TFormula<Allocator>;
168 if(is_bot()) {
169 return F::make_false();
170 }
171 else if(is_top()) {
172 return F::make_true();
173 }
174 return F::make_binary(
175 F::make_avar(avar),
176 EQ,
178 UNTYPED, allocator);
179 }
180
181 /** Deinterpret the current value to a logical constant. */
182 template<class F>
183 CUDA NI F deinterpret() const {
184 return pre_universe::template deinterpret<F>(value());
185 }
186
187 /** Under-approximates the current element \f$ a \f$ w.r.t. \f$ \rrbracket a \llbracket \f$ into `ua`.
188 * For this abstract universe, it always returns `true` since the current element \f$ a \f$ is an exact representation of \f$ \rrbracket a \llbracket \f$. */
189 CUDA constexpr bool extract(local_type& ua) const {
190 ua.val = value();
191 return true;
192 }
193
194 /** Print the current element. */
195 CUDA NI void print() const {
196 if(is_bot()) {
197 printf("\u22A5");
198 }
199 else if(is_top()) {
200 printf("\u22A4");
201 }
202 else {
204 }
205 }
206
207public:
208 /** Expects a predicate of the form `x = k` or `k = x`, where `x` is any variable's name, and `k` a constant.
209 Existential formula \f$ \exists{x:T} \f$ can also be interpreted (only to top). */
210 template<bool diagnose = false, class F, class Env, class M2>
211 CUDA NI static bool interpret_tell(const F& f, const Env& env, this_type2<M2>& tell, IDiagnostics& diagnostics) {
212 if(f.is(F::E)) {
213 value_type k;
214 bool res = pre_universe::template interpret_type<diagnose>(f, k, diagnostics);
215 if(res) {
216 tell.meet(local_type(k));
217 }
218 return res;
219 }
220 else {
221 if(f.is_binary() && f.sig() == EQ) {
222 int idx_constant = f.seq(0).is_constant() ? 0 : (f.seq(1).is_constant() ? 1 : 100);
223 int idx_variable = f.seq(0).is_variable() ? 0 : (f.seq(1).is_variable() ? 1 : 100);
224 if(idx_constant + idx_variable == 1) {
225 const auto& k = f.seq(idx_constant);
226 const auto& x = f.seq(idx_variable);
227 value_type t;
228 if(pre_universe::template interpret_tell<diagnose>(k, t, diagnostics)) {
229 value_type a;
230 if(pre_universe::template interpret_ask<diagnose>(k, a, diagnostics)) {
231 if(a == t) {
232 tell.meet(local_type(t));
233 return true;
234 }
235 else {
236 RETURN_INTERPRETATION_ERROR("The constant has no exact interpretation which is required in this abstract universe.");
237 }
238 }
239 }
240 return false;
241 }
242 }
244 "Tell interpretation only supports existential quantifier and binary formulas of the form `t1 = t2` where t1 is a constant and t2 is a variable (or conversely).");
245 }
246 }
247
248 /** Same as `interpret_tell` without the support for existential quantifier. */
249 template<bool diagnose = false, class F, class Env, class M2>
250 CUDA NI static bool interpret_ask(const F& f, const Env& env, this_type2<M2>& ask, IDiagnostics& diagnostics) {
251 if(f.is(F::E)) {
252 RETURN_INTERPRETATION_ERROR("Ask interpretation only supports binary formulas of the form `t1 = t2` where t1 is a constant and t2 is a variable (or conversely).")
253 }
254 return interpret_tell<diagnose>(f, env, ask, diagnostics);
255 }
256
257 template<IKind kind, bool diagnose = false, class F, class Env, class M2>
258 CUDA NI static bool interpret(const F& f, const Env& env, this_type2<M2>& value, IDiagnostics& diagnostics) {
259 if constexpr(kind == IKind::ASK) {
260 return interpret_ask<diagnose>(f, env, value, diagnostics);
261 }
262 else {
263 return interpret_tell<diagnose>(f, env, value, diagnostics);
264 }
265 }
266
267public:
268 /** In-place projection of the result of the unary function `fun(a)`. */
269 CUDA constexpr void project(Sig fun, const local_type& a) {
270 if(a.is_bot()) {
271 meet_bot();
272 }
273 else if(!a.is_top()) {
274 meet(local_type(pre_universe::project(fun, a.value())));
275 }
276 }
277
278 /** In-place projection of the result of the binary function `fun(a, b)`. */
279 CUDA constexpr void project(Sig fun, const local_type& a, const local_type& b) {
280 if(a.is_bot() || b.is_bot()) {
281 meet_bot();
282 }
283 else if(!a.is_top() && !b.is_top()) {
284 if constexpr(is_arithmetic) {
285 if(is_division(fun) && b == pre_universe::zero()) {
286 meet_bot();
287 return;
288 }
289 }
290 meet(local_type(pre_universe::project(fun, a.value(), b.value())));
291 }
292 }
293
294 template<class Pre2, class Mem2>
295 friend class FlatUniverse;
296};
297
298// Lattice operators
299
300template<class Pre>
302 if(a == b) {
303 return a;
304 }
305 else if(a.is_bot() || b.is_top()) {
306 return b;
307 }
308 else if(b.is_bot() || a.is_top()) {
309 return a;
310 }
311 else {
313 }
314}
315
316template<class Pre>
318 if(a == b) {
319 return a;
320 }
321 else if(a.is_bot() || b.is_top()) {
322 return a;
323 }
324 else if(b.is_bot() || a.is_top()) {
325 return b;
326 }
327 else {
329 }
330}
331
332template<class Pre, class M1, class M2>
333CUDA constexpr bool operator<=(const FlatUniverse<Pre, M1>& a, const FlatUniverse<Pre, M2>& b) {
334 return a.is_bot() || b.is_top() || a == b;
335}
336
337template<class Pre, class M1, class M2>
338CUDA constexpr bool operator<(const FlatUniverse<Pre, M1>& a, const FlatUniverse<Pre, M2>& b) {
339 return (a.is_bot() || b.is_top()) && a != b;
340}
341
342template<class Pre, class M1, class M2>
343CUDA constexpr bool operator>=(const FlatUniverse<Pre, M1>& a, const FlatUniverse<Pre, M2>& b) {
344 return b <= a;
345}
346
347template<class Pre, class M1, class M2>
348CUDA constexpr bool operator>(const FlatUniverse<Pre, M1>& a, const FlatUniverse<Pre, M2>& b) {
349 return b < a;
350}
351
352template<class Pre, class M1, class M2>
353CUDA constexpr bool operator==(const FlatUniverse<Pre, M1>& a, const FlatUniverse<Pre, M2>& b) {
354 return a.value() == b.value();
355}
356
357template<class Pre, class M1, class M2>
358CUDA constexpr bool operator!=(const FlatUniverse<Pre, M1>& a, const FlatUniverse<Pre, M2>& b) {
359 return a.value() != b.value();
360}
361
362template<class Pre, class M>
363std::ostream& operator<<(std::ostream &s, const FlatUniverse<Pre, M> &a) {
364 if(a.is_bot()) {
365 s << "\u22A5";
366 }
367 else if(a.is_top()) {
368 s << "\u22A4";
369 }
370 else {
371 s << a.value();
372 }
373 return s;
374}
375
376} // namespace lala
377
378#endif
Definition ast.hpp:38
Definition arith_bound.hpp:118
Definition b.hpp:10
Definition flat_universe.hpp:30
typename pre_universe::value_type value_type
Definition flat_universe.hpp:34
CUDA constexpr local::B is_top() const
Definition flat_universe.hpp:115
CUDA constexpr void join_top()
Definition flat_universe.hpp:126
CUDA constexpr FlatUniverse(const this_type2< M > &other)
Definition flat_universe.hpp:85
static constexpr const char * name
Definition flat_universe.hpp:54
CUDA NI F deinterpret() const
Definition flat_universe.hpp:183
static constexpr const bool is_arithmetic
Definition flat_universe.hpp:55
CUDA static NI bool interpret(const F &f, const Env &env, this_type2< M2 > &value, IDiagnostics &diagnostics)
Definition flat_universe.hpp:258
static constexpr const bool injective_concretization
Definition flat_universe.hpp:52
static constexpr const bool is_abstract_universe
Definition flat_universe.hpp:45
Mem memory_type
Definition flat_universe.hpp:35
CUDA constexpr void project(Sig fun, const local_type &a, const local_type &b)
Definition flat_universe.hpp:279
CUDA constexpr FlatUniverse(this_type &&other)
Definition flat_universe.hpp:82
CUDA constexpr void meet_bot()
Definition flat_universe.hpp:144
CUDA constexpr FlatUniverse(const ArithBound< typename pre_universe::dual_type, M > &other)
Definition flat_universe.hpp:92
CUDA NI void print() const
Definition flat_universe.hpp:195
CUDA constexpr value_type value() const
Definition flat_universe.hpp:108
CUDA static NI bool interpret_ask(const F &f, const Env &env, this_type2< M2 > &ask, IDiagnostics &diagnostics)
Definition flat_universe.hpp:250
CUDA constexpr bool join(const this_type2< M1 > &other)
Definition flat_universe.hpp:131
static CUDA constexpr local_type bot()
Definition flat_universe.hpp:69
static constexpr const bool preserve_join
Definition flat_universe.hpp:50
CUDA constexpr void project(Sig fun, const local_type &a)
Definition flat_universe.hpp:269
this_type2< battery::local_memory > local_type
Definition flat_universe.hpp:38
CUDA constexpr FlatUniverse(const ArithBound< pre_universe, M > &other)
Definition flat_universe.hpp:88
CUDA constexpr FlatUniverse()
Definition flat_universe.hpp:78
static constexpr const bool sequential
Definition flat_universe.hpp:46
CUDA constexpr this_type & operator=(const this_type &other)
Definition flat_universe.hpp:103
static CUDA constexpr local_type top()
Definition flat_universe.hpp:74
static constexpr const bool preserve_concrete_covers
Definition flat_universe.hpp:53
static constexpr const bool preserve_meet
Definition flat_universe.hpp:51
static CUDA constexpr local_type eq_k(value_type k)
Definition flat_universe.hpp:59
CUDA constexpr this_type & operator=(const this_type2< M > &other)
Definition flat_universe.hpp:98
static constexpr const bool is_totally_ordered
Definition flat_universe.hpp:47
static constexpr const bool preserve_bot
Definition flat_universe.hpp:48
CUDA constexpr FlatUniverse(const this_type &other)
Definition flat_universe.hpp:81
CUDA NI TFormula< Allocator > deinterpret(AVar avar, const Env &env, const Allocator &allocator=Allocator()) const
Definition flat_universe.hpp:166
CUDA constexpr local::B is_bot() const
Definition flat_universe.hpp:122
CUDA constexpr bool extract(local_type &ua) const
Definition flat_universe.hpp:189
CUDA constexpr FlatUniverse(value_type k)
Definition flat_universe.hpp:80
CUDA static NI bool interpret_tell(const F &f, const Env &env, this_type2< M2 > &tell, IDiagnostics &diagnostics)
Definition flat_universe.hpp:211
static constexpr const bool preserve_top
Definition flat_universe.hpp:49
CUDA constexpr bool meet(const this_type2< M1 > &other)
Definition flat_universe.hpp:149
PreUniverse pre_universe
Definition flat_universe.hpp:33
Definition diagnostics.hpp:19
Definition ast.hpp:234
#define RETURN_INTERPRETATION_ERROR(MSG)
Definition diagnostics.hpp:155
Definition ast.hpp:210
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:530
CUDA constexpr LDual dual(const L &x)
Definition arith_bound.hpp:110
CUDA constexpr auto fjoin(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:463
CUDA constexpr bool operator==(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:503
Sig
Definition ast.hpp:94
@ EQ
Unary arithmetic function symbols.
Definition ast.hpp:112
CUDA constexpr bool operator<(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:484
CUDA NI constexpr bool is_division(Sig sig)
Definition ast.hpp:196
CUDA constexpr auto fmeet(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:470
CUDA constexpr bool operator>(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:497
#define UNTYPED
Definition sort.hpp:21