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.
@@ -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 &&rhs) : _fVal(std::move(rhs._fVal)) {}
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 &expr)
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 &rhs) const
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 &rhs) const
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()) return true;
158
- else return rhs.is_plus_infinity();
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 &rhs) const
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()) return true;
180
- else return rhs.is_minus_infinity();
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs)
968
+ friend BoundedDouble operator-(const BoundedDouble& lhs)
288
969
  {
289
970
  return -lhs._fVal;
290
971
  }
291
972
 
292
- friend BoundedDouble operator-(const BoundedDouble &lhs, const BoundedDouble &rhs)
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 && lhs > std::numeric_limits<double>::max() / rhs)
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 && lhs < std::numeric_limits<double>::max() / rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
1094
+ friend BoundedDouble operator%(const BoundedDouble& lhs,
1095
+ const BoundedDouble& rhs)
409
1096
  {
410
- if (rhs.is_zero()) assert(false && "divide by 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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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
- friend BoundedDouble operator&&(const BoundedDouble &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs)
1154
+ friend BoundedDouble operator!(const BoundedDouble& lhs)
463
1155
  {
464
1156
  return !lhs._fVal;
465
1157
  }
466
1158
 
467
- friend BoundedDouble operator>>(const BoundedDouble &lhs, const BoundedDouble &rhs)
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) lhs.getNumeral() >> (s32_t) rhs.getNumeral();
1170
+ return (s32_t)lhs.getNumeral() >> (s32_t)rhs.getNumeral();
478
1171
  }
479
1172
 
480
- friend BoundedDouble operator<<(const BoundedDouble &lhs, const BoundedDouble &rhs)
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) lhs.getNumeral() << (s32_t) rhs.getNumeral();
1184
+ return (s32_t)lhs.getNumeral() << (s32_t)rhs.getNumeral();
491
1185
  }
492
1186
 
493
- friend BoundedDouble ite(const BoundedDouble& cond, const BoundedDouble& lhs,
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 &operator<<(std::ostream &out, const BoundedDouble &expr)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &lhs, const BoundedDouble &rhs)
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 &it: _l)
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 &it: _l)
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 &lhs)
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