svf-tools 1.0.682 → 1.0.684

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svf-tools",
3
- "version": "1.0.682",
3
+ "version": "1.0.684",
4
4
  "description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,353 @@
1
+ //===- AddressValue.h ----Address Value Sets-------------------------//
2
+ //
3
+ // SVF: Static Value-Flow Analysis
4
+ //
5
+ // Copyright (C) <2013-2022> <Yulei Sui>
6
+ //
7
+
8
+ // This program is free software: you can redistribute it and/or modify
9
+ // it under the terms of the GNU Affero General Public License as published by
10
+ // the Free Software Foundation, either version 3 of the License, or
11
+ // (at your option) any later version.
12
+
13
+ // This program is distributed in the hope that it will be useful,
14
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ // GNU Affero General Public License for more details.
17
+
18
+ // You should have received a copy of the GNU Affero General Public License
19
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ //
21
+ //===----------------------------------------------------------------------===//
22
+ /*
23
+ * BoundedZ3Expr.h
24
+ *
25
+ * Created on: Mar 20, 2023
26
+ * Author: Xiao Cheng
27
+ *
28
+ */
29
+
30
+ #ifndef SVF_BOUNDEDZ3EXPR_H
31
+ #define SVF_BOUNDEDZ3EXPR_H
32
+
33
+ #include "Util/Z3Expr.h"
34
+
35
+ namespace SVF
36
+ {
37
+
38
+ /*!
39
+ * Atom Z3 expr for unlimited precision integers
40
+ */
41
+ class BoundedZ3Expr : public Z3Expr
42
+ {
43
+
44
+ public:
45
+ BoundedZ3Expr() = default;
46
+
47
+ BoundedZ3Expr(const Z3Expr &z3Expr) : Z3Expr(z3Expr) {}
48
+
49
+ BoundedZ3Expr(const z3::expr &e) : Z3Expr(e) {}
50
+
51
+ BoundedZ3Expr(s32_t i) : Z3Expr(i) {}
52
+
53
+ BoundedZ3Expr(int64_t i) : Z3Expr(getContext().int_val(i)) {}
54
+
55
+ BoundedZ3Expr(const BoundedZ3Expr &z3Expr) : Z3Expr(z3Expr) {}
56
+
57
+
58
+ inline BoundedZ3Expr &operator=(const BoundedZ3Expr &rhs)
59
+ {
60
+ Z3Expr::operator=(rhs);
61
+ return *this;
62
+ }
63
+
64
+ BoundedZ3Expr(BoundedZ3Expr &&z3Expr) : Z3Expr(z3Expr) {}
65
+
66
+
67
+ inline BoundedZ3Expr &operator=(BoundedZ3Expr &&rhs)
68
+ {
69
+ Z3Expr::operator=(rhs);
70
+ return *this;
71
+ }
72
+
73
+ bool is_plus_infinite() const
74
+ {
75
+ return eq(*this, getContext().int_const("+oo"));
76
+ }
77
+
78
+ bool is_minus_infinite() const
79
+ {
80
+ return eq(*this, getContext().int_const("-oo"));
81
+ }
82
+
83
+ bool is_infinite() const
84
+ {
85
+ return is_plus_infinite() || is_minus_infinite();
86
+ }
87
+
88
+ void set_plus_infinite()
89
+ {
90
+ *this = plus_infinity();
91
+ }
92
+
93
+ void set_minus_infinite()
94
+ {
95
+ *this = minus_infinity();
96
+ }
97
+
98
+ static BoundedZ3Expr plus_infinity()
99
+ {
100
+ return getContext().int_const("+oo");
101
+ }
102
+
103
+ static BoundedZ3Expr minus_infinity()
104
+ {
105
+ return getContext().int_const("-oo");
106
+ }
107
+
108
+ static z3::context &getContext()
109
+ {
110
+ return Z3Expr::getContext();
111
+ }
112
+
113
+ bool is_zero() const
114
+ {
115
+ return getExpr().is_numeral() && getExpr().get_numeral_int64() == 0;
116
+ }
117
+
118
+ static bool isZero(const BoundedZ3Expr &expr)
119
+ {
120
+ return expr.is_numeral() && expr.get_numeral_int64() == 0;
121
+ }
122
+
123
+ BoundedZ3Expr equal(const BoundedZ3Expr &rhs) const
124
+ {
125
+ return getExpr() == rhs.getExpr();
126
+ }
127
+
128
+ BoundedZ3Expr leq(const BoundedZ3Expr &rhs) const
129
+ {
130
+ return getExpr() <= rhs.getExpr();
131
+ }
132
+
133
+ BoundedZ3Expr geq(const BoundedZ3Expr &rhs) const
134
+ {
135
+ return getExpr() >= rhs.getExpr();
136
+ }
137
+
138
+ /// Reload operator
139
+ //{%
140
+ friend BoundedZ3Expr operator==(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
141
+ {
142
+ return lhs.equal(rhs);
143
+ }
144
+
145
+ friend BoundedZ3Expr operator!=(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
146
+ {
147
+ return !lhs.equal(rhs);
148
+ }
149
+
150
+ friend BoundedZ3Expr operator>(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
151
+ {
152
+ return !lhs.leq(rhs);
153
+ }
154
+
155
+ friend BoundedZ3Expr operator<(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
156
+ {
157
+ return !lhs.geq(rhs);
158
+ }
159
+
160
+ friend BoundedZ3Expr operator<=(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
161
+ {
162
+ return lhs.leq(rhs);
163
+ }
164
+
165
+ friend BoundedZ3Expr operator>=(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
166
+ {
167
+ return lhs.geq(rhs);
168
+ }
169
+
170
+ friend BoundedZ3Expr operator+(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
171
+ {
172
+ if (!lhs.is_infinite() && !rhs.is_infinite())
173
+ return lhs.getExpr() + rhs.getExpr();
174
+ else if (!lhs.is_infinite() && rhs.is_infinite())
175
+ return rhs;
176
+ else if (lhs.is_infinite() && !rhs.is_infinite())
177
+ return lhs;
178
+ else if (eq(lhs, rhs))
179
+ return lhs;
180
+ else
181
+ assert(false && "undefined operation +oo + -oo");
182
+ }
183
+
184
+ friend BoundedZ3Expr operator-(const BoundedZ3Expr &lhs)
185
+ {
186
+ return -lhs.getExpr();
187
+ }
188
+
189
+ friend BoundedZ3Expr operator-(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
190
+ {
191
+ if (!lhs.is_infinite() && !rhs.is_infinite())
192
+ return lhs.getExpr() - rhs.getExpr();
193
+ else if (!lhs.is_infinite() && rhs.is_infinite())
194
+ return -rhs;
195
+ else if (lhs.is_infinite() && !rhs.is_infinite())
196
+ return lhs;
197
+ else if (!eq(lhs, rhs))
198
+ return lhs;
199
+ else
200
+ assert(false && "undefined operation +oo - +oo");
201
+ }
202
+
203
+ friend BoundedZ3Expr operator*(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
204
+ {
205
+ if (lhs.is_zero() || rhs.is_zero()) return 0;
206
+ else if (lhs.is_infinite() && rhs.is_infinite())
207
+ return eq(lhs, rhs) ? plus_infinity() : minus_infinity();
208
+ else if (lhs.is_infinite())
209
+ return ite(rhs.getExpr() > 0, lhs, -lhs);
210
+ else if (rhs.is_infinite())
211
+ return ite(lhs.getExpr() > 0, rhs, -rhs);
212
+ else
213
+ return lhs.getExpr() * rhs.getExpr();
214
+ }
215
+
216
+ friend BoundedZ3Expr operator/(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
217
+ {
218
+ if (rhs.is_zero()) assert(false && "divide by zero");
219
+ else if (!lhs.is_infinite() && !rhs.is_infinite())
220
+ return lhs.getExpr() / rhs.getExpr();
221
+ else if (!lhs.is_infinite() && rhs.is_infinite())
222
+ return 0;
223
+ else if (lhs.is_infinite() && !rhs.is_infinite())
224
+ return ite(rhs.getExpr() > 0, lhs, -lhs);
225
+ else
226
+ // TODO: +oo/-oo L'Hôpital's rule?
227
+ return eq(lhs, rhs) ? plus_infinity() : minus_infinity();
228
+
229
+ }
230
+
231
+ friend BoundedZ3Expr operator%(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
232
+ {
233
+ if (rhs.is_zero()) assert(false && "divide by zero");
234
+ else if (!lhs.is_infinite() && !rhs.is_infinite())
235
+ return lhs.getExpr() % rhs.getExpr();
236
+ else if (!lhs.is_infinite() && rhs.is_infinite())
237
+ return 0;
238
+ // TODO: not sure
239
+ else if (lhs.is_infinite() && !rhs.is_infinite())
240
+ return ite(rhs.getExpr() > 0, lhs, -lhs);
241
+ else
242
+ // TODO: +oo/-oo L'Hôpital's rule?
243
+ return eq(lhs, rhs) ? plus_infinity() : minus_infinity();
244
+ }
245
+
246
+ friend BoundedZ3Expr operator^(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
247
+ {
248
+ return bv2int(int2bv(64, lhs.getExpr()) ^ int2bv(64, rhs.getExpr()), true);
249
+ }
250
+
251
+ friend BoundedZ3Expr operator&(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
252
+ {
253
+ return bv2int(int2bv(64, lhs.getExpr()) & int2bv(64, rhs.getExpr()), true);
254
+ }
255
+
256
+ friend BoundedZ3Expr operator|(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
257
+ {
258
+ return bv2int(int2bv(64, lhs.getExpr()) | int2bv(64, rhs.getExpr()), true);
259
+ }
260
+
261
+ friend BoundedZ3Expr ashr(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
262
+ {
263
+ if (lhs.is_zero())
264
+ return lhs;
265
+ else if (lhs.is_infinite())
266
+ return lhs;
267
+ else if (rhs.is_infinite())
268
+ return ite(lhs.getExpr() >= 0, BoundedZ3Expr(0), BoundedZ3Expr(-1));
269
+ else
270
+ return ashr(lhs.getExpr(), rhs.getExpr());
271
+ }
272
+
273
+ friend BoundedZ3Expr shl(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
274
+ {
275
+ if (lhs.is_zero())
276
+ return lhs;
277
+ else if (lhs.is_infinite())
278
+ return lhs;
279
+ else if (rhs.is_infinite())
280
+ return ite(lhs.getExpr() >= 0, plus_infinity(), minus_infinity());
281
+ else
282
+ return shl(lhs.getExpr(), rhs.getExpr());
283
+ }
284
+
285
+ friend BoundedZ3Expr lshr(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
286
+ {
287
+ return lshr(lhs.getExpr(), rhs.getExpr());
288
+ }
289
+
290
+ friend BoundedZ3Expr int2bv(u32_t n, const BoundedZ3Expr &e)
291
+ {
292
+ return int2bv(n, e.getExpr());
293
+ }
294
+
295
+ friend BoundedZ3Expr bv2int(const BoundedZ3Expr &e, bool isSigned)
296
+ {
297
+ return bv2int(e.getExpr(), isSigned);
298
+ }
299
+
300
+ friend BoundedZ3Expr operator&&(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
301
+ {
302
+ return lhs.getExpr() && rhs.getExpr();
303
+ }
304
+
305
+ friend BoundedZ3Expr operator||(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
306
+ {
307
+ return lhs.getExpr() || rhs.getExpr();
308
+ }
309
+
310
+ friend BoundedZ3Expr operator!(const BoundedZ3Expr &lhs)
311
+ {
312
+ return !lhs.getExpr();
313
+ }
314
+
315
+ friend BoundedZ3Expr ite(const BoundedZ3Expr &cond, const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
316
+ {
317
+ return ite(cond.getExpr(), lhs.getExpr(), rhs.getExpr());
318
+ }
319
+
320
+ friend std::ostream &operator<<(std::ostream &out, const BoundedZ3Expr &expr)
321
+ {
322
+ out << expr.getExpr();
323
+ return out;
324
+ }
325
+
326
+ friend bool eq(const BoundedZ3Expr &lhs, const BoundedZ3Expr &rhs)
327
+ {
328
+ return eq(lhs.getExpr(), rhs.getExpr());
329
+ }
330
+
331
+ inline BoundedZ3Expr simplify() const
332
+ {
333
+ return getExpr().simplify();
334
+ }
335
+
336
+ inline bool is_true() const
337
+ {
338
+ return getExpr().is_true();
339
+ }
340
+ //%}
341
+ }; // end class ConZ3Expr
342
+ } // end namespace SVF
343
+
344
+ /// Specialise hash for ConZ3Expr
345
+ template<>
346
+ struct std::hash<SVF::BoundedZ3Expr>
347
+ {
348
+ size_t operator()(const SVF::BoundedZ3Expr &z3Expr) const
349
+ {
350
+ return z3Expr.hash();
351
+ }
352
+ };
353
+ #endif //SVF_BOUNDEDZ3EXPR_H
@@ -82,7 +82,7 @@ public:
82
82
  /// Create the IntervalValue [-oo, +oo]
83
83
  static IntervalValue top()
84
84
  {
85
- return IntervalValue(INT_MIN, INT_MAX);
85
+ return IntervalValue(minus_infinity(), plus_infinity());
86
86
  }
87
87
 
88
88
  /// Create the bottom IntervalValue
@@ -92,37 +92,41 @@ public:
92
92
  }
93
93
 
94
94
  /// Create default IntervalValue
95
- explicit IntervalValue() : AbstractValue(AbstractValue::IntervalK), _lb(INT_MIN), _ub(INT_MAX) {}
95
+ explicit IntervalValue() : AbstractValue(AbstractValue::IntervalK), _lb(minus_infinity()), _ub(plus_infinity()) {}
96
96
 
97
97
  /// Create the IntervalValue [n, n]
98
- explicit IntervalValue(double n) : AbstractValue(AbstractValue::IntervalK), _lb(n), _ub(n) {}
98
+ explicit IntervalValue(int64_t n) : AbstractValue(AbstractValue::IntervalK), _lb(n), _ub(n) {}
99
99
 
100
- explicit IntervalValue(s32_t n) : IntervalValue((double) n) {}
100
+ explicit IntervalValue(s32_t n) : IntervalValue((int64_t) n) {}
101
101
 
102
- explicit IntervalValue(u32_t n) : IntervalValue((double) n) {}
102
+ explicit IntervalValue(u32_t n) : IntervalValue((int64_t) n) {}
103
+
104
+ explicit IntervalValue(double n) : IntervalValue((int64_t) n) {}
105
+
106
+ explicit IntervalValue(NumericLiteral n) : IntervalValue(n, n) {}
103
107
 
104
108
  /// Create the IntervalValue [lb, ub]
105
109
  explicit IntervalValue(NumericLiteral lb, NumericLiteral ub) : AbstractValue(AbstractValue::IntervalK),
106
110
  _lb(std::move(lb)), _ub(std::move(ub)) {}
107
111
 
108
- explicit IntervalValue(double lb, double ub) : IntervalValue(NumericLiteral(lb), NumericLiteral(ub)) {}
112
+ explicit IntervalValue(int64_t lb, int64_t ub) : IntervalValue(NumericLiteral(lb), NumericLiteral(ub)) {}
109
113
 
110
- explicit IntervalValue(s32_t lb, s32_t ub) : IntervalValue((double) lb, (double) ub) {}
114
+ explicit IntervalValue(double lb, double ub) : IntervalValue(NumericLiteral((int64_t) lb), NumericLiteral((int64_t) ub)) {}
111
115
 
112
- explicit IntervalValue(u32_t lb, u32_t ub) : IntervalValue((double) lb, (double) ub) {}
116
+ explicit IntervalValue(s32_t lb, s32_t ub) : IntervalValue((int64_t) lb, (int64_t) ub) {}
113
117
 
114
- explicit IntervalValue(s64_t lb, s64_t ub) : IntervalValue((double) lb, (double) ub) {}
118
+ explicit IntervalValue(u32_t lb, u32_t ub) : IntervalValue((int64_t) lb, (int64_t) ub) {}
115
119
 
116
- explicit IntervalValue(u64_t lb, u64_t ub) : IntervalValue((double) lb, (double) ub) {}
120
+ explicit IntervalValue(u64_t lb, u64_t ub) : IntervalValue((int64_t) lb, (int64_t) ub) {}
117
121
 
118
122
  /// Copy constructor
119
123
  IntervalValue(const IntervalValue &) = default;
120
124
 
121
125
  /// Move constructor
122
- IntervalValue(IntervalValue &&) noexcept = default;
126
+ IntervalValue(IntervalValue &&) = default;
123
127
 
124
128
  /// Copy assignment operator
125
- IntervalValue &operator=(const IntervalValue &a) noexcept = default;
129
+ IntervalValue &operator=(const IntervalValue &a) = default;
126
130
 
127
131
  /// Move assignment operator
128
132
  IntervalValue &operator=(IntervalValue &&) = default;
@@ -256,7 +260,7 @@ public:
256
260
  }
257
261
 
258
262
  /// Return
259
- double getNumeral() const
263
+ int64_t getNumeral() const
260
264
  {
261
265
  assert(is_numeral() && "this IntervalValue is not numeral");
262
266
  return _lb.getNumeral();
@@ -419,7 +423,7 @@ public:
419
423
  /// Return true if the IntervalValue contains n
420
424
  bool contains(int n) const
421
425
  {
422
- return this->_lb.getNumeral() <= n && this->_ub.getNumeral() >= n;
426
+ return this->_lb.leq(n) && this->_ub.geq(n);
423
427
  }
424
428
 
425
429
  void dump(std::ostream &o) const
@@ -436,7 +440,7 @@ public:
436
440
 
437
441
  std::string toString() const
438
442
  {
439
- return "[" + std::to_string(lb().getNumeral()) + ", " + std::to_string(ub().getNumeral()) + "]";
443
+ return "[" + lb().to_string() + ", " + ub().to_string() + "]";
440
444
  }
441
445
 
442
446
  }; // end class IntervalValue
@@ -491,8 +495,9 @@ inline IntervalValue operator*(const IntervalValue &lhs,
491
495
  NumericLiteral lu = lhs.lb() * rhs.ub();
492
496
  NumericLiteral ul = lhs.ub() * rhs.lb();
493
497
  NumericLiteral uu = lhs.ub() * rhs.ub();
494
- return IntervalValue(std::min({ll.getNumeral(), lu.getNumeral(), ul.getNumeral(), uu.getNumeral()}),
495
- std::max({ll.getNumeral(), lu.getNumeral(), ul.getNumeral(), uu.getNumeral()}));
498
+ std::vector<NumericLiteral> vec{ll, lu, ul, uu};
499
+ return IntervalValue(NumericLiteral::min(vec),
500
+ NumericLiteral::max(vec));
496
501
  }
497
502
  }
498
503
 
@@ -515,8 +520,10 @@ inline IntervalValue operator/(const IntervalValue &lhs,
515
520
  NumericLiteral lu = lhs.lb() / rhs.ub();
516
521
  NumericLiteral ul = lhs.ub() / rhs.lb();
517
522
  NumericLiteral uu = lhs.ub() / rhs.ub();
518
- return IntervalValue(std::min({ll.getNumeral(), lu.getNumeral(), ul.getNumeral(), uu.getNumeral()}),
519
- std::max({ll.getNumeral(), lu.getNumeral(), ul.getNumeral(), uu.getNumeral()}));
523
+ std::vector<NumericLiteral> vec{ll, lu, ul, uu};
524
+
525
+ return IntervalValue(NumericLiteral::min(vec),
526
+ NumericLiteral::max(vec));
520
527
  }
521
528
  }
522
529
 
@@ -538,9 +545,9 @@ inline IntervalValue operator%(const IntervalValue &lhs,
538
545
  }
539
546
  else
540
547
  {
541
- double n_ub = std::max(std::abs(lhs.lb().getNumeral()), std::abs(lhs.ub().getNumeral()));
542
- double d_ub = std::max(std::abs(rhs.lb().getNumeral()), std::abs(rhs.ub().getNumeral())) - 1;
543
- double ub = std::min(n_ub, d_ub);
548
+ NumericLiteral n_ub = max(abs(lhs.lb()), abs(lhs.ub()));
549
+ NumericLiteral d_ub = max(abs(rhs.lb()), rhs.ub() - 1);
550
+ NumericLiteral ub = min(n_ub, d_ub);
544
551
 
545
552
  if (lhs.lb().getNumeral() < 0)
546
553
  {
@@ -550,12 +557,12 @@ inline IntervalValue operator%(const IntervalValue &lhs,
550
557
  }
551
558
  else
552
559
  {
553
- return IntervalValue(-ub, double(0));
560
+ return IntervalValue(-ub, 0);
554
561
  }
555
562
  }
556
563
  else
557
564
  {
558
- return IntervalValue(double(0), ub);
565
+ return IntervalValue(0, ub);
559
566
  }
560
567
  }
561
568
  }
@@ -580,12 +587,12 @@ inline IntervalValue operator>(const IntervalValue &lhs, const IntervalValue &rh
580
587
  else
581
588
  {
582
589
  // lhs[3,4] rhs[1,2]
583
- if (lhs.lb().getNumeral() > rhs.ub().getNumeral())
590
+ if (!lhs.lb().leq(rhs.ub()))
584
591
  {
585
592
  return IntervalValue(1, 1);
586
593
  // lhs[1,2] rhs[3,4]
587
594
  }
588
- else if (lhs.ub().getNumeral() < rhs.lb().getNumeral())
595
+ else if (lhs.ub().geq(rhs.lb()))
589
596
  {
590
597
  return IntervalValue(0, 0);
591
598
  }
@@ -618,12 +625,12 @@ inline IntervalValue operator<(const IntervalValue &lhs, const IntervalValue &rh
618
625
  else
619
626
  {
620
627
  // lhs [1,2] rhs [3,4]
621
- if (lhs.ub().getNumeral() < rhs.lb().getNumeral())
628
+ if (!lhs.ub().geq(rhs.lb()))
622
629
  {
623
630
  return IntervalValue(1, 1);
624
631
  // lhs [3,4] rhs [1,2]
625
632
  }
626
- else if (lhs.lb().getNumeral() > rhs.ub().getNumeral())
633
+ else if (!lhs.lb().leq(rhs.ub()))
627
634
  {
628
635
  return IntervalValue(0, 0);
629
636
  // lhs [1,3] rhs [2,4]
@@ -657,12 +664,12 @@ inline IntervalValue operator>=(const IntervalValue &lhs, const IntervalValue &r
657
664
  else
658
665
  {
659
666
  // lhs [2,3] rhs [1,2]
660
- if (lhs.lb().getNumeral() >= rhs.ub().getNumeral())
667
+ if (lhs.lb().geq(rhs.ub()))
661
668
  {
662
669
  return IntervalValue(1, 1);
663
670
  // lhs [1,2] rhs[3,4]
664
671
  }
665
- else if (lhs.ub().getNumeral() < rhs.lb().getNumeral())
672
+ else if (!lhs.ub().geq(rhs.lb()))
666
673
  {
667
674
  return IntervalValue(0, 0);
668
675
  // lhs [1,3] rhs [2,4]
@@ -696,12 +703,12 @@ inline IntervalValue operator<=(const IntervalValue &lhs, const IntervalValue &r
696
703
  else
697
704
  {
698
705
  // lhs [1,2] rhs [2,3]
699
- if (lhs.ub().getNumeral() <= rhs.lb().getNumeral())
706
+ if (lhs.ub().leq(rhs.lb()))
700
707
  {
701
708
  return IntervalValue(1, 1);
702
709
  // lhs [3,4] rhs[1,2]
703
710
  }
704
- else if (lhs.lb().getNumeral() > rhs.ub().getNumeral())
711
+ else if (!lhs.lb().leq(rhs.ub()))
705
712
  {
706
713
  return IntervalValue(0, 0);
707
714
  // lhs [1,3] rhs [2,4]
@@ -765,8 +772,9 @@ inline IntervalValue operator>>(const IntervalValue &lhs, const IntervalValue &r
765
772
  NumericLiteral lu = lhs.lb() >> shift.ub();
766
773
  NumericLiteral ul = lhs.ub() >> shift.lb();
767
774
  NumericLiteral uu = lhs.ub() >> shift.ub();
768
- return IntervalValue(std::min({ll.getNumeral(), lu.getNumeral(), ul.getNumeral(), uu.getNumeral()}),
769
- std::max({ll.getNumeral(), lu.getNumeral(), ul.getNumeral(), uu.getNumeral()}));
775
+ std::vector<NumericLiteral> vec{ll, lu, ul, uu};
776
+ return IntervalValue(NumericLiteral::min(vec),
777
+ NumericLiteral::max(vec));
770
778
  }
771
779
  }
772
780
  }
@@ -778,19 +786,19 @@ inline IntervalValue operator&(const IntervalValue &lhs, const IntervalValue &rh
778
786
  return IntervalValue::bottom();
779
787
  else if (lhs.is_numeral() && rhs.is_numeral())
780
788
  {
781
- return IntervalValue((s32_t)lhs.getNumeral() & (s32_t)rhs.getNumeral());
789
+ return IntervalValue(lhs.lb() & rhs.lb());
782
790
  }
783
791
  else if (lhs.lb().getNumeral() >= 0 && rhs.lb().getNumeral() >= 0)
784
792
  {
785
- return IntervalValue(0.0, std::min(lhs.ub().getNumeral(), rhs.ub().getNumeral()));
793
+ return IntervalValue((int64_t) 0, min(lhs.ub(), rhs.ub()));
786
794
  }
787
795
  else if (lhs.lb().getNumeral() >= 0)
788
796
  {
789
- return IntervalValue(0.0, lhs.ub().getNumeral());
797
+ return IntervalValue((int64_t) 0, lhs.ub());
790
798
  }
791
799
  else if (rhs.lb().getNumeral() >= 0)
792
800
  {
793
- return IntervalValue(0.0, rhs.ub().getNumeral());
801
+ return IntervalValue((int64_t) 0, rhs.ub());
794
802
  }
795
803
  else
796
804
  {
@@ -813,13 +821,13 @@ inline IntervalValue operator|(const IntervalValue &lhs, const IntervalValue &rh
813
821
  if (lhs.isBottom() || rhs.isBottom())
814
822
  return IntervalValue::bottom();
815
823
  else if (lhs.is_numeral() && rhs.is_numeral())
816
- return IntervalValue((s32_t)lhs.getNumeral() | (s32_t)rhs.getNumeral());
824
+ return IntervalValue(lhs.lb() | rhs.lb());
817
825
  else if (lhs.lb().getNumeral() >= 0 && !lhs.ub().is_infinity() &&
818
826
  rhs.lb().getNumeral() >= 0 && !rhs.ub().is_infinity())
819
827
  {
820
- double m = std::max(lhs.ub().getNumeral(), rhs.ub().getNumeral());
821
- double ub = next_power_of_2(s64_t(m+1));
822
- return IntervalValue(0.0, ub);
828
+ int64_t m = std::max(lhs.ub().getNumeral(), rhs.ub().getNumeral());
829
+ int64_t ub = next_power_of_2(s64_t(m+1));
830
+ return IntervalValue((int64_t) 0, (int64_t) ub);
823
831
  }
824
832
  else
825
833
  {
@@ -842,13 +850,13 @@ inline IntervalValue operator^(const IntervalValue &lhs, const IntervalValue &rh
842
850
  if (lhs.isBottom() || rhs.isBottom())
843
851
  return IntervalValue::bottom();
844
852
  else if (lhs.is_numeral() && rhs.is_numeral())
845
- return IntervalValue((s32_t)lhs.getNumeral() ^ (s32_t)rhs.getNumeral());
853
+ return IntervalValue(lhs.lb() ^ rhs.lb());
846
854
  else if (lhs.lb().getNumeral() >= 0 && !lhs.ub().is_infinity() &&
847
855
  rhs.lb().getNumeral() >= 0 && !rhs.ub().is_infinity())
848
856
  {
849
- double m = std::max(lhs.ub().getNumeral(), rhs.ub().getNumeral());
850
- double ub = next_power_of_2(s64_t(m+1));
851
- return IntervalValue(0.0, ub);
857
+ int64_t m = std::max(lhs.ub().getNumeral(), rhs.ub().getNumeral());
858
+ int64_t ub = next_power_of_2(s64_t(m+1));
859
+ return IntervalValue((int64_t) 0, (int64_t) ub);
852
860
  }
853
861
  else
854
862
  {