ESBMC
Efficient SMT-based Context-Bounded Model Checker
Loading...
Searching...
No Matches
wrapped_interval.h
Go to the documentation of this file.
1#pragma once
2
3#include "interval_template.h"
4
5class wrapped_interval : public interval_templatet<BigInt>
6{
7public:
11
12 explicit wrapped_interval(const type2tc &t)
13 : t(t), upper_bound(compute_upper_bound(t))
14 {
15 assert(is_representable(t));
16
17 lower = 0;
18 upper = is_bool_type(t) ? 1 : compute_upper_bound(t) - 1;
19 }
20
21 static bool is_representable(const type2tc &t)
22 {
23 return is_signedbv_type(t) || is_unsignedbv_type(t) || is_bool_type(t) ||
24 is_pointer_type(t);
25 }
26
28 {
29 auto value = b;
30 // TODO: I could use a better way here!
31 if (b.is_negative() && !b.is_zero())
33
34 assert(value >= 0);
35 assert(value <= get_upper_bound());
36 return value;
37 }
38
39 void set(bool is_upper, const BigInt &b) override
40 {
41 auto value = convert_to_wrap(b);
42
43 if (is_upper)
44 upper = value;
45 else
46 lower = value;
47 }
48
49 BigInt get(bool is_upper) const override
50 {
51 auto is_signed = is_signedbv_type(t);
52 auto value = is_upper ? upper : lower;
53
54 if (is_signed)
55 {
56 auto middle = get_upper_bound() / 2; // [128] 256
57 if (*value >= middle)
58 *value -= middle * 2;
59 }
60
61 return *value;
62 }
63
64 bool bottom = false;
65 bool empty() const override
66 {
67 return bottom;
68 }
69
70 bool is_top() const override
71 {
72 return !is_bottom() && cardinality() == get_upper_bound();
73 }
74
76 {
77 wrapped_interval result(w.t);
78
79 if (w.is_top())
80 result.bottom = true;
81
82 if (!w.is_bottom())
83 {
84 auto mod = w.get_upper_bound();
85 result.lower = (*w.upper + 1) % mod;
86 result.upper = (*w.lower - 1) % mod;
87 if (result.upper < 0)
88 *result.upper += mod;
89 }
90 return result;
91 }
92
94 static bool wrapped_le(
95 const BigInt &b,
96 const BigInt &a,
97 const BigInt &c,
98 const type2tc &t)
99 {
100 auto mod = compute_upper_bound(t);
101 // https://torstencurdt.com/tech/posts/modulo-of-negative-numbers/
102 auto lhs = (b - a) % mod;
103 if (lhs < 0)
104 lhs = lhs + mod;
105 auto rhs = (c - a) % mod;
106 if (rhs < 0)
107 rhs = rhs + mod;
108
109 return lhs <= rhs;
110 }
111
112 void make_le_than(const BigInt &v) override // add upper bound
113 {
114 if (get_upper_bound() <= v)
115 return;
117 value.lower = get_min();
118
119 value.set_upper(v);
120
121 *this = over_meet(*this, value);
122 }
123
125 {
126 if (rhs.is_bottom())
127 {
128 bottom = true;
129 return;
130 }
131
132 // RHS contains upper bound (MAX_INT) we are always less than that
133 if (rhs.contains(get_max()))
134 return;
135
137 value.lower = get_min();
138 value.upper = rhs.upper;
139
140 *this = over_meet(*this, value);
141 }
142
143 void make_ge_than(const BigInt &v) override // add lower bound
144 {
146 value.set_lower(v);
147 value.upper = get_max();
148 *this = over_meet(*this, value);
149 }
150
151 void make_ge_than(const wrapped_interval &rhs) // add lower bound
152 {
153 if (rhs.is_bottom())
154 {
155 bottom = true;
156 return;
157 }
158
159 // RHS contains lower bound (MIN_INT) we are always greater than that
160 if (rhs.contains(get_min()))
161 return;
162
164 value.lower = rhs.lower;
165 value.upper = get_max();
166
167 *this = over_meet(*this, value);
168 }
169
171 {
172 // 0^w or 10^(w-1)
173 return is_signedbv_type(t) ? get_upper_bound() / 2 : 0;
174 }
175
177 {
178 // 1^w or 01^(w-1)
179 return is_signedbv_type(t) ? get_upper_bound() / 2 - 1
180 : get_upper_bound() - 1;
181 }
182
184 {
185 if (is_bottom())
186 return 0;
187
188 auto mod = get_upper_bound();
189 assert(mod != 0);
190 auto card = (*upper - *lower) % mod;
191 if (card < 0)
192 card += mod;
193 return card + 1;
194 }
195
196 bool contains(const BigInt &e) const override
197 {
198 if (is_top())
199 return true;
200
201 return wrapped_le(e, *lower, *upper, t);
202 }
203
204 bool is_equal(const wrapped_interval &rhs) const
205 {
206 return t == rhs.t && lower == rhs.lower && upper == rhs.upper;
207 }
208
209 bool is_included(const wrapped_interval &rhs) const
210 {
211 if (is_bottom() || rhs.is_top() || is_equal(rhs))
212 return true;
213 if (is_top() || rhs.is_bottom())
214 return false;
215
216 return rhs.contains(*lower) && rhs.contains(*upper) &&
217 (!contains(*rhs.lower) || !contains(*rhs.upper));
218 }
219
220 static wrapped_interval
222 {
223 if (s.is_included(t))
224 return t;
225 if (t.is_included(s))
226 return s;
227
228 wrapped_interval result(s.t);
229 if (complement(s).is_included(t))
230 {
231 return result;
232 }
233
234 // t overlaps the start of s, so the union runs from t's start to s's end;
235 // [s.lower, t.upper] would drop the part of s past t.upper (#8209).
236 if (t.contains(*s.lower) && s.contains(*t.upper))
237 {
238 result.lower = t.lower;
239 result.upper = s.upper;
240 return result;
241 }
242
243 result.lower = s.lower;
244 result.upper = t.upper;
245 return result;
246 }
247
248 static wrapped_interval
250 {
251 wrapped_interval result(s.t);
252 if (
253 !t.is_bottom() && !s.is_bottom() && !t.contains(*s.upper) &&
254 !s.contains(*t.lower))
255 {
256 result.lower = t.lower;
257 result.upper = s.upper;
258 return complement(result);
259 }
260 result.bottom = true;
261 return result;
262 }
263
264 static wrapped_interval
266 {
267 return t.cardinality() > s.cardinality() ? t : s;
268 }
269
271 static wrapped_interval over_join(std::vector<wrapped_interval> &r)
272 {
274 bottom.bottom = true;
275
276 if (r.empty())
277 return bottom;
278 bottom.t = r[0].t;
279 auto f = bottom;
280 auto g = bottom;
281
282 // Sort by left bound
283 std::sort(r.begin(), r.end(), [](auto a, auto b) {
284 if (a.is_bottom())
285 return true;
286 if (b.is_bottom())
287 return false;
288
289 return *a.lower < *b.lower;
290 });
291
292 for (unsigned i = 0; i < r.size(); ++i)
293 {
294 // Crossing the south pole means wrapping from 1^w to 0^w; a singleton
295 // does not, and seeding f with it opens a gap later operands cover.
296 if (r[i].is_top() || *r[i].upper < *r[i].lower)
297 {
298 f = extend(f, r[i]);
299 }
300 }
301
302 for (unsigned i = 0; i < r.size(); ++i)
303 {
304 g = bigger(g, gap(f, r[i]));
305 f = extend(f, r[i]);
306 }
307 auto rr = complement(bigger(g, complement(f)));
308
309 return rr;
310 }
311 static wrapped_interval
313 {
314 assert(s.t == t.t);
315#if 0
316
317 if(s.is_included(t))
318 return t;
319 if(t.is_included(s))
320 return s;
321
322 const BigInt &a = s.lower;
323 const BigInt &b = s.upper;
324 const BigInt &c = t.lower;
325 const BigInt &d = t.upper;
326
327 wrapped_interval result(s.t);
328
329 if(t.contains(a) && t.contains(b) && s.contains(c) && s.contains(d))
330 return result;
331
332 if(t.contains(b) && s.contains(c))
333 {
334 result.lower = a;
335 result.upper = d;
336 return result;
337 }
338
339 if(s.contains(d) && t.contains(a))
340 {
341 result.lower = c;
342 result.upper = b;
343 return result;
344 }
345
346 wrapped_interval b_c(s.t);
347 b_c.lower = b;
348 b_c.upper = c;
349 wrapped_interval d_a(s.t);
350 d_a.lower = d;
351 d_a.upper = a;
352
353 if(
354 (b_c.cardinality() < d_a.cardinality()) ||
355 (b_c.cardinality() == d_a.cardinality() && a <= c))
356 {
357 result.lower = a;
358 result.upper = d;
359 return result;
360 }
361
362 result.lower = c;
363 result.upper = b;
364
365 return result;
366#else
367 std::vector<wrapped_interval> r;
368 r.push_back(s);
369 r.push_back(t);
370 auto result = over_join(r);
371 return result;
372#endif
373 }
374
376 {
377 wrapped_interval rhs(t);
378 rhs.bottom = i.is_bottom();
379 rhs.lower = i.lower;
380 rhs.upper = i.upper;
381
382 *this = over_join(rhs, *this);
383 }
384
385 // Under meet
386 static wrapped_interval
388 {
390 }
391
392 static std::vector<wrapped_interval>
394 {
395 assert(s.t == t.t);
396
397 std::vector<wrapped_interval> result;
398
399 if (s.is_bottom() || t.is_bottom())
400 return result;
401
402 if (s.is_equal(t) || s.is_top())
403 {
404 result.push_back(t);
405 return result;
406 }
407
408 if (t.is_top())
409 {
410 result.push_back(s);
411 return result;
412 }
413
414 const BigInt &a = *s.lower;
415 const BigInt &b = *s.upper;
416 const BigInt &c = *t.lower;
417 const BigInt &d = *t.upper;
418
419 if (t.contains(a) && t.contains(b) && s.contains(c) && s.contains(d))
420 {
421 wrapped_interval a_d(s.t);
422 a_d.lower = a;
423 a_d.upper = d;
424
425 wrapped_interval c_b(s.t);
426 c_b.lower = c;
427 c_b.upper = b;
428
429 result.push_back(a_d);
430 result.push_back(c_b);
431 return result;
432 }
433
434 if (t.contains(a) && t.contains(b))
435 {
436 result.push_back(s);
437 return result;
438 }
439
440 if (s.contains(c) && s.contains(d))
441 {
442 result.push_back(t);
443 return result;
444 }
445
446 if (t.contains(a) && s.contains(d) && !t.contains(b) && !s.contains(c))
447 {
448 wrapped_interval a_d(s.t);
449 a_d.lower = a;
450 a_d.upper = d;
451
452 result.push_back(a_d);
453 return result;
454 }
455
456 if (t.contains(b) && s.contains(c) && !t.contains(a) && !s.contains(d))
457 {
458 wrapped_interval c_b(s.t);
459 c_b.lower = c;
460 c_b.upper = b;
461
462 result.push_back(c_b);
463 return result;
464 }
465
466 return result;
467 }
468
470 static wrapped_interval
472 {
473 // TODO: this will probably not be needed!
474 assert(s.t == t.t);
475
476 if (s.is_included(t))
477 return s;
478 if (t.is_included(s))
479 return t;
480
481 const BigInt &a = *s.lower;
482 const BigInt &b = *s.upper;
483 const BigInt &c = *t.lower;
484 const BigInt &d = *t.upper;
485
486 wrapped_interval result(s.t);
487
488 if (!t.contains(a) && !t.contains(b) && !s.contains(c) && !s.contains(d))
489 {
490 result.bottom = true;
491 return result;
492 }
493
494 // Overlapping at both ends, the meet is two pieces: keep the smaller
495 // operand, which covers both (#8204).
496 if (t.contains(a) && t.contains(b) && s.contains(c) && s.contains(d))
497 {
498 if (
499 (s.cardinality() < t.cardinality()) ||
500 (s.cardinality() == t.cardinality() && a <= c))
501 return s;
502 return t;
503 }
504
505 if (s.contains(d) && t.contains(a))
506 {
507 result.lower = a;
508 result.upper = d;
509 return result;
510 }
511
512 result.lower = c;
513 result.upper = b;
514 return result;
515 }
516
518 {
519 wrapped_interval result(lhs.t);
520 result.set_lower(-1);
521 result.set_upper(-1);
522 return result * lhs;
523 }
524
525 static wrapped_interval
527 {
528 assert(f1.t == f2.t);
529 wrapped_interval result(f2.t);
530#if 1
531 if (f2.is_included(f1))
532 return f1;
533
534 // The interval is too big already, give up to TOP
535 if (f1.cardinality() >= f1.get_upper_bound() / 2)
536 return result;
537
538 auto f1_to_f2 = over_join(f1, f2);
539 assert(!f1_to_f2.is_bottom());
540
541 // Lower bound keeps the same but upper increases
542 if (*f1_to_f2.lower == *f1.lower && *f1_to_f2.upper == *f2.upper)
543 {
544 wrapped_interval double_upper(f1.t);
545 double_upper.lower = *f1_to_f2.lower;
546 double_upper.upper =
547 ((((2 * *f1.upper) - *f1.lower) % f1.get_upper_bound()) + 1) %
548 f1.get_upper_bound();
549 return over_join(f1_to_f2, double_upper);
550 }
551
552 // Upper bound keeps the same but lower decreases
553 if (*f1_to_f2.lower == *f2.lower && *f1_to_f2.upper == *f1.upper)
554 {
555 wrapped_interval double_lower(f1.t);
556 double_lower.lower =
557 ((((2 * *f1.lower) - *f1.upper) % f1.get_upper_bound()) - 1) %
558 f1.get_upper_bound();
559 double_lower.upper = *f1.upper;
560 return over_join(f1_to_f2, double_lower);
561 }
562
563 // Lower and upper bound of f1 is included in f2
564 if (f2.contains(*f1.lower) && f2.contains(*f1.upper))
565 {
566 wrapped_interval magic(f1.t);
567 // Maintain the lower
568 magic.lower = *f2.lower;
569 // Increase the upper by the difference between uppers
570 magic.upper = (((*f2.upper + (((2 * *f1.upper) - (2 * *f1.lower)) %
571 f1.get_upper_bound())) %
572 f1.get_upper_bound()) +
573 1) %
574 f1.get_upper_bound();
575 return over_join(f1_to_f2, magic);
576 }
577#endif
578
579 // Give up return top
580 return result;
581 }
582
583 friend wrapped_interval
585 {
586 assert(lhs.t->get_width() == rhs.t->get_width());
587 wrapped_interval result(lhs.t);
588
589 if (lhs.is_bottom() || rhs.is_bottom())
590 {
591 result.bottom = true;
592 return result;
593 }
594
595 auto mod = lhs.get_upper_bound();
596 if (lhs.cardinality() + rhs.cardinality() <= mod)
597 {
598 result.lower = (*lhs.lower + *rhs.lower) % mod;
599 result.upper = (*lhs.upper + *rhs.upper) % mod;
600 assert(*result.lower >= 0);
601 assert(*result.upper >= 0);
602 }
603
604 return result;
605 }
606
607 friend wrapped_interval
609 {
610 assert(lhs.t->get_width() == rhs.t->get_width());
611 wrapped_interval result(lhs.t);
612
613 if (lhs.is_bottom() || rhs.is_bottom())
614 {
615 result.bottom = true;
616 return result;
617 }
618
619 auto mod = lhs.get_upper_bound();
620 if (lhs.cardinality() + rhs.cardinality() <= mod)
621 {
622 result.lower = (*lhs.lower - *rhs.upper) % mod;
623 result.upper = (*lhs.upper - *rhs.lower) % mod;
624 if (*result.lower < 0)
625 *result.lower += mod;
626 if (*result.upper < 0)
627 *result.upper += mod;
628 assert(*result.lower >= 0);
629 assert(*result.upper >= 0);
630 }
631
632 return result;
633 }
634
636 {
637 wrapped_interval result(t);
638
639 result.lower = result.get_upper_bound() / 2 - 1;
640 result.upper = result.get_upper_bound() / 2;
641
642 return result;
643 }
644
646 {
647 wrapped_interval result(t);
648
649 result.upper = 0;
650 result.lower = result.get_upper_bound() - 1;
651
652 return result;
653 }
654
655 std::vector<wrapped_interval> ssplit() const
656 {
657 std::vector<wrapped_interval> r;
658 if (is_bottom())
659 return r;
660
661 if (is_top())
662 {
663 wrapped_interval north(t);
664 wrapped_interval south(t);
665
666 north.lower = get_upper_bound() / 2;
667 north.upper = get_upper_bound() - 1;
668
669 south.lower = 0;
670 south.upper = get_upper_bound() / 2 - 1;
671
672 r.push_back(north);
673 r.push_back(south);
674 return r;
675 }
676
677 if (!south_pole(t).is_included(*this))
678 {
679 r.push_back(*this);
680 return r;
681 }
682
683 wrapped_interval north(t);
684 wrapped_interval south(t);
685
686 north.upper = upper;
687 north.lower = 0;
688
689 south.lower = lower;
690 south.upper = get_upper_bound() - 1;
691
692 r.push_back(north);
693 r.push_back(south);
694
695 return r;
696 }
697
698 static wrapped_interval
700 {
701 return over_meet(s, complement(t));
702 }
703
704 std::vector<wrapped_interval> nsplit() const
705 {
706 std::vector<wrapped_interval> r;
707 if (is_bottom())
708 return r;
709
710 if (is_top())
711 {
712 wrapped_interval north(t);
713 wrapped_interval south(t);
714
715 north.lower = get_upper_bound() / 2;
716 north.upper = get_upper_bound() - 1;
717
718 south.lower = 0;
719 south.upper = get_upper_bound() / 2 - 1;
720
721 r.push_back(north);
722 r.push_back(south);
723 return r;
724 }
725
726 if (!north_pole(t).is_included(*this))
727 {
728 r.push_back(*this);
729 return r;
730 }
731
732 wrapped_interval north(t);
733 wrapped_interval south(t);
734
735 north.upper = upper;
736 north.lower = get_upper_bound() / 2;
737
738 south.lower = lower;
739 south.upper = get_upper_bound() / 2 - 1;
740
741 r.push_back(north);
742 r.push_back(south);
743
744 return r;
745 }
746
747 static std::vector<wrapped_interval> cut(const wrapped_interval &u)
748 {
749 std::vector<wrapped_interval> r;
750
751 for (const auto &w : u.nsplit())
752 {
753 for (const auto &s : w.ssplit())
754 {
755 r.push_back(s);
756 }
757 }
758 return r;
759 }
760
761 bool most_significant_bit(const BigInt &b) const
762 {
763 return (b >> (t->get_width() - 1)) == 1;
764 }
765
766 static BigInt trunc(const BigInt &b, unsigned k)
767 {
768 // TODO: and operation for bigint
769 return b % BigInt::power2(k);
770 }
771
772 static wrapped_interval
773 cast(const wrapped_interval &old, const type2tc &new_type)
774 {
775 // Special case for Bool!
776 if (is_bool_type(new_type))
777 {
778 wrapped_interval boolean(new_type);
779 boolean.lower = 0;
780 boolean.upper = 1;
781
782 if (!old.contains(0))
783 boolean.lower = 1;
784
785 else if (old.singleton())
786 boolean.upper = 0;
787
788 return boolean;
789 }
790
791 if (new_type->get_width() < old.t->get_width())
792 return old.trunc(new_type);
793
794 if (is_signedbv_type(old.t))
795 return old.sign_extension(new_type);
796
797 return old.zero_extension(new_type);
798 }
799
801 {
802 std::vector<wrapped_interval> parts;
803
804 for (auto &interval : ssplit())
805 {
806 wrapped_interval result(cast);
807 result.lower = interval.lower;
808 result.upper = interval.upper;
809 parts.push_back(result);
810 }
811
812 return over_join(parts);
813 }
814
815 wrapped_interval left_shift(unsigned k) const
816 {
817 if (is_bottom())
818 return *this;
819
820 wrapped_interval result(t);
821 if (
822 trunc(*lower, t->get_width() - k) == *lower &&
823 trunc(*upper, t->get_width() - k) == *upper)
824 {
825 result.lower = *lower << k;
826 result.upper = *upper << k;
827 }
828 else
829 {
830 result.lower = 0;
831 result.upper = (get_upper_bound() - 1) - BigInt::power2m1(k);
832 }
833 return result;
834 }
835
836 static wrapped_interval
838 {
839 if (lhs.is_bottom())
840 return lhs;
841
842 if (rhs.lower == rhs.upper && !rhs.is_bottom())
843 return lhs.left_shift(rhs.get_lower().to_uint64());
844
845 wrapped_interval result(lhs.t);
846 return result;
847 }
848
850 {
851 if (is_bottom())
852 return *this;
853
854 wrapped_interval result(t);
855 if (south_pole(t).is_included(*this))
856 {
857 result.lower = 0;
858 result.upper = BigInt::power2m1(t->get_width() - k);
859 }
860 else
861 {
862 result.lower = *lower >> k;
863 result.upper = *upper >> k;
864 }
865 return result;
866 }
867
868 static wrapped_interval
870 {
871 if (lhs.is_bottom())
872 return lhs;
873
874 if (rhs.lower == rhs.upper && !rhs.is_bottom())
875 return lhs.logical_right_shift(rhs.get_lower().to_uint64());
876
877 wrapped_interval result(lhs.t);
878 return result;
879 }
880
882 {
883 if (is_bottom())
884 return *this;
885
886 wrapped_interval result(t);
887 if (north_pole(t).is_included(*this))
888 {
889 BigInt m = BigInt::power2m1(t->get_width() - k);
890 result.lower = (get_upper_bound() - 1) - m;
891 result.upper = m;
892 }
893 else
894 {
895 result.set_lower(get_lower() >> k);
896 result.set_upper(get_upper() >> k);
897 }
898 return result;
899 }
900
902 const wrapped_interval &lhs,
903 const wrapped_interval &rhs)
904 {
905 if (lhs.is_bottom())
906 return lhs;
907
908 if (rhs.lower == rhs.upper && !rhs.is_bottom())
909 return lhs.arithmetic_right_shift(rhs.get_lower().to_uint64());
910
911 wrapped_interval result(lhs.t);
912 return result;
913 }
914
915 static wrapped_interval
917 {
918 wrapped_interval result(lhs.t);
919 if (
920 lhs.singleton() && rhs.singleton() && lhs.get_lower() == rhs.get_lower())
921 {
922 result.set_lower(1);
923 result.set_upper(1);
924 }
925 else if (intersection(lhs, rhs).empty())
926 {
927 result.set_lower(0);
928 result.set_upper(0);
929 }
930 else
931 {
932 result.set_lower(0);
933 result.set_upper(1);
934 }
935 return result;
936 }
937
939 {
940 wrapped_interval result(i.t);
941 if (!i.contains(0))
942 {
943 // i is always true, return false
944 result.set_lower(0);
945 result.set_upper(0);
946 }
947 else if (i.singleton())
948 {
949 // i is always false, return true
950 result.set_lower(1);
951 result.set_upper(1);
952 }
953 else
954 {
955 // i is a maybe
956 result.set_lower(0);
957 result.set_upper(1);
958 }
959 return result;
960 }
961
962 static wrapped_interval
964 {
965 return invert_bool(equality(lhs, rhs));
966 }
967
982 std::pair<BigInt, BigInt> get_interval_bounds() const
983 {
984 BigInt minimum = get_lower();
985 BigInt maximum = get_lower();
986
987 for (const wrapped_interval &w : cut(*this))
988 {
989 BigInt local_min = std::min(w.get_lower(), w.get_upper());
990 BigInt local_max = std::max(w.get_lower(), w.get_upper());
991
992 minimum = std::min(minimum, local_min);
993 maximum = std::max(maximum, local_max);
994 }
995 return std::make_pair(minimum, maximum);
996 }
997
998 static wrapped_interval
1000 {
1001 wrapped_interval result(lhs.t);
1002 const std::pair<BigInt, BigInt> lhs_bounds = lhs.get_interval_bounds();
1003 const std::pair<BigInt, BigInt> rhs_bounds = rhs.get_interval_bounds();
1004
1005 result.set_lower(lhs_bounds.second < rhs_bounds.first ? 1 : 0);
1006 result.set_upper(lhs_bounds.first >= rhs_bounds.second ? 0 : 1);
1007 assert(result.get_lower() <= result.get_upper());
1008 return result;
1009 }
1010
1011 static wrapped_interval
1013 {
1014 wrapped_interval result(lhs.t);
1015 const std::pair<BigInt, BigInt> lhs_bounds = lhs.get_interval_bounds();
1016 const std::pair<BigInt, BigInt> rhs_bounds = rhs.get_interval_bounds();
1017
1018 result.set_lower(lhs_bounds.second <= rhs_bounds.first ? 1 : 0);
1019 result.set_upper(lhs_bounds.first > rhs_bounds.second ? 0 : 1);
1020 assert(result.get_lower() <= result.get_upper());
1021 return result;
1022 }
1023
1024 static wrapped_interval
1026 {
1027 return less_than_equal(rhs, lhs);
1028 }
1029
1030 static wrapped_interval
1032 {
1033 return less_than(rhs, lhs);
1034 }
1035
1037 {
1038 std::vector<wrapped_interval> parts;
1039
1040 auto compute_outer_region = [this, &cast](bool bit) {
1041 BigInt result = 0;
1042 if (bit)
1043 result = (compute_upper_bound(cast) - 1) - (get_upper_bound() - 1);
1044
1045 return result;
1046 };
1047
1048 for (auto &interval : nsplit())
1049 {
1050 wrapped_interval result(cast);
1051 result.lower =
1052 compute_outer_region(most_significant_bit(*interval.lower)) +
1053 *interval.lower;
1054 result.upper =
1055 compute_outer_region(most_significant_bit(*interval.upper)) +
1056 *interval.upper;
1057 parts.push_back(result);
1058 }
1059
1060 return over_join(parts);
1061 }
1062
1064 {
1065 wrapped_interval result(cast);
1066 auto k = cast->get_width();
1067 assert(k <= t->get_width());
1068 if (is_bottom())
1069 result.bottom = true;
1070
1071 else if (
1072 (*lower >> k) == (*upper >> k) && (trunc(*lower, k) <= trunc(*upper, k)))
1073 {
1074 result.lower = trunc(*lower, k);
1075 result.upper = trunc(*upper, k);
1076 }
1077
1078 else if (
1079 ((*lower >> k) + 1 % 2) == (*upper >> k) % 2 &&
1080 (trunc(*lower, k) > trunc(*upper, k)))
1081 {
1082 result.lower = trunc(*lower, k);
1083 result.upper = trunc(*upper, k);
1084 }
1085 return result;
1086 }
1087
1088 static std::vector<wrapped_interval>
1090 {
1091 wrapped_interval result(lhs.t);
1092
1093 wrapped_interval w_u(lhs.t);
1094 wrapped_interval w_s(lhs.t);
1095
1096 auto up = lhs.get_upper_bound();
1097
1098 auto &a = *lhs.lower;
1099 auto &b = *lhs.upper;
1100 auto &c = *rhs.lower;
1101 auto &d = *rhs.upper;
1102
1103 if (b * d - a * c < up)
1104 {
1105 w_u.lower = (a * c) % up;
1106 w_u.upper = (b * d) % up;
1107 }
1108
1109 if (
1110 ((w_s.most_significant_bit(a) == w_s.most_significant_bit(b)) ==
1111 (w_s.most_significant_bit(c) == w_s.most_significant_bit(d))) &&
1112 (b * d - a * c < up))
1113 {
1114 w_s.lower = a * c % up;
1115 w_s.upper = b * d % up;
1116 }
1117 else if (
1118 (w_s.most_significant_bit(a) && w_s.most_significant_bit(b)) &&
1119 (!w_s.most_significant_bit(c) && !w_s.most_significant_bit(d)) &&
1120 (b * c - a * d < up))
1121 {
1122 w_s.lower = a * d % up;
1123 w_s.upper = b * c % up;
1124 }
1125 else if (
1126 (!w_s.most_significant_bit(a) && !w_s.most_significant_bit(b)) &&
1127 (w_s.most_significant_bit(c) && w_s.most_significant_bit(d)) &&
1128 (a * d - b * c < up))
1129 {
1130 w_s.lower = b * c % up;
1131 w_s.upper = a * d % up;
1132 }
1133
1134 return intersection(w_u, w_s);
1135 }
1136
1137 friend wrapped_interval
1139 {
1140 // TODO: over-join for list
1141 std::vector<wrapped_interval> r;
1142 for (auto &u : cut(lhs))
1143 for (auto &v : cut(rhs))
1144 for (auto &m : multiply_us(u, v))
1145 r.push_back(m);
1146 return over_join(r);
1147 }
1148
1150 {
1151 wrapped_interval r(rhs.t);
1152 r.lower = 0;
1153 r.upper = *rhs.upper - 1;
1154 return r;
1155 }
1156
1157 friend wrapped_interval
1159 {
1160 std::vector<wrapped_interval> r;
1161
1163 zero.lower = 0;
1164 zero.upper = 0;
1165
1166 for (auto &u : s.ssplit())
1167 for (auto &v : t.ssplit())
1168 {
1169 // Only optimize if its singleton
1170 auto v_non_zero = difference(v, zero);
1171 if ((u / v_non_zero).cardinality() == 1)
1172 {
1173 r.push_back(u - ((u / v_non_zero) * v_non_zero));
1174 continue;
1175 }
1176 if (is_signedbv_type(u.t) && s.most_significant_bit(*u.upper))
1177 r.push_back(-amb(v));
1178 else
1179 r.push_back(amb(v));
1180 }
1181
1182 return over_join(r);
1183 }
1184
1185 friend wrapped_interval
1187 {
1188 std::vector<wrapped_interval> r;
1189
1190 wrapped_interval zero(lhs.t);
1191 zero.lower = 0;
1192 zero.upper = 0;
1193 if (!is_signedbv_type(lhs.t))
1194 {
1195 for (const auto &u : lhs.ssplit())
1196 for (const auto &v : rhs.ssplit())
1197 {
1198 auto non_zero = difference(v, zero);
1199 wrapped_interval temp(lhs.t);
1200 temp.lower = *u.lower / *non_zero.upper;
1201 temp.upper = *u.upper / *non_zero.lower;
1202 r.push_back(temp);
1203 }
1204 }
1205 else
1206 {
1207 for (const auto &u : cut(lhs))
1208 for (const auto &v : cut(rhs))
1209 {
1210 auto non_zero = difference(v, zero);
1211 wrapped_interval temp(lhs.t);
1212
1213 auto msb_a = temp.most_significant_bit(*u.lower);
1214 auto msb_c = temp.most_significant_bit(*non_zero.lower);
1215
1216 if (!msb_a && !msb_c)
1217 {
1218 temp.set_lower(u.get_lower() / non_zero.get_upper());
1219 temp.set_upper(u.get_upper() / non_zero.get_lower());
1220 }
1221 else if (msb_a && msb_c)
1222 {
1223 temp.set_lower(u.get_upper() / non_zero.get_lower());
1224 temp.set_upper(u.get_lower() / non_zero.get_upper());
1225 }
1226 else if (!msb_a && msb_c)
1227 {
1228 temp.set_lower(u.get_upper() / non_zero.get_upper());
1229 temp.set_upper(u.get_lower() / non_zero.get_lower());
1230 }
1231 else if (msb_a && !msb_c)
1232 {
1233 temp.set_lower(u.get_lower() / non_zero.get_lower());
1234 temp.set_upper(u.get_upper() / non_zero.get_upper());
1235 }
1236 else
1237 {
1238 log_error("This should never happen");
1239 abort();
1240 }
1241
1242 r.push_back(temp);
1243 }
1244 }
1245 return over_join(r);
1246 }
1247
1248 typedef std::function<uint64_t(uint64_t, uint64_t, uint64_t, uint64_t)>
1250
1251 friend wrapped_interval
1253 {
1254 const unsigned width = lhs.t->get_width();
1255 const auto min_or =
1256 [&width](uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
1257 uint64_t m, temp;
1258 m = compute_m(width);
1259 while (m != 0)
1260 {
1261 if (~a & c & m)
1262 {
1263 temp = (a | m) & -m;
1264 if (temp <= b)
1265 {
1266 a = temp;
1267 break;
1268 }
1269 }
1270 else if (a & ~c & m)
1271 {
1272 temp = (c | m) & -m;
1273 if (temp <= d)
1274 {
1275 c = temp;
1276 break;
1277 }
1278 }
1279 m = m >> 1;
1280 }
1281 return a | c;
1282 };
1283 const auto max_or =
1284 [&width](uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
1285 uint64_t m, temp;
1286 m = compute_m(width);
1287 if (width == 32)
1288 assert(m == 0x80000000);
1289 while (m != 0)
1290 {
1291 if (b & d & m)
1292 {
1293 temp = (b - m) | (m - 1);
1294 if (temp >= a)
1295 {
1296 b = temp;
1297 break;
1298 }
1299 temp = (d - m) | (m - 1);
1300 if (temp >= c)
1301 {
1302 d = temp;
1303 break;
1304 }
1305 }
1306 m = m >> 1;
1307 }
1308 return b | d;
1309 };
1310 return warren_approximation(lhs, rhs, min_or, max_or);
1311 }
1312
1313 friend wrapped_interval
1315 {
1316 const unsigned width = lhs.t->get_width();
1317 const auto min_and =
1318 [&width](uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
1319 uint64_t m, temp;
1320
1321 m = compute_m(width);
1322 while (m != 0)
1323 {
1324 if (~a & ~c & m)
1325 {
1326 temp = (a | m) & -m;
1327 if (temp <= b)
1328 {
1329 a = temp;
1330 break;
1331 }
1332 temp = (c | m) & -m;
1333 if (temp <= d)
1334 {
1335 c = temp;
1336 break;
1337 }
1338 }
1339 m = m >> 1;
1340 }
1341 return a & c;
1342 };
1343 const auto max_and =
1344 [&width](uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
1345 uint64_t m, temp;
1346
1347 m = compute_m(width);
1348 while (m != 0)
1349 {
1350 if (b & ~d & m)
1351 {
1352 temp = (b & ~m) | (m - 1);
1353 if (temp >= a)
1354 {
1355 b = temp;
1356 break;
1357 }
1358 }
1359 else if (~b & d & m)
1360 {
1361 temp = (d & ~m) | (m - 1);
1362 if (temp >= c)
1363 {
1364 d = temp;
1365 break;
1366 }
1367 }
1368 m = m >> 1;
1369 }
1370 return b & d;
1371 };
1372 return warren_approximation(lhs, rhs, min_and, max_and);
1373 }
1374
1375 friend wrapped_interval
1377 {
1378 const unsigned width = lhs.t->get_width();
1379 const auto min_xor =
1380 [&width](uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
1381 uint64_t m, temp;
1382 m = compute_m(width);
1383 while (m != 0)
1384 {
1385 if (~a & c & m)
1386 {
1387 temp = (a | m) & -m;
1388 if (temp <= b)
1389 {
1390 a = temp;
1391 }
1392 }
1393 else if (a & ~c & m)
1394 {
1395 temp = (c | m) & -m;
1396 if (temp <= d)
1397 {
1398 c = temp;
1399 }
1400 }
1401 m = m >> 1;
1402 }
1403 return a ^ c;
1404 };
1405 const auto max_xor =
1406 [&width](uint64_t a, uint64_t b, uint64_t c, uint64_t d) {
1407 uint64_t m, temp;
1408 m = compute_m(width);
1409 while (m != 0)
1410 {
1411 if (b & d & m)
1412 {
1413 temp = (b - m) | (m - 1);
1414 if (temp >= a)
1415 {
1416 b = temp;
1417 }
1418 else
1419 {
1420 temp = (d - m) | (m - 1);
1421 if (temp >= c)
1422 {
1423 d = temp;
1424 }
1425 }
1426 }
1427 m = m >> 1;
1428 }
1429 return b ^ d;
1430 };
1431 return warren_approximation(lhs, rhs, min_xor, max_xor);
1432 }
1433
1435 {
1436 wrapped_interval result(w.t);
1437 result.set_lower(-w.get_upper() - 1);
1438 result.set_upper(-w.get_lower() - 1);
1439 return result;
1440 }
1441
1443 {
1444 return upper_bound;
1445 }
1446
1448
1450 const wrapped_interval &cond,
1451 const wrapped_interval &true_value,
1452 const wrapped_interval &false_value)
1453 {
1454 if (!cond.contains(0))
1455 return true_value;
1456
1457 if (cond.singleton())
1458 return false_value;
1459
1460 return over_join(true_value, false_value);
1461 }
1462
1463protected:
1465
1466private:
1467 static BigInt compute_upper_bound(const type2tc &t)
1468 {
1469 if (is_pointer_type(t))
1470 return BigInt::power2(config.ansi_c.address_width);
1471
1472 return BigInt::power2(t->get_width());
1473 }
1474
1475 // For bitwise intervals approximations (Warren 2002)
1476 static uint64_t compute_m(unsigned width)
1477 {
1478 assert(width - 1 < 64);
1479 uint64_t m = (uint64_t)1 << (width - 1);
1480 if (width == 32)
1481 assert(m == 0x80000000);
1482 return m;
1483 }
1484
1485 static wrapped_interval warren_approximation(
1486 const wrapped_interval &lhs,
1487 const wrapped_interval &rhs,
1490 {
1491 // TODO: BigInt has no support for bitwise operators
1492 wrapped_interval result(lhs.t);
1493 if (lhs.t->get_width() > 64)
1494 return result;
1495
1496 std::vector<wrapped_interval> r;
1497 for (auto &u : lhs.ssplit())
1498 for (auto &v : rhs.ssplit())
1499 {
1500 auto u_lower = (*u.lower).to_uint64();
1501 auto u_upper = (*u.upper).to_uint64();
1502
1503 auto v_lower = (*v.lower).to_uint64();
1504 auto v_upper = (*v.upper).to_uint64();
1505
1506 wrapped_interval temp(lhs.t);
1507 temp.lower = min(u_lower, u_upper, v_lower, v_upper);
1508 temp.upper = max(u_lower, u_upper, v_lower, v_upper);
1509 r.push_back(temp);
1510 }
1511
1512 return over_join(r);
1513 }
1514};
Definition bigint.hh:58
static BigInt power2(unsigned n)
Definition bigint.hh:310
bool is_zero() const
Definition bigint.hh:218
bool is_negative() const
Definition bigint.hh:226
static BigInt power2m1(unsigned n)
Definition bigint.hh:318
uint64_t to_uint64() const
Definition bigint.cpp:659
T get_lower() const
Definition interval_template.h:42
void set_lower(const T &b)
Definition interval_template.h:75
void set_upper(const T &b)
Definition interval_template.h:71
bool is_bottom() const
Definition interval_template.h:117
std::optional< BigInt > upper
Definition interval_template.h:39
BigInt get_upper() const
Definition interval_template.h:47
bool singleton() const
There is only one value that satisfies.
Definition interval_template.h:128
std::optional< BigInt > lower
Definition interval_template.h:39
unsigned int get_width() const
Fetch bit width of this type.
Definition irep2_type.cpp:352
Definition toml.hpp:1531
Definition wrapped_interval.h:6
friend wrapped_interval operator-(const wrapped_interval &lhs)
Definition wrapped_interval.h:517
static bool is_representable(const type2tc &t)
Definition wrapped_interval.h:21
static wrapped_interval south_pole(const type2tc &t)
Definition wrapped_interval.h:645
wrapped_interval trunc(const type2tc &cast) const
Definition wrapped_interval.h:1063
bool most_significant_bit(const BigInt &b) const
Definition wrapped_interval.h:761
std::vector< wrapped_interval > ssplit() const
Definition wrapped_interval.h:655
bool is_included(const wrapped_interval &rhs) const
Definition wrapped_interval.h:209
wrapped_interval logical_right_shift(unsigned k) const
Definition wrapped_interval.h:849
static wrapped_interval logical_right_shift(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:869
BigInt get_min() const
Definition wrapped_interval.h:170
static wrapped_interval left_shift(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:837
BigInt get_max() const
Definition wrapped_interval.h:176
static wrapped_interval under_meet(const wrapped_interval &s, const wrapped_interval &t)
Definition wrapped_interval.h:387
bool is_equal(const wrapped_interval &rhs) const
Definition wrapped_interval.h:204
wrapped_interval sign_extension(const type2tc &cast) const
Definition wrapped_interval.h:1036
static wrapped_interval less_than_equal(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:1012
static wrapped_interval difference(const wrapped_interval &s, const wrapped_interval &t)
Definition wrapped_interval.h:699
bool contains(const BigInt &e) const override
Definition wrapped_interval.h:196
void make_le_than(const wrapped_interval &rhs)
Definition wrapped_interval.h:124
friend wrapped_interval operator-(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:608
void make_ge_than(const BigInt &v) override
Definition wrapped_interval.h:143
static BigInt trunc(const BigInt &b, unsigned k)
Definition wrapped_interval.h:766
static std::vector< wrapped_interval > intersection(const wrapped_interval &s, const wrapped_interval &t)
Definition wrapped_interval.h:393
static wrapped_interval over_join(const wrapped_interval &s, const wrapped_interval &t)
Definition wrapped_interval.h:312
friend wrapped_interval operator%(const wrapped_interval &s, const wrapped_interval &t)
Definition wrapped_interval.h:1158
friend wrapped_interval operator^(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:1376
static wrapped_interval over_meet(const wrapped_interval &s, const wrapped_interval &t)
Over meet.
Definition wrapped_interval.h:471
std::vector< wrapped_interval > nsplit() const
Definition wrapped_interval.h:704
wrapped_interval(const type2tc &t)
Definition wrapped_interval.h:12
BigInt cardinality() const
Definition wrapped_interval.h:183
wrapped_interval zero_extension(const type2tc &cast) const
Definition wrapped_interval.h:800
static std::vector< wrapped_interval > multiply_us(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:1089
static wrapped_interval less_than(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:999
friend wrapped_interval operator*(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:1138
static wrapped_interval cast(const wrapped_interval &old, const type2tc &new_type)
Definition wrapped_interval.h:773
bool empty() const override
Checks whether there are values that satisfy the the interval.
Definition wrapped_interval.h:65
wrapped_interval left_shift(unsigned k) const
Definition wrapped_interval.h:815
void approx_union_with(const interval_templatet< BigInt > &i) override
Definition wrapped_interval.h:375
std::pair< BigInt, BigInt > get_interval_bounds() const
Computes the minimum and maximum value inside the interval.
Definition wrapped_interval.h:982
static wrapped_interval invert_bool(const wrapped_interval &i)
Definition wrapped_interval.h:938
bool is_top() const override
Definition wrapped_interval.h:70
const BigInt & get_upper_bound() const
Definition wrapped_interval.h:1442
BigInt upper_bound
Definition wrapped_interval.h:1464
static wrapped_interval north_pole(const type2tc &t)
Definition wrapped_interval.h:635
static std::vector< wrapped_interval > cut(const wrapped_interval &u)
Definition wrapped_interval.h:747
void make_le_than(const BigInt &v) override
Definition wrapped_interval.h:112
static wrapped_interval gap(const wrapped_interval &s, const wrapped_interval &t)
Definition wrapped_interval.h:249
static wrapped_interval bitnot(const wrapped_interval &w)
Definition wrapped_interval.h:1434
wrapped_interval arithmetic_right_shift(unsigned k) const
Definition wrapped_interval.h:881
static wrapped_interval ternary_if(const wrapped_interval &cond, const wrapped_interval &true_value, const wrapped_interval &false_value)
Definition wrapped_interval.h:1449
static wrapped_interval extrapolate_to(const wrapped_interval &f1, const wrapped_interval &f2)
Definition wrapped_interval.h:526
static wrapped_interval extend(const wrapped_interval &s, const wrapped_interval &t)
Definition wrapped_interval.h:221
friend wrapped_interval operator&(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:1314
static wrapped_interval bigger(const wrapped_interval &s, const wrapped_interval &t)
Definition wrapped_interval.h:265
static wrapped_interval amb(const wrapped_interval &rhs)
Definition wrapped_interval.h:1149
static wrapped_interval equality(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:916
wrapped_interval()
Definition wrapped_interval.h:8
BigInt get(bool is_upper) const override
Definition wrapped_interval.h:49
static wrapped_interval complement(const wrapped_interval &w)
Definition wrapped_interval.h:75
static wrapped_interval not_equal(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:963
void make_ge_than(const wrapped_interval &rhs)
Definition wrapped_interval.h:151
static bool wrapped_le(const BigInt &b, const BigInt &a, const BigInt &c, const type2tc &t)
b <=_a c iff b -_w a <= c -_w a
Definition wrapped_interval.h:94
static wrapped_interval greater_than_equal(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:1025
friend wrapped_interval operator+(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:584
type2tc t
Definition wrapped_interval.h:1447
bool bottom
Definition wrapped_interval.h:64
BigInt convert_to_wrap(const BigInt &b) const
Definition wrapped_interval.h:27
static wrapped_interval over_join(std::vector< wrapped_interval > &r)
Over union.
Definition wrapped_interval.h:271
static wrapped_interval arithmetic_right_shift(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:901
std::function< uint64_t(uint64_t, uint64_t, uint64_t, uint64_t)> warren_approximation_function
Definition wrapped_interval.h:1249
void set(bool is_upper, const BigInt &b) override
Definition wrapped_interval.h:39
friend wrapped_interval operator/(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:1186
static wrapped_interval greater_than(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:1031
friend wrapped_interval operator|(const wrapped_interval &lhs, const wrapped_interval &rhs)
Definition wrapped_interval.h:1252
configt config
Definition config.cpp:8
pthread_cond_t cond
Definition cuda.h:50
@ zero
Success iff the returned integer is zero (e.g. pthread_mutex_lock).
Definition fallible_calls.h:26
irep_container< type2t > type2tc
Definition irep2.h:430
#define log_error(fmt,...)
Definition message.h:83
const T & max(const T &left, const T &right)
Definition min_max.h:10
const T & min(const T &left, const T &right)
Definition min_max.h:19
void * value
Definition solidity_mapping.c:2
void abort(void)
Definition stdlib.c:77
TOML_PURE_INLINE_GETTER constexpr const T & min(const T &a, const T &b) noexcept
Definition toml.hpp:2491