Lattice Land Core Library
Loading...
Searching...
No Matches
pre_finc.hpp
Go to the documentation of this file.
1// Copyright 2022 Pierre Talbot
2
3#ifndef LALA_CORE_PRE_FINC_HPP
4#define LALA_CORE_PRE_FINC_HPP
5
6#include "../logic/logic.hpp"
7
8namespace lala {
9
10template <class VT>
11struct PreFDec;
12
13/** `PreFInc` is a pre-abstract universe \f$ \langle \mathbb{F}\setminus\{NaN\}, \leq \rangle \f$ totally ordered by the floating-point arithmetic comparison operator.
14 We work on a subset of floating-point numbers without NaN.
15 It is used to represent (and possibly approximate) constraints of the form \f$ x \geq k \f$ where \f$ k \f$ is a real number.
16*/
17template<class VT>
18struct PreFInc {
21 using value_type = VT;
23
24 constexpr static const bool is_totally_ordered = true;
25 constexpr static const bool preserve_bot = true;
26 constexpr static const bool preserve_top = true;
27 constexpr static const bool preserve_join = true;
28 constexpr static const bool preserve_meet = true;
29 /** Note that -0 and +0 are treated as the same element. */
30 constexpr static const bool injective_concretization = true;
31 constexpr static const bool preserve_concrete_covers = false;
32 constexpr static const bool complemented = false;
33 constexpr static const bool increasing = true;
34 constexpr static const char* name = "FInc";
35 constexpr static const bool is_arithmetic = true;
36 CUDA constexpr static value_type zero() { return 0.0; }
37 CUDA constexpr static value_type one() { return 1.0; }
38
39private:
40 template<bool diagnose, bool is_tell, class F>
41 CUDA NI static bool interpret(const F& f, value_type& k, IDiagnostics& diagnostics) {
42 if(f.is(F::Z)) {
43 auto z = f.z();
44 // We do not consider the min and max values of integers to be infinities when they are part of the logical formula.
45 if constexpr(is_tell) {
46 k = battery::rd_cast<value_type, decltype(z), false>(z);
47 }
48 else {
49 k = battery::ru_cast<value_type, decltype(z), false>(z);
50 }
51 return true;
52 }
53 else if(f.is(F::R)) {
54 if constexpr(is_tell) {
55 k = battery::rd_cast<value_type>(battery::get<0>(f.r()));
56 }
57 else {
58 k = battery::ru_cast<value_type>(battery::get<1>(f.r()));
59 }
60 return true;
61 }
62 RETURN_INTERPRETATION_ERROR("Only a constant of sort `Int` or `Real` can be interpreted by a floating-point abstract universe.")
63 }
64
65public:
66 /** Interpret a constant in the lattice of increasing floating-point numbers `FInc` according to the upset semantics (see universe.hpp for explanation).
67 Interpretations:
68 * Formulas of kind `F::Z` might be over-approximated (if the integer cannot be represented in a floating-point number because it is too large).
69 * Formulas of kind `F::R` might be over-approximated to the lower bound of the interval (if the real number is represented by an interval [lb..ub] where lb != ub).
70 * Other kind of formulas are not supported. */
71 template<bool diagnose, class F>
72 CUDA static bool interpret_tell(const F& f, value_type& k, IDiagnostics& diagnostics) {
73 return interpret<diagnose, true>(f, k, diagnostics);
74 }
75
76 /** Same as `interpret_tell` but the constant is under-approximated instead. */
77 template<bool diagnose, class F>
78 CUDA static bool interpret_ask(const F& f, value_type& k, IDiagnostics& diagnostics) {
79 return interpret<diagnose, false>(f, k, diagnostics);
80 }
81
82 /** Verify if the type of a variable, introduced by an existential quantifier, is compatible with the current abstract universe.
83 Interpretations:
84 * Variables of type `Int` are always over-approximated (\f$ \mathbb{Z} \subseteq \gamma(\bot) \f$).
85 * Variables of type `Real` are represented exactly (only initially because \f$ \mathbb{R} = \gamma(\bot) \f$). */
86 template<bool diagnose, class F>
87 CUDA NI static bool interpret_type(const F& f, value_type& k, IDiagnostics& diagnostics) {
88 assert(f.is(F::E));
89 const auto& vname = battery::get<0>(f.exists());
90 const auto& cty = battery::get<1>(f.exists());
91 if(cty.is_int()) {
92 k = bot();
93 RETURN_INTERPRETATION_WARNING("Variable `" + vname + "` of sort `Int` is over-approximated in a floating-point abstract universe.");
94 }
95 else if(cty.is_real()) {
96 k = bot();
97 return true;
98 }
99 else {
100 RETURN_INTERPRETATION_ERROR("Variable `" + vname + "` can only be of sort `Real`, or be over-approximated if the sort is `Bool` or `Int`.");
101 }
102 }
103
104 /** Given a floating-point value, create a logical constant representing that value.
105 * The constant is represented by a singleton interval of `double` [v..v].
106 * Note that the lattice order has no influence here.
107 * \pre `v != bot()` and `v != top()`.
108 */
109 template<class F>
110 CUDA static F deinterpret(const value_type& v) {
111 return F::make_real(v, v);
112 }
113
114 /** The logical predicate symbol corresponding to the order of this pre-universe.
115 We have \f$ a \leq_\mathit{FInc} b \Leftrightarrow a \leq b \f$.
116 \return The logical symbol `LEQ`. */
117 CUDA static constexpr Sig sig_order() { return LEQ; }
118
119 /** The logical predicate symbol corresponding to the strict order of this pre-universe.
120 We have \f$ a <_\mathit{FInc} b \Leftrightarrow a < b \f$.
121 \return The logical symbol `LT`. */
122 CUDA static constexpr Sig sig_strict_order() { return LT; }
123
124 /** \f$ \bot \f$ is represented by the floating-point negative infinity value. */
125 CUDA static constexpr value_type bot() {
126 return battery::limits<value_type>::bot();
127 }
128
129 /** \f$ \top \f$ is represented by the floating-point positive infinity value. */
130 CUDA static constexpr value_type top() {
131 return battery::limits<value_type>::top();
132 }
133
134 /** \return \f$ x \sqcup y \f$ defined as \f$ \mathit{max}(x, y) \f$. */
135 CUDA static constexpr value_type join(value_type x, value_type y) { return battery::max(x, y); }
136
137 /** \return \f$ x \sqcap y \f$ defined as \f$ \mathit{min}(x, y) \f$. */
138 CUDA static constexpr value_type meet(value_type x, value_type y) { return battery::min(x, y); }
139
140 /** \return \f$ \mathit{true} \f$ if \f$ x \leq_\mathit{FInc} y \f$ where the order \f$ \leq_\mathit{FInc} \f$ is the natural arithmetic ordering, otherwise returns \f$ \mathit{false} \f$. */
141 CUDA static constexpr bool order(value_type x, value_type y) { return x <= y; }
142
143 /** \return \f$ \mathit{true} \f$ if \f$ x <_\mathit{FInc} y \f$ where the order \f$ <_\mathit{ZInc} \f$ is the natural arithmetic ordering, otherwise returns \f$ \mathit{false} \f$. */
144 CUDA static constexpr bool strict_order(value_type x, value_type y) { return x < y; }
145
146 /** From a lattice perspective, this function returns an element \f$ y \f$ such that \f$ y \f$ is a cover of \f$ x \f$.
147
148 \return The next value of \f$ x \f$ in the floating-point increasing chain \f$ -\infty, \ldots, prev(-2.0), -2.0, next(-2.0), \ldots, \infty \f$ is the next representable value of \f$ x \f$ when \f$ x \not\in \{\infty, -\infty\} \f$ and \f$ x \f$ otherwise.
149 Note that \f$ 0 \f$ is considered to be represented by a single value. */
150 CUDA static constexpr value_type next(value_type x) {
151 if(x == bot() || x == top()) {
152 return x;
153 }
154 if(x == value_type{-0.0}) {
155 return battery::nextafter(value_type{+0.0}, top());
156 }
157 return battery::nextafter(x, top());
158 }
159
160 /** From a lattice perspective, this function returns an element \f$ y \f$ such that \f$ x \f$ is a cover of \f$ y \f$.
161
162 \return The previous value of \f$ x \f$ in the floating-point increasing chain \f$ -\infty, \ldots, prev(-2.0), -2.0, next(-2.0), \ldots, \infty \f$ is the previous representable value of \f$ x \f$ when \f$ x \not\in \{\infty, -\infty\} \f$ and \f$ x \f$ otherwise.
163 \f$ 0 \f$ is considered to be represented by a single value. */
164 CUDA static constexpr value_type prev(value_type x) {
165 if(x == bot() || x == top()) {
166 return x;
167 }
168 if(x == value_type{+0.0}) {
169 return battery::nextafter(value_type{-0.0}, bot());
170 }
171 return battery::nextafter(x, bot());
172 }
173
174 CUDA NI static constexpr bool is_supported_fun(Sig sig) {
175 switch(sig) {
176 case NEG:
177 case ABS:
178 case MIN:
179 case MAX:
180 case EQ:
181 case NEQ:
182 case LEQ:
183 case GEQ:
184 case LT:
185 case GT:
186 case ADD:
187 case SUB:
188 case MUL:
189 case DIV:
190 return true;
191 default: return false;
192 }
193 }
194
195 template<Sig sig>
196 CUDA static constexpr value_type fun(value_type x) {
197 static_assert(is_supported_fun(sig), "Unsupported unary function.");
198 // Negation and absolute functions are exact in floating-point arithmetic.
199 switch(sig) {
200 case NEG: return -x;
201 case ABS: return abs(x);
202 default: assert(0); return x;
203 }
204 }
205
206 template<Sig sig>
207 CUDA NI static constexpr value_type fun(value_type x, value_type y) {
208 static_assert(is_supported_fun(sig), "Unsupported binary function.");
209 switch(sig) {
210 case ADD: return battery::add_down(x, y);
211 case SUB: return battery::sub_down(x, y);
212 case MUL: return battery::mul_down(x, y);
213 case DIV: return battery::div_down(x, y);
214 case MIN: return battery::min(x, y);
215 case MAX: return battery::max(x, y);
216 case EQ: return x == y;
217 case NEQ: return x != y;
218 case LEQ: return x <= y;
219 case GEQ: return x >= y;
220 case LT: return x < y;
221 case GT: return x >= y;
222 default: assert(0); return x;
223 }
224 }
225};
226
227} // namespace lala
228
229#endif
Definition diagnostics.hpp:19
#define RETURN_INTERPRETATION_WARNING(MSG)
Definition diagnostics.hpp:159
#define RETURN_INTERPRETATION_ERROR(MSG)
Definition diagnostics.hpp:155
Definition abstract_deps.hpp:14
Sig
Definition ast.hpp:94
@ NEQ
Equality relations.
Definition ast.hpp:112
@ LEQ
Unary arithmetic function symbols.
Definition ast.hpp:113
@ EQ
Unary arithmetic function symbols.
Definition ast.hpp:112
@ GEQ
Unary arithmetic function symbols.
Definition ast.hpp:113
@ ADD
Unary arithmetic function symbols.
Definition ast.hpp:97
@ MIN
Unary arithmetic function symbols.
Definition ast.hpp:97
@ DIV
Unary arithmetic function symbols.
Definition ast.hpp:101
@ GT
Arithmetic comparison predicates. When applied to set, it corresponds to the lexicographic ordering o...
Definition ast.hpp:113
@ MAX
Binary arithmetic function symbols.
Definition ast.hpp:97
@ LT
Unary arithmetic function symbols.
Definition ast.hpp:113
@ ABS
Unary arithmetic function symbols.
Definition ast.hpp:96
@ SUB
Unary arithmetic function symbols.
Definition ast.hpp:97
@ MUL
Unary arithmetic function symbols.
Definition ast.hpp:97
@ NEG
Unary arithmetic function symbols.
Definition ast.hpp:96
Definition pre_fdec.hpp:19
Definition pre_finc.hpp:18
static CUDA constexpr value_type prev(value_type x)
Definition pre_finc.hpp:164
static CUDA bool interpret_tell(const F &f, value_type &k, IDiagnostics &diagnostics)
Definition pre_finc.hpp:72
static CUDA constexpr value_type top()
Definition pre_finc.hpp:130
static CUDA F deinterpret(const value_type &v)
Definition pre_finc.hpp:110
static constexpr const bool preserve_top
Definition pre_finc.hpp:26
static constexpr const bool is_totally_ordered
Definition pre_finc.hpp:24
static CUDA constexpr value_type fun(value_type x)
Definition pre_finc.hpp:196
static CUDA constexpr bool order(value_type x, value_type y)
Definition pre_finc.hpp:141
static CUDA constexpr value_type join(value_type x, value_type y)
Definition pre_finc.hpp:135
static constexpr const bool increasing
Definition pre_finc.hpp:33
static constexpr const char * name
Definition pre_finc.hpp:34
static constexpr const bool preserve_meet
Definition pre_finc.hpp:28
VT value_type
Definition pre_finc.hpp:21
static CUDA constexpr Sig sig_strict_order()
Definition pre_finc.hpp:122
CUDA static constexpr value_type zero()
Definition pre_finc.hpp:36
static CUDA constexpr value_type bot()
Definition pre_finc.hpp:125
CUDA static NI bool interpret_type(const F &f, value_type &k, IDiagnostics &diagnostics)
Definition pre_finc.hpp:87
static constexpr const bool preserve_join
Definition pre_finc.hpp:27
CUDA static NI constexpr bool is_supported_fun(Sig sig)
Definition pre_finc.hpp:174
static CUDA constexpr Sig sig_order()
Definition pre_finc.hpp:117
PreFInc< VT > this_type
Definition pre_finc.hpp:19
static CUDA constexpr value_type next(value_type x)
Definition pre_finc.hpp:150
static constexpr const bool complemented
Definition pre_finc.hpp:32
static constexpr const bool preserve_concrete_covers
Definition pre_finc.hpp:31
static CUDA constexpr value_type meet(value_type x, value_type y)
Definition pre_finc.hpp:138
static constexpr const bool is_arithmetic
Definition pre_finc.hpp:35
static constexpr const bool injective_concretization
Definition pre_finc.hpp:30
static CUDA bool interpret_ask(const F &f, value_type &k, IDiagnostics &diagnostics)
Definition pre_finc.hpp:78
static constexpr const bool preserve_bot
Definition pre_finc.hpp:25
CUDA static constexpr value_type one()
Definition pre_finc.hpp:37
static CUDA constexpr bool strict_order(value_type x, value_type y)
Definition pre_finc.hpp:144
CUDA static NI constexpr value_type fun(value_type x, value_type y)
Definition pre_finc.hpp:207