svf-tools 1.0.966 → 1.0.968
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/index.html +10 -2
- package/package.json +1 -1
- package/svf/include/AE/Core/IntervalValue.h +97 -54
- package/svf/include/AE/Core/NumericValue.h +748 -115
- package/svf/include/MemoryModel/AccessPath.h +1 -0
- package/svf/include/SVFIR/SVFStatements.h +1 -0
- package/svf/lib/AE/Core/RelationSolver.cpp +17 -11
- package/svf/lib/AE/Svfexe/AbstractInterpretation.cpp +1 -10
- package/svf/lib/AE/Svfexe/BufOverflowChecker.cpp +1 -9
- package/svf/lib/AE/Svfexe/SVFIR2AbsState.cpp +75 -87
- package/svf/lib/MemoryModel/AccessPath.cpp +27 -26
- package/svf-llvm/tools/AE/ae.cpp +218 -1
- package/svf-llvm/tools/Example/svf-ex.cpp +0 -1
|
@@ -34,22 +34,695 @@
|
|
|
34
34
|
#define SVF_NUMERICVALUE_H
|
|
35
35
|
|
|
36
36
|
#include "SVFIR/SVFType.h"
|
|
37
|
-
#include <cmath>
|
|
38
37
|
#include <cfloat> // For DBL_MAX
|
|
38
|
+
#include <cmath>
|
|
39
39
|
#include <utility>
|
|
40
40
|
|
|
41
|
-
|
|
42
41
|
#define epsilon std::numeric_limits<double>::epsilon();
|
|
43
42
|
namespace SVF
|
|
44
43
|
{
|
|
45
44
|
|
|
45
|
+
/**
|
|
46
|
+
* @brief A class representing a bounded 64-bit integer.
|
|
47
|
+
*
|
|
48
|
+
* BoundedInt is a class that represents a 64-bit integer that can also
|
|
49
|
+
* represent positive and negative infinity. It includes a 64-bit integer
|
|
50
|
+
* value and a boolean flag indicating whether the value is infinite.
|
|
51
|
+
* If the value is infinite, the integer value is used to represent the sign
|
|
52
|
+
* of infinity (1 for positive infinity and 0 for negative infinity).
|
|
53
|
+
*/
|
|
54
|
+
class BoundedInt
|
|
55
|
+
{
|
|
56
|
+
protected:
|
|
57
|
+
s64_t _iVal; // The 64-bit integer value.
|
|
58
|
+
bool _isInf; // True if the value is infinite. If true, _iVal == 1
|
|
59
|
+
// represents positive infinity and _iVal == 0 represents
|
|
60
|
+
// negative infinity.
|
|
61
|
+
|
|
62
|
+
// Default constructor is protected to prevent creating an object without
|
|
63
|
+
// initializing _iVal and _isInf.
|
|
64
|
+
BoundedInt() = default;
|
|
65
|
+
|
|
66
|
+
public:
|
|
67
|
+
// Constructs a BoundedInt with the given 64-bit integer value. The value is
|
|
68
|
+
// not infinite.
|
|
69
|
+
BoundedInt(s64_t fVal) : _iVal(fVal), _isInf(false) {}
|
|
70
|
+
|
|
71
|
+
// Constructs a BoundedInt with the given 64-bit integer value and infinity
|
|
72
|
+
// flag.
|
|
73
|
+
BoundedInt(s64_t fVal, bool isInf) : _iVal(fVal), _isInf(isInf) {}
|
|
74
|
+
|
|
75
|
+
// Copy constructor.
|
|
76
|
+
BoundedInt(const BoundedInt& rhs) : _iVal(rhs._iVal), _isInf(rhs._isInf) {}
|
|
77
|
+
|
|
78
|
+
// Copy assignment operator.
|
|
79
|
+
BoundedInt& operator=(const BoundedInt& rhs)
|
|
80
|
+
{
|
|
81
|
+
_iVal = rhs._iVal;
|
|
82
|
+
_isInf = rhs._isInf;
|
|
83
|
+
return *this;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Move constructor.
|
|
87
|
+
BoundedInt(BoundedInt&& rhs) : _iVal(rhs._iVal), _isInf(rhs._isInf) {}
|
|
88
|
+
|
|
89
|
+
// Move assignment operator.
|
|
90
|
+
BoundedInt& operator=(BoundedInt&& rhs)
|
|
91
|
+
{
|
|
92
|
+
_iVal = rhs._iVal;
|
|
93
|
+
_isInf = rhs._isInf;
|
|
94
|
+
return *this;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Virtual destructor.
|
|
98
|
+
virtual ~BoundedInt() {}
|
|
99
|
+
|
|
100
|
+
// Checks if the BoundedInt represents positive infinity.
|
|
101
|
+
bool is_plus_infinity() const
|
|
102
|
+
{
|
|
103
|
+
return _isInf && _iVal == 1;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Checks if the BoundedInt represents negative infinity.
|
|
107
|
+
bool is_minus_infinity() const
|
|
108
|
+
{
|
|
109
|
+
return _isInf && _iVal == -1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Checks if the BoundedInt represents either positive or negative infinity.
|
|
113
|
+
bool is_infinity() const
|
|
114
|
+
{
|
|
115
|
+
return is_plus_infinity() || is_minus_infinity();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Sets the BoundedInt to represent positive infinity.
|
|
119
|
+
void set_plus_infinity()
|
|
120
|
+
{
|
|
121
|
+
*this = plus_infinity();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Sets the BoundedInt to represent negative infinity.
|
|
125
|
+
void set_minus_infinity()
|
|
126
|
+
{
|
|
127
|
+
*this = minus_infinity();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Returns a BoundedInt representing positive infinity.
|
|
131
|
+
static BoundedInt plus_infinity()
|
|
132
|
+
{
|
|
133
|
+
return {1, true};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Returns a BoundedInt representing negative infinity.
|
|
137
|
+
static BoundedInt minus_infinity()
|
|
138
|
+
{
|
|
139
|
+
return {-1, true};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Checks if the BoundedInt represents zero.
|
|
143
|
+
bool is_zero() const
|
|
144
|
+
{
|
|
145
|
+
return _iVal == 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Checks if the given BoundedInt represents zero.
|
|
149
|
+
static bool isZero(const BoundedInt& expr)
|
|
150
|
+
{
|
|
151
|
+
return expr._iVal == 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Checks if the BoundedInt is equal to another BoundedInt.
|
|
155
|
+
bool equal(const BoundedInt& rhs) const
|
|
156
|
+
{
|
|
157
|
+
return _iVal == rhs._iVal && _isInf == rhs._isInf;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Checks if the BoundedInt is less than or equal to another BoundedInt.
|
|
161
|
+
bool leq(const BoundedInt& rhs) const
|
|
162
|
+
{
|
|
163
|
+
// If only one of the two BoundedInts is infinite.
|
|
164
|
+
if (is_infinity() ^ rhs.is_infinity())
|
|
165
|
+
{
|
|
166
|
+
if (is_infinity())
|
|
167
|
+
{
|
|
168
|
+
return is_minus_infinity();
|
|
169
|
+
}
|
|
170
|
+
else
|
|
171
|
+
{
|
|
172
|
+
return rhs.is_plus_infinity();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// If both BoundedInts are infinite.
|
|
176
|
+
if (is_infinity() && rhs.is_infinity())
|
|
177
|
+
{
|
|
178
|
+
if (is_minus_infinity())
|
|
179
|
+
return true;
|
|
180
|
+
else
|
|
181
|
+
return rhs.is_plus_infinity();
|
|
182
|
+
}
|
|
183
|
+
// If neither BoundedInt is infinite.
|
|
184
|
+
else
|
|
185
|
+
return _iVal <= rhs._iVal;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Checks if the BoundedInt is greater than or equal to another BoundedInt.
|
|
189
|
+
bool geq(const BoundedInt& rhs) const
|
|
190
|
+
{
|
|
191
|
+
// If only one of the two BoundedInts is infinite.
|
|
192
|
+
if (is_infinity() ^ rhs.is_infinity())
|
|
193
|
+
{
|
|
194
|
+
if (is_infinity())
|
|
195
|
+
{
|
|
196
|
+
return is_plus_infinity();
|
|
197
|
+
}
|
|
198
|
+
else
|
|
199
|
+
{
|
|
200
|
+
return rhs.is_minus_infinity();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// If both BoundedInts are infinite.
|
|
204
|
+
if (is_infinity() && rhs.is_infinity())
|
|
205
|
+
{
|
|
206
|
+
if (is_plus_infinity())
|
|
207
|
+
return true;
|
|
208
|
+
else
|
|
209
|
+
return rhs.is_minus_infinity();
|
|
210
|
+
}
|
|
211
|
+
// If neither BoundedInt is infinite.
|
|
212
|
+
else
|
|
213
|
+
return _iVal >= rhs._iVal;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/// Reload operator
|
|
217
|
+
//{%
|
|
218
|
+
// Overloads the equality operator to compare two BoundedInt objects.
|
|
219
|
+
friend BoundedInt operator==(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
220
|
+
{
|
|
221
|
+
return lhs.equal(rhs);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Overloads the inequality operator to compare two BoundedInt objects.
|
|
225
|
+
friend BoundedInt operator!=(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
226
|
+
{
|
|
227
|
+
return !lhs.equal(rhs);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Overloads the greater than operator to compare two BoundedInt objects.
|
|
231
|
+
friend BoundedInt operator>(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
232
|
+
{
|
|
233
|
+
return !lhs.leq(rhs);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Overloads the less than operator to compare two BoundedInt objects.
|
|
237
|
+
friend BoundedInt operator<(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
238
|
+
{
|
|
239
|
+
return !lhs.geq(rhs);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Overloads the less than or equal to operator to compare two BoundedInt
|
|
243
|
+
// objects.
|
|
244
|
+
friend BoundedInt operator<=(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
245
|
+
{
|
|
246
|
+
return lhs.leq(rhs);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Overloads the greater than or equal to operator to compare two BoundedInt
|
|
250
|
+
// objects.
|
|
251
|
+
friend BoundedInt operator>=(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
252
|
+
{
|
|
253
|
+
return lhs.geq(rhs);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Safely adds two BoundedInt objects.
|
|
258
|
+
*
|
|
259
|
+
* This function adds two BoundedInt objects in a way that respects the
|
|
260
|
+
* bounds of the underlying s64_t type. It checks for conditions that would
|
|
261
|
+
* result in overflow or underflow and returns a representation of positive
|
|
262
|
+
* or negative infinity in those cases. If addition of the two numbers would
|
|
263
|
+
* result in a value that is within the representable range of s64_t, it
|
|
264
|
+
* performs the addition and returns the result. If the addition is not
|
|
265
|
+
* defined (e.g., positive infinity plus negative infinity), it asserts
|
|
266
|
+
* false to indicate an error.
|
|
267
|
+
*
|
|
268
|
+
* @param lhs The first BoundedInt to add. This can be any valid BoundedInt,
|
|
269
|
+
* including positive and negative infinity.
|
|
270
|
+
* @param rhs The second BoundedInt to add. This can be any valid
|
|
271
|
+
* BoundedInt, including positive and negative infinity.
|
|
272
|
+
* @return A BoundedInt that represents the result of the addition. If the
|
|
273
|
+
* addition would result in overflow, the function returns a BoundedInt
|
|
274
|
+
* representing positive infinity. If the addition would result in
|
|
275
|
+
* underflow, the function returns a BoundedInt representing negative
|
|
276
|
+
* infinity. If the addition is not defined (e.g., positive infinity plus
|
|
277
|
+
* negative infinity), the function asserts false and does not return a
|
|
278
|
+
* value.
|
|
279
|
+
*/
|
|
280
|
+
static BoundedInt safeAdd(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
281
|
+
{
|
|
282
|
+
// If one number is positive infinity and the other is negative
|
|
283
|
+
// infinity, this is an invalid operation, so we assert false.
|
|
284
|
+
if ((lhs.is_plus_infinity() && rhs.is_minus_infinity()) ||
|
|
285
|
+
(lhs.is_minus_infinity() && rhs.is_plus_infinity()))
|
|
286
|
+
{
|
|
287
|
+
assert(false && "invalid add");
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// If either number is positive infinity, the result is positive
|
|
291
|
+
// infinity.
|
|
292
|
+
if (lhs.is_plus_infinity() || rhs.is_plus_infinity())
|
|
293
|
+
{
|
|
294
|
+
return plus_infinity();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// If either number is negative infinity, the result is negative
|
|
298
|
+
// infinity.
|
|
299
|
+
if (lhs.is_minus_infinity() || rhs.is_minus_infinity())
|
|
300
|
+
{
|
|
301
|
+
return minus_infinity();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// If both numbers are positive and their sum would exceed the maximum
|
|
305
|
+
// representable number, the result is positive infinity.
|
|
306
|
+
if (lhs._iVal > 0 && rhs._iVal > 0 &&
|
|
307
|
+
(std::numeric_limits<s64_t>::max() - lhs._iVal) < rhs._iVal)
|
|
308
|
+
{
|
|
309
|
+
return plus_infinity();
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// If both numbers are negative and their sum would be less than the
|
|
313
|
+
// most negative representable number, the result is negative infinity.
|
|
314
|
+
if (lhs._iVal < 0 && rhs._iVal < 0 &&
|
|
315
|
+
(-std::numeric_limits<s64_t>::max() - lhs._iVal) > rhs._iVal)
|
|
316
|
+
{
|
|
317
|
+
return minus_infinity();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// If none of the above conditions are met, the numbers can be safely
|
|
321
|
+
// added.
|
|
322
|
+
return lhs._iVal + rhs._iVal;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Overloads the addition operator to safely add two BoundedInt objects.
|
|
326
|
+
// Utilizes the safeAdd method to handle potential overflow and underflow.
|
|
327
|
+
friend BoundedInt operator+(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
328
|
+
{
|
|
329
|
+
return safeAdd(lhs, rhs);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Overloads the unary minus operator to negate a BoundedInt object.
|
|
333
|
+
// The operation simply negates the internal integer value.
|
|
334
|
+
friend BoundedInt operator-(const BoundedInt& lhs)
|
|
335
|
+
{
|
|
336
|
+
return {-lhs._iVal, lhs._isInf};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Overloads the subtraction operator to safely subtract one BoundedInt
|
|
340
|
+
// object from another. This is implemented as the addition of the lhs and
|
|
341
|
+
// the negation of the rhs, using the safeAdd method for safety.
|
|
342
|
+
friend BoundedInt operator-(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
343
|
+
{
|
|
344
|
+
return safeAdd(lhs, -rhs);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* @brief Performs safe multiplication of two BoundedInt objects.
|
|
349
|
+
*
|
|
350
|
+
* This function ensures that the multiplication of two BoundedInt objects
|
|
351
|
+
* doesn't result in overflow or underflow. It returns the multiplication
|
|
352
|
+
* result if it can be represented within the range of a 64-bit integer. If
|
|
353
|
+
* the result would be larger than the maximum representable positive
|
|
354
|
+
* number, it returns positive infinity. If the result would be less than
|
|
355
|
+
* the minimum representable negative number, it returns negative infinity.
|
|
356
|
+
* If either of the inputs is zero, the result is zero. If either of the
|
|
357
|
+
* inputs is infinity, the result is determined by the signs of the inputs.
|
|
358
|
+
*
|
|
359
|
+
* @param lhs The first BoundedInt to multiply.
|
|
360
|
+
* @param rhs The second BoundedInt to multiply.
|
|
361
|
+
* @return The result of the multiplication, or positive/negative infinity
|
|
362
|
+
* if the result would be outside the range of a 64-bit integer.
|
|
363
|
+
*/
|
|
364
|
+
static BoundedInt safeMul(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
365
|
+
{
|
|
366
|
+
// If either number is zero, the result is zero.
|
|
367
|
+
if (lhs._iVal == 0 || rhs._iVal == 0)
|
|
368
|
+
return 0;
|
|
369
|
+
|
|
370
|
+
// If either number is infinity, the result depends on the signs of the
|
|
371
|
+
// numbers.
|
|
372
|
+
if (lhs.is_infinity() || rhs.is_infinity())
|
|
373
|
+
{
|
|
374
|
+
// If the signs of the numbers are the same, the result is positive
|
|
375
|
+
// infinity. If the signs of the numbers are different, the result
|
|
376
|
+
// is negative infinity.
|
|
377
|
+
if (lhs._iVal * rhs._iVal > 0)
|
|
378
|
+
{
|
|
379
|
+
return plus_infinity();
|
|
380
|
+
}
|
|
381
|
+
else
|
|
382
|
+
{
|
|
383
|
+
return minus_infinity();
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// If both numbers are positive and their product would exceed the
|
|
388
|
+
// maximum representable number, the result is positive infinity.
|
|
389
|
+
if (lhs._iVal > 0 && rhs._iVal > 0 &&
|
|
390
|
+
(std::numeric_limits<s64_t>::max() / lhs._iVal) < rhs._iVal)
|
|
391
|
+
{
|
|
392
|
+
return plus_infinity();
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// If both numbers are negative and their product would exceed the
|
|
396
|
+
// maximum representable number, the result is positive infinity.
|
|
397
|
+
if (lhs._iVal < 0 && rhs._iVal < 0 &&
|
|
398
|
+
(std::numeric_limits<s64_t>::max() / lhs._iVal) > rhs._iVal)
|
|
399
|
+
{
|
|
400
|
+
return plus_infinity();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// If one number is positive and the other is negative and their product
|
|
404
|
+
// would be less than the most negative representable number, the result
|
|
405
|
+
// is negative infinity.
|
|
406
|
+
if ((lhs._iVal > 0 && rhs._iVal < 0 &&
|
|
407
|
+
(-std::numeric_limits<s64_t>::max() / lhs._iVal) > rhs._iVal) ||
|
|
408
|
+
(lhs._iVal < 0 && rhs._iVal > 0 &&
|
|
409
|
+
(-std::numeric_limits<s64_t>::max() / rhs._iVal) > lhs._iVal))
|
|
410
|
+
{
|
|
411
|
+
return minus_infinity();
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// If none of the above conditions are met, the numbers can be safely
|
|
415
|
+
// multiplied.
|
|
416
|
+
return lhs._iVal * rhs._iVal;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
friend BoundedInt operator%(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
421
|
+
{
|
|
422
|
+
if (rhs.is_zero())
|
|
423
|
+
assert(false && "divide by zero");
|
|
424
|
+
else if (!lhs.is_infinity() && !rhs.is_infinity())
|
|
425
|
+
return lhs._iVal % rhs._iVal;
|
|
426
|
+
else if (!lhs.is_infinity() && rhs.is_infinity())
|
|
427
|
+
return 0;
|
|
428
|
+
// TODO: not sure
|
|
429
|
+
else if (lhs.is_infinity() && !rhs.is_infinity())
|
|
430
|
+
return ite(rhs._iVal > 0, lhs, -lhs);
|
|
431
|
+
else
|
|
432
|
+
// TODO: +oo/-oo L'Hôpital's rule?
|
|
433
|
+
return eq(lhs, rhs) ? plus_infinity() : minus_infinity();
|
|
434
|
+
abort();
|
|
435
|
+
}
|
|
436
|
+
// Overloads the multiplication operator to safely multiply two BoundedInt
|
|
437
|
+
// objects. Utilizes the safeMul method to handle potential overflow.
|
|
438
|
+
friend BoundedInt operator*(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
439
|
+
{
|
|
440
|
+
return safeMul(lhs, rhs);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Overloads the division operator to safely divide a BoundedInt object by
|
|
444
|
+
// another. Utilizes the safeDiv method to handle potential division by zero
|
|
445
|
+
// and overflow.
|
|
446
|
+
friend BoundedInt operator/(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
447
|
+
{
|
|
448
|
+
if (rhs.is_zero())
|
|
449
|
+
assert(false && "divide by zero");
|
|
450
|
+
else if (!lhs.is_infinity() && !rhs.is_infinity())
|
|
451
|
+
return lhs._iVal / rhs._iVal;
|
|
452
|
+
else if (!lhs.is_infinity() && rhs.is_infinity())
|
|
453
|
+
return 0;
|
|
454
|
+
else if (lhs.is_infinity() && !rhs.is_infinity())
|
|
455
|
+
return ite(rhs._iVal >= 0, lhs, -lhs);
|
|
456
|
+
else
|
|
457
|
+
return eq(lhs, rhs) ? plus_infinity() : minus_infinity();
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Overload bitwise operators for BoundedInt objects. These operators
|
|
461
|
+
// directly apply the corresponding bitwise operators to the internal
|
|
462
|
+
// integer values of the BoundedInt objects.
|
|
463
|
+
|
|
464
|
+
// Overloads the bitwise XOR operator for BoundedInt objects.
|
|
465
|
+
friend BoundedInt operator^(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
466
|
+
{
|
|
467
|
+
return lhs._iVal ^ rhs._iVal;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Overloads the bitwise AND operator for BoundedInt objects.
|
|
471
|
+
friend BoundedInt operator&(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
472
|
+
{
|
|
473
|
+
return lhs._iVal & rhs._iVal;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Overloads the bitwise OR operator for BoundedInt objects.
|
|
477
|
+
friend BoundedInt operator|(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
478
|
+
{
|
|
479
|
+
return lhs._iVal | rhs._iVal;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Overload logical operators for BoundedInt objects. These operators
|
|
483
|
+
// directly apply the corresponding logical operators to the internal
|
|
484
|
+
// integer values of the BoundedInt objects.
|
|
485
|
+
|
|
486
|
+
// Overloads the logical AND operator for BoundedInt objects.
|
|
487
|
+
friend BoundedInt operator&&(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
488
|
+
{
|
|
489
|
+
return lhs._iVal && rhs._iVal;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// Overloads the logical OR operator for BoundedInt objects.
|
|
493
|
+
friend BoundedInt operator||(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
494
|
+
{
|
|
495
|
+
return lhs._iVal || rhs._iVal;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Overloads the logical NOT operator for BoundedInt objects.
|
|
499
|
+
friend BoundedInt operator!(const BoundedInt& lhs)
|
|
500
|
+
{
|
|
501
|
+
return !lhs._iVal;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Overloads the right shift operator for BoundedInt objects.
|
|
505
|
+
// This operation is safe as long as the right-hand side is non-negative.
|
|
506
|
+
// If the left-hand side is zero or infinity, the result is the same as the
|
|
507
|
+
// left-hand side. If the right-hand side is infinity, the result depends on
|
|
508
|
+
// the sign of the left-hand side.
|
|
509
|
+
friend BoundedInt operator>>(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
510
|
+
{
|
|
511
|
+
assert(rhs.geq(0) && "rhs should be greater or equal than 0");
|
|
512
|
+
if (lhs.is_zero())
|
|
513
|
+
return lhs;
|
|
514
|
+
else if (lhs.is_infinity())
|
|
515
|
+
return lhs;
|
|
516
|
+
else if (rhs.is_infinity())
|
|
517
|
+
return lhs.geq(0) ? 0 : -1;
|
|
518
|
+
else
|
|
519
|
+
return lhs._iVal >> rhs._iVal;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Overloads the left shift operator for BoundedInt objects.
|
|
523
|
+
// This operation is safe as long as the right-hand side is non-negative.
|
|
524
|
+
// If the left-hand side is zero or infinity, the result is the same as the
|
|
525
|
+
// left-hand side. If the right-hand side is infinity, the result depends on
|
|
526
|
+
// the sign of the left-hand side.
|
|
527
|
+
friend BoundedInt operator<<(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
528
|
+
{
|
|
529
|
+
assert(rhs.geq(0) && "rhs should be greater or equal than 0");
|
|
530
|
+
if (lhs.is_zero())
|
|
531
|
+
return lhs;
|
|
532
|
+
else if (lhs.is_infinity())
|
|
533
|
+
return lhs;
|
|
534
|
+
else if (rhs.is_infinity())
|
|
535
|
+
return lhs.geq(0) ? plus_infinity() : minus_infinity();
|
|
536
|
+
else
|
|
537
|
+
return lhs._iVal << rhs._iVal;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Overloads the ternary if-then-else operator for BoundedInt objects.
|
|
541
|
+
// The condition is evaluated as a boolean, and the result is either the
|
|
542
|
+
// second or third argument depending on the condition.
|
|
543
|
+
friend BoundedInt ite(const BoundedInt& cond, const BoundedInt& lhs,
|
|
544
|
+
const BoundedInt& rhs)
|
|
545
|
+
{
|
|
546
|
+
return cond._iVal != 0 ? lhs : rhs;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// Overloads the stream insertion operator for BoundedInt objects.
|
|
550
|
+
// This allows BoundedInt objects to be printed directly using std::cout or
|
|
551
|
+
// other output streams.
|
|
552
|
+
friend std::ostream& operator<<(std::ostream& out, const BoundedInt& expr)
|
|
553
|
+
{
|
|
554
|
+
out << expr._iVal;
|
|
555
|
+
return out;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Defines a function to compare two BoundedInt objects for equality.
|
|
559
|
+
// This function directly compares the internal integer values of the
|
|
560
|
+
// BoundedInt objects.
|
|
561
|
+
friend bool eq(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
562
|
+
{
|
|
563
|
+
return lhs._iVal == rhs._iVal && lhs._isInf == rhs._isInf;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// Defines a function to find the minimum of two BoundedInt objects.
|
|
567
|
+
// This function directly compares the internal integer values of the BoundedInt objects,
|
|
568
|
+
// and also checks if either of them represents infinity.
|
|
569
|
+
friend BoundedInt min(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
570
|
+
{
|
|
571
|
+
if (lhs.is_minus_infinity() || rhs.is_minus_infinity())
|
|
572
|
+
return minus_infinity();
|
|
573
|
+
else if(lhs.is_plus_infinity())
|
|
574
|
+
return rhs;
|
|
575
|
+
else if(rhs.is_plus_infinity())
|
|
576
|
+
return lhs;
|
|
577
|
+
else
|
|
578
|
+
return BoundedInt(std::min(lhs._iVal, rhs._iVal));
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
// Defines a function to find the maximum of two BoundedInt objects.
|
|
583
|
+
// This function directly compares the internal integer values of the BoundedInt objects,
|
|
584
|
+
// and also checks if either of them represents infinity.
|
|
585
|
+
friend BoundedInt max(const BoundedInt& lhs, const BoundedInt& rhs)
|
|
586
|
+
{
|
|
587
|
+
if (lhs.is_plus_infinity() || rhs.is_plus_infinity())
|
|
588
|
+
return plus_infinity();
|
|
589
|
+
else if(lhs.is_minus_infinity())
|
|
590
|
+
return rhs;
|
|
591
|
+
else if(rhs.is_minus_infinity())
|
|
592
|
+
return lhs;
|
|
593
|
+
else
|
|
594
|
+
return BoundedInt(std::max(lhs._iVal, rhs._iVal));
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
// Defines a function to find the minimum of a vector of BoundedInt objects.
|
|
599
|
+
// This function iterates over the vector and returns the smallest
|
|
600
|
+
// BoundedInt object.
|
|
601
|
+
static BoundedInt min(std::vector<BoundedInt>& _l)
|
|
602
|
+
{
|
|
603
|
+
BoundedInt ret(plus_infinity());
|
|
604
|
+
for (const auto& it : _l)
|
|
605
|
+
{
|
|
606
|
+
if (it.is_minus_infinity())
|
|
607
|
+
return minus_infinity();
|
|
608
|
+
else if (!it.geq(ret))
|
|
609
|
+
{
|
|
610
|
+
ret = it;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return ret;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Defines a function to find the maximum of a vector of BoundedInt objects.
|
|
617
|
+
// This function iterates over the vector and returns the largest BoundedInt
|
|
618
|
+
// object.
|
|
619
|
+
static BoundedInt max(std::vector<BoundedInt>& _l)
|
|
620
|
+
{
|
|
621
|
+
BoundedInt ret(minus_infinity());
|
|
622
|
+
for (const auto& it : _l)
|
|
623
|
+
{
|
|
624
|
+
if (it.is_plus_infinity())
|
|
625
|
+
return plus_infinity();
|
|
626
|
+
else if (!it.leq(ret))
|
|
627
|
+
{
|
|
628
|
+
ret = it;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
return ret;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Defines a function to find the absolute value of a BoundedInt object.
|
|
635
|
+
// This function directly applies the unary minus operator if the BoundedInt
|
|
636
|
+
// object is negative.
|
|
637
|
+
friend BoundedInt abs(const BoundedInt& lhs)
|
|
638
|
+
{
|
|
639
|
+
return lhs.leq(0) ? -lhs : lhs;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Defines a method to check if a BoundedInt object is true.
|
|
643
|
+
// A BoundedInt object is considered true if its internal integer value is
|
|
644
|
+
// non-zero.
|
|
645
|
+
inline bool is_true() const
|
|
646
|
+
{
|
|
647
|
+
return _iVal != 0;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* @brief Retrieves the numeral value of the BoundedInt object.
|
|
652
|
+
*
|
|
653
|
+
* This method returns the numeral representation of the BoundedInt object.
|
|
654
|
+
* If the object represents negative infinity, it returns the minimum
|
|
655
|
+
* representable 64-bit integer. If the object represents positive infinity,
|
|
656
|
+
* it returns the maximum representable 64-bit integer. Otherwise, it
|
|
657
|
+
* returns the actual 64-bit integer value of the object.
|
|
658
|
+
*
|
|
659
|
+
* @return The numeral value of the BoundedInt object.
|
|
660
|
+
*/
|
|
661
|
+
inline s64_t getNumeral() const
|
|
662
|
+
{
|
|
663
|
+
// If the object represents negative infinity, return the minimum
|
|
664
|
+
// representable 64-bit integer.
|
|
665
|
+
if (is_minus_infinity())
|
|
666
|
+
{
|
|
667
|
+
return std::numeric_limits<s64_t>::min();
|
|
668
|
+
}
|
|
669
|
+
// If the object represents positive infinity, return the maximum
|
|
670
|
+
// representable 64-bit integer.
|
|
671
|
+
else if (is_plus_infinity())
|
|
672
|
+
{
|
|
673
|
+
return std::numeric_limits<s64_t>::max();
|
|
674
|
+
}
|
|
675
|
+
// Otherwise, return the actual 64-bit integer value of the object.
|
|
676
|
+
else
|
|
677
|
+
{
|
|
678
|
+
return _iVal;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
inline virtual const std::string to_string() const
|
|
683
|
+
{
|
|
684
|
+
if (is_minus_infinity())
|
|
685
|
+
{
|
|
686
|
+
return "-oo";
|
|
687
|
+
}
|
|
688
|
+
if (is_plus_infinity())
|
|
689
|
+
{
|
|
690
|
+
return "+oo";
|
|
691
|
+
}
|
|
692
|
+
else
|
|
693
|
+
return std::to_string(_iVal);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
//%}
|
|
697
|
+
|
|
698
|
+
bool is_real() const
|
|
699
|
+
{
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
inline s64_t getIntNumeral() const
|
|
704
|
+
{
|
|
705
|
+
return getNumeral();
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
inline double getRealNumeral() const
|
|
709
|
+
{
|
|
710
|
+
assert(false && "cannot get real number for integer!");
|
|
711
|
+
abort();
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const double getFVal() const
|
|
715
|
+
{
|
|
716
|
+
assert(false && "cannot get real number for integer!");
|
|
717
|
+
abort();
|
|
718
|
+
}
|
|
719
|
+
};
|
|
46
720
|
/*!
|
|
47
721
|
* Bounded double numeric value
|
|
48
722
|
*/
|
|
49
723
|
class BoundedDouble
|
|
50
724
|
{
|
|
51
725
|
protected:
|
|
52
|
-
|
|
53
726
|
double _fVal;
|
|
54
727
|
|
|
55
728
|
BoundedDouble() = default;
|
|
@@ -65,7 +738,7 @@ public:
|
|
|
65
738
|
return *this;
|
|
66
739
|
}
|
|
67
740
|
|
|
68
|
-
BoundedDouble(BoundedDouble
|
|
741
|
+
BoundedDouble(BoundedDouble&& rhs) : _fVal(std::move(rhs._fVal)) {}
|
|
69
742
|
|
|
70
743
|
BoundedDouble& operator=(BoundedDouble&& rhs)
|
|
71
744
|
{
|
|
@@ -75,7 +748,6 @@ public:
|
|
|
75
748
|
|
|
76
749
|
virtual ~BoundedDouble() {}
|
|
77
750
|
|
|
78
|
-
|
|
79
751
|
static bool doubleEqual(double a, double b)
|
|
80
752
|
{
|
|
81
753
|
if (std::isinf(a) && std::isinf(b))
|
|
@@ -123,23 +795,22 @@ public:
|
|
|
123
795
|
return -std::numeric_limits<double>::infinity();
|
|
124
796
|
}
|
|
125
797
|
|
|
126
|
-
|
|
127
798
|
bool is_zero() const
|
|
128
799
|
{
|
|
129
800
|
return doubleEqual(_fVal, 0.0f);
|
|
130
801
|
}
|
|
131
802
|
|
|
132
|
-
static bool isZero(const BoundedDouble
|
|
803
|
+
static bool isZero(const BoundedDouble& expr)
|
|
133
804
|
{
|
|
134
805
|
return doubleEqual(expr.getFVal(), 0.0f);
|
|
135
806
|
}
|
|
136
807
|
|
|
137
|
-
bool equal(const BoundedDouble
|
|
808
|
+
bool equal(const BoundedDouble& rhs) const
|
|
138
809
|
{
|
|
139
810
|
return doubleEqual(_fVal, rhs._fVal);
|
|
140
811
|
}
|
|
141
812
|
|
|
142
|
-
bool leq(const BoundedDouble
|
|
813
|
+
bool leq(const BoundedDouble& rhs) const
|
|
143
814
|
{
|
|
144
815
|
if (is_infinity() ^ rhs.is_infinity())
|
|
145
816
|
{
|
|
@@ -152,16 +823,18 @@ public:
|
|
|
152
823
|
return rhs.is_plus_infinity();
|
|
153
824
|
}
|
|
154
825
|
}
|
|
155
|
-
if(is_infinity() && rhs.is_infinity())
|
|
826
|
+
if (is_infinity() && rhs.is_infinity())
|
|
156
827
|
{
|
|
157
|
-
if(is_minus_infinity())
|
|
158
|
-
|
|
828
|
+
if (is_minus_infinity())
|
|
829
|
+
return true;
|
|
830
|
+
else
|
|
831
|
+
return rhs.is_plus_infinity();
|
|
159
832
|
}
|
|
160
833
|
else
|
|
161
834
|
return _fVal <= rhs._fVal;
|
|
162
835
|
}
|
|
163
836
|
|
|
164
|
-
bool geq(const BoundedDouble
|
|
837
|
+
bool geq(const BoundedDouble& rhs) const
|
|
165
838
|
{
|
|
166
839
|
if (is_infinity() ^ rhs.is_infinity())
|
|
167
840
|
{
|
|
@@ -174,10 +847,12 @@ public:
|
|
|
174
847
|
return rhs.is_minus_infinity();
|
|
175
848
|
}
|
|
176
849
|
}
|
|
177
|
-
if(is_infinity() && rhs.is_infinity())
|
|
850
|
+
if (is_infinity() && rhs.is_infinity())
|
|
178
851
|
{
|
|
179
|
-
if(is_plus_infinity())
|
|
180
|
-
|
|
852
|
+
if (is_plus_infinity())
|
|
853
|
+
return true;
|
|
854
|
+
else
|
|
855
|
+
return rhs.is_minus_infinity();
|
|
181
856
|
}
|
|
182
857
|
else
|
|
183
858
|
return _fVal >= rhs._fVal;
|
|
@@ -185,32 +860,38 @@ public:
|
|
|
185
860
|
|
|
186
861
|
/// Reload operator
|
|
187
862
|
//{%
|
|
188
|
-
friend BoundedDouble operator==(const BoundedDouble
|
|
863
|
+
friend BoundedDouble operator==(const BoundedDouble& lhs,
|
|
864
|
+
const BoundedDouble& rhs)
|
|
189
865
|
{
|
|
190
866
|
return lhs.equal(rhs);
|
|
191
867
|
}
|
|
192
868
|
|
|
193
|
-
friend BoundedDouble operator!=(const BoundedDouble
|
|
869
|
+
friend BoundedDouble operator!=(const BoundedDouble& lhs,
|
|
870
|
+
const BoundedDouble& rhs)
|
|
194
871
|
{
|
|
195
872
|
return !lhs.equal(rhs);
|
|
196
873
|
}
|
|
197
874
|
|
|
198
|
-
friend BoundedDouble operator>(const BoundedDouble
|
|
875
|
+
friend BoundedDouble operator>(const BoundedDouble& lhs,
|
|
876
|
+
const BoundedDouble& rhs)
|
|
199
877
|
{
|
|
200
878
|
return !lhs.leq(rhs);
|
|
201
879
|
}
|
|
202
880
|
|
|
203
|
-
friend BoundedDouble operator<(const BoundedDouble
|
|
881
|
+
friend BoundedDouble operator<(const BoundedDouble& lhs,
|
|
882
|
+
const BoundedDouble& rhs)
|
|
204
883
|
{
|
|
205
884
|
return !lhs.geq(rhs);
|
|
206
885
|
}
|
|
207
886
|
|
|
208
|
-
friend BoundedDouble operator<=(const BoundedDouble
|
|
887
|
+
friend BoundedDouble operator<=(const BoundedDouble& lhs,
|
|
888
|
+
const BoundedDouble& rhs)
|
|
209
889
|
{
|
|
210
890
|
return lhs.leq(rhs);
|
|
211
891
|
}
|
|
212
892
|
|
|
213
|
-
friend BoundedDouble operator>=(const BoundedDouble
|
|
893
|
+
friend BoundedDouble operator>=(const BoundedDouble& lhs,
|
|
894
|
+
const BoundedDouble& rhs)
|
|
214
895
|
{
|
|
215
896
|
return lhs.geq(rhs);
|
|
216
897
|
}
|
|
@@ -256,8 +937,7 @@ public:
|
|
|
256
937
|
if (lhs > 0 && rhs > 0 &&
|
|
257
938
|
(std::numeric_limits<double>::max() - lhs) < rhs)
|
|
258
939
|
{
|
|
259
|
-
res =
|
|
260
|
-
std::numeric_limits<double>::infinity(); // Set result to
|
|
940
|
+
res = std::numeric_limits<double>::infinity(); // Set result to
|
|
261
941
|
// positive infinity to
|
|
262
942
|
// indicate overflow
|
|
263
943
|
return res;
|
|
@@ -279,17 +959,19 @@ public:
|
|
|
279
959
|
return res;
|
|
280
960
|
}
|
|
281
961
|
|
|
282
|
-
friend BoundedDouble operator+(const BoundedDouble
|
|
962
|
+
friend BoundedDouble operator+(const BoundedDouble& lhs,
|
|
963
|
+
const BoundedDouble& rhs)
|
|
283
964
|
{
|
|
284
965
|
return safeAdd(lhs._fVal, rhs._fVal);
|
|
285
966
|
}
|
|
286
967
|
|
|
287
|
-
friend BoundedDouble operator-(const BoundedDouble
|
|
968
|
+
friend BoundedDouble operator-(const BoundedDouble& lhs)
|
|
288
969
|
{
|
|
289
970
|
return -lhs._fVal;
|
|
290
971
|
}
|
|
291
972
|
|
|
292
|
-
friend BoundedDouble operator-(const BoundedDouble
|
|
973
|
+
friend BoundedDouble operator-(const BoundedDouble& lhs,
|
|
974
|
+
const BoundedDouble& rhs)
|
|
293
975
|
{
|
|
294
976
|
return safeAdd(lhs._fVal, -rhs._fVal);
|
|
295
977
|
}
|
|
@@ -323,11 +1005,13 @@ public:
|
|
|
323
1005
|
// negative infinity
|
|
324
1006
|
}
|
|
325
1007
|
// Check for overflow scenarios
|
|
326
|
-
if (lhs > 0 && rhs > 0 &&
|
|
1008
|
+
if (lhs > 0 && rhs > 0 &&
|
|
1009
|
+
lhs > std::numeric_limits<double>::max() / rhs)
|
|
327
1010
|
{
|
|
328
1011
|
return std::numeric_limits<double>::infinity();
|
|
329
1012
|
}
|
|
330
|
-
if (lhs < 0 && rhs < 0 &&
|
|
1013
|
+
if (lhs < 0 && rhs < 0 &&
|
|
1014
|
+
lhs < std::numeric_limits<double>::max() / rhs)
|
|
331
1015
|
{
|
|
332
1016
|
return std::numeric_limits<double>::infinity();
|
|
333
1017
|
}
|
|
@@ -347,7 +1031,8 @@ public:
|
|
|
347
1031
|
return res; // If no overflow or underflow, return the product
|
|
348
1032
|
}
|
|
349
1033
|
|
|
350
|
-
friend BoundedDouble operator*(const BoundedDouble
|
|
1034
|
+
friend BoundedDouble operator*(const BoundedDouble& lhs,
|
|
1035
|
+
const BoundedDouble& rhs)
|
|
351
1036
|
{
|
|
352
1037
|
return safeMul(lhs._fVal, rhs._fVal);
|
|
353
1038
|
}
|
|
@@ -400,14 +1085,17 @@ public:
|
|
|
400
1085
|
return res; // If no special cases, return the quotient
|
|
401
1086
|
}
|
|
402
1087
|
|
|
403
|
-
friend BoundedDouble operator/(const BoundedDouble
|
|
1088
|
+
friend BoundedDouble operator/(const BoundedDouble& lhs,
|
|
1089
|
+
const BoundedDouble& rhs)
|
|
404
1090
|
{
|
|
405
1091
|
return safeDiv(lhs._fVal, rhs._fVal);
|
|
406
1092
|
}
|
|
407
1093
|
|
|
408
|
-
friend BoundedDouble operator%(const BoundedDouble
|
|
1094
|
+
friend BoundedDouble operator%(const BoundedDouble& lhs,
|
|
1095
|
+
const BoundedDouble& rhs)
|
|
409
1096
|
{
|
|
410
|
-
if (rhs.is_zero())
|
|
1097
|
+
if (rhs.is_zero())
|
|
1098
|
+
assert(false && "divide by zero");
|
|
411
1099
|
else if (!lhs.is_infinity() && !rhs.is_infinity())
|
|
412
1100
|
return std::fmod(lhs._fVal, rhs._fVal);
|
|
413
1101
|
else if (!lhs.is_infinity() && rhs.is_infinity())
|
|
@@ -430,41 +1118,46 @@ public:
|
|
|
430
1118
|
return !is_int();
|
|
431
1119
|
}
|
|
432
1120
|
|
|
433
|
-
friend BoundedDouble operator^(const BoundedDouble
|
|
1121
|
+
friend BoundedDouble operator^(const BoundedDouble& lhs,
|
|
1122
|
+
const BoundedDouble& rhs)
|
|
434
1123
|
{
|
|
435
1124
|
int lInt = std::round(lhs._fVal), rInt = std::round(rhs._fVal);
|
|
436
1125
|
return lInt ^ rInt;
|
|
437
1126
|
}
|
|
438
1127
|
|
|
439
|
-
friend BoundedDouble operator&(const BoundedDouble
|
|
1128
|
+
friend BoundedDouble operator&(const BoundedDouble& lhs,
|
|
1129
|
+
const BoundedDouble& rhs)
|
|
440
1130
|
{
|
|
441
1131
|
int lInt = std::round(lhs._fVal), rInt = std::round(rhs._fVal);
|
|
442
1132
|
return lInt & rInt;
|
|
443
1133
|
}
|
|
444
1134
|
|
|
445
|
-
friend BoundedDouble operator|(const BoundedDouble
|
|
1135
|
+
friend BoundedDouble operator|(const BoundedDouble& lhs,
|
|
1136
|
+
const BoundedDouble& rhs)
|
|
446
1137
|
{
|
|
447
1138
|
int lInt = std::round(lhs._fVal), rInt = std::round(rhs._fVal);
|
|
448
1139
|
return lInt | rInt;
|
|
449
1140
|
}
|
|
450
1141
|
|
|
451
|
-
|
|
452
|
-
|
|
1142
|
+
friend BoundedDouble operator&&(const BoundedDouble& lhs,
|
|
1143
|
+
const BoundedDouble& rhs)
|
|
453
1144
|
{
|
|
454
1145
|
return lhs._fVal && rhs._fVal;
|
|
455
1146
|
}
|
|
456
1147
|
|
|
457
|
-
friend BoundedDouble operator||(const BoundedDouble
|
|
1148
|
+
friend BoundedDouble operator||(const BoundedDouble& lhs,
|
|
1149
|
+
const BoundedDouble& rhs)
|
|
458
1150
|
{
|
|
459
1151
|
return lhs._fVal || rhs._fVal;
|
|
460
1152
|
}
|
|
461
1153
|
|
|
462
|
-
friend BoundedDouble operator!(const BoundedDouble
|
|
1154
|
+
friend BoundedDouble operator!(const BoundedDouble& lhs)
|
|
463
1155
|
{
|
|
464
1156
|
return !lhs._fVal;
|
|
465
1157
|
}
|
|
466
1158
|
|
|
467
|
-
friend BoundedDouble operator>>(const BoundedDouble
|
|
1159
|
+
friend BoundedDouble operator>>(const BoundedDouble& lhs,
|
|
1160
|
+
const BoundedDouble& rhs)
|
|
468
1161
|
{
|
|
469
1162
|
assert(rhs.geq(0) && "rhs should be greater or equal than 0");
|
|
470
1163
|
if (lhs.is_zero())
|
|
@@ -474,10 +1167,11 @@ public:
|
|
|
474
1167
|
else if (rhs.is_infinity())
|
|
475
1168
|
return lhs.geq(0) ? 0 : -1;
|
|
476
1169
|
else
|
|
477
|
-
return (s32_t)
|
|
1170
|
+
return (s32_t)lhs.getNumeral() >> (s32_t)rhs.getNumeral();
|
|
478
1171
|
}
|
|
479
1172
|
|
|
480
|
-
friend BoundedDouble operator<<(const BoundedDouble
|
|
1173
|
+
friend BoundedDouble operator<<(const BoundedDouble& lhs,
|
|
1174
|
+
const BoundedDouble& rhs)
|
|
481
1175
|
{
|
|
482
1176
|
assert(rhs.geq(0) && "rhs should be greater or equal than 0");
|
|
483
1177
|
if (lhs.is_zero())
|
|
@@ -487,32 +1181,33 @@ public:
|
|
|
487
1181
|
else if (rhs.is_infinity())
|
|
488
1182
|
return lhs.geq(0) ? plus_infinity() : minus_infinity();
|
|
489
1183
|
else
|
|
490
|
-
return (s32_t)
|
|
1184
|
+
return (s32_t)lhs.getNumeral() << (s32_t)rhs.getNumeral();
|
|
491
1185
|
}
|
|
492
1186
|
|
|
493
|
-
friend BoundedDouble ite(const BoundedDouble& cond,
|
|
494
|
-
const BoundedDouble& rhs)
|
|
1187
|
+
friend BoundedDouble ite(const BoundedDouble& cond,
|
|
1188
|
+
const BoundedDouble& lhs, const BoundedDouble& rhs)
|
|
495
1189
|
{
|
|
496
1190
|
return cond._fVal != 0.0f ? lhs._fVal : rhs._fVal;
|
|
497
1191
|
}
|
|
498
1192
|
|
|
499
|
-
friend std::ostream
|
|
1193
|
+
friend std::ostream& operator<<(std::ostream& out,
|
|
1194
|
+
const BoundedDouble& expr)
|
|
500
1195
|
{
|
|
501
1196
|
out << expr._fVal;
|
|
502
1197
|
return out;
|
|
503
1198
|
}
|
|
504
1199
|
|
|
505
|
-
friend bool eq(const BoundedDouble
|
|
1200
|
+
friend bool eq(const BoundedDouble& lhs, const BoundedDouble& rhs)
|
|
506
1201
|
{
|
|
507
1202
|
return doubleEqual(lhs._fVal, rhs._fVal);
|
|
508
1203
|
}
|
|
509
1204
|
|
|
510
|
-
friend BoundedDouble min(const BoundedDouble
|
|
1205
|
+
friend BoundedDouble min(const BoundedDouble& lhs, const BoundedDouble& rhs)
|
|
511
1206
|
{
|
|
512
1207
|
return std::min(lhs._fVal, rhs._fVal);
|
|
513
1208
|
}
|
|
514
1209
|
|
|
515
|
-
friend BoundedDouble max(const BoundedDouble
|
|
1210
|
+
friend BoundedDouble max(const BoundedDouble& lhs, const BoundedDouble& rhs)
|
|
516
1211
|
{
|
|
517
1212
|
return std::max(lhs._fVal, rhs._fVal);
|
|
518
1213
|
}
|
|
@@ -520,7 +1215,7 @@ public:
|
|
|
520
1215
|
static BoundedDouble min(std::vector<BoundedDouble>& _l)
|
|
521
1216
|
{
|
|
522
1217
|
BoundedDouble ret(plus_infinity());
|
|
523
|
-
for (const auto
|
|
1218
|
+
for (const auto& it : _l)
|
|
524
1219
|
{
|
|
525
1220
|
if (it.is_minus_infinity())
|
|
526
1221
|
return minus_infinity();
|
|
@@ -535,7 +1230,7 @@ public:
|
|
|
535
1230
|
static BoundedDouble max(std::vector<BoundedDouble>& _l)
|
|
536
1231
|
{
|
|
537
1232
|
BoundedDouble ret(minus_infinity());
|
|
538
|
-
for (const auto
|
|
1233
|
+
for (const auto& it : _l)
|
|
539
1234
|
{
|
|
540
1235
|
if (it.is_plus_infinity())
|
|
541
1236
|
return plus_infinity();
|
|
@@ -547,7 +1242,7 @@ public:
|
|
|
547
1242
|
return ret;
|
|
548
1243
|
}
|
|
549
1244
|
|
|
550
|
-
friend BoundedDouble abs(const BoundedDouble
|
|
1245
|
+
friend BoundedDouble abs(const BoundedDouble& lhs)
|
|
551
1246
|
{
|
|
552
1247
|
return lhs.leq(0) ? -lhs : lhs;
|
|
553
1248
|
}
|
|
@@ -592,68 +1287,6 @@ public:
|
|
|
592
1287
|
//%}
|
|
593
1288
|
}; // end class BoundedDouble
|
|
594
1289
|
|
|
595
|
-
class BoundedInt : public BoundedDouble
|
|
596
|
-
{
|
|
597
|
-
private:
|
|
598
|
-
BoundedInt() = default;
|
|
599
|
-
|
|
600
|
-
public:
|
|
601
|
-
|
|
602
|
-
BoundedInt(s32_t val)
|
|
603
|
-
{
|
|
604
|
-
_fVal = val;
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
BoundedInt(s64_t val)
|
|
608
|
-
{
|
|
609
|
-
_fVal = val;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
BoundedInt(const BoundedInt& rhs)
|
|
613
|
-
{
|
|
614
|
-
_fVal = rhs._fVal;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
BoundedInt& operator=(const BoundedInt& rhs)
|
|
618
|
-
{
|
|
619
|
-
_fVal = rhs._fVal;
|
|
620
|
-
return *this;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
BoundedInt(BoundedInt&& rhs)
|
|
624
|
-
{
|
|
625
|
-
_fVal = rhs._fVal;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
BoundedInt& operator=(const BoundedInt&& rhs)
|
|
629
|
-
{
|
|
630
|
-
_fVal = rhs._fVal;
|
|
631
|
-
return *this;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
BoundedInt(double val)
|
|
635
|
-
{
|
|
636
|
-
_fVal = val;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
BoundedInt(const BoundedDouble& f)
|
|
640
|
-
{
|
|
641
|
-
_fVal = f.getFVal();
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
virtual ~BoundedInt() {}
|
|
645
|
-
|
|
646
|
-
inline const std::string to_string() const override
|
|
647
|
-
{
|
|
648
|
-
if (is_minus_infinity())
|
|
649
|
-
return "-∞";
|
|
650
|
-
else if (is_plus_infinity())
|
|
651
|
-
return "∞";
|
|
652
|
-
else
|
|
653
|
-
return std::to_string(getIntNumeral());
|
|
654
|
-
}
|
|
655
|
-
};
|
|
656
|
-
|
|
657
1290
|
} // end namespace SVF
|
|
658
1291
|
|
|
659
1292
|
#endif // SVF_NUMERICVALUE_H
|