rapx/analysis/range/domain/
range.rs1#![allow(unused_imports)]
2#![allow(unused_variables)]
3#![allow(dead_code)]
4#![allow(unused_assignments)]
5#![allow(irrefutable_let_patterns)]
6use std::{default, fmt};
7
8use num_traits::{Bounded, Num, Zero};
9use rust_intervals::Interval;
10use rustc_middle::mir::{BinOp, UnOp};
11use std::ops::{Add, Mul, Sub};
12
13use crate::{
14 analysis::range::{Range, RangeType, domain::symbolic_expr::IntervalTypeTrait},
15 rap_trace,
16};
17
18use super::domain::*;
19
20impl<T> Range<T>
21where
22 T: IntervalArithmetic,
23{
24 pub fn new(lb: T, ub: T, rtype: RangeType) -> Self {
26 Self {
27 rtype,
28 range: Interval::new_closed_closed(lb, ub),
29 }
30 }
31 pub fn default(default: T) -> Self {
32 Self {
33 rtype: RangeType::Unknown,
34
35 range: Interval::new_closed_closed(default, default),
36 }
37 }
38 pub fn init(r: Interval<T>) -> Self {
40 Self {
41 rtype: RangeType::Regular,
42 range: r,
43 }
44 }
45
46 pub fn top() -> Self {
47 Self::new(T::min_value(), T::max_value(), RangeType::Regular)
48 }
49
50 pub fn bottom() -> Self {
51 Self::default(T::min_value())
52 }
53
54 pub fn exact(value: T) -> Self {
55 Self::new(value.clone(), value, RangeType::Regular)
56 }
57
58 pub fn get_lower(&self) -> T {
59 self.range.lower().unwrap().clone()
60 }
61
62 pub fn get_upper(&self) -> T {
64 self.range.upper().unwrap().clone()
65 }
66
67 pub fn is_unknown(&self) -> bool {
69 self.rtype == RangeType::Unknown
70 }
71
72 pub fn set_unknown(&mut self) {
74 self.rtype = RangeType::Unknown;
75 }
76
77 pub fn is_regular(&self) -> bool {
79 self.rtype == RangeType::Regular
80 }
81
82 pub fn set_regular(&mut self) {
84 self.rtype = RangeType::Regular;
85 }
86
87 pub fn is_empty(&self) -> bool {
89 self.rtype == RangeType::Empty
90 }
91
92 pub fn set_empty(&mut self) {
94 self.rtype = RangeType::Empty;
95 }
96 pub fn set_default(&mut self) {
97 self.rtype = RangeType::Regular;
98 self.range = Interval::new_closed_closed(T::min_value(), T::max_value());
99 }
100 pub fn add(&self, other: &Range<T>) -> Range<T> {
101 let a = self
102 .get_lower()
103 .clone()
104 .checked_add(&other.get_lower().clone())
105 .unwrap_or(T::max_value());
106
107 let b = self
108 .get_upper()
109 .clone()
110 .checked_add(&other.get_upper().clone())
111 .unwrap_or(T::max_value());
112
113 Range::new(a, b, RangeType::Regular)
114 }
115
116 pub fn sub(&self, other: &Range<T>) -> Range<T> {
117 let a = self
118 .get_lower()
119 .clone()
120 .checked_sub(&other.get_upper().clone())
121 .unwrap_or(T::min_value());
122
123 let b = self
124 .get_upper()
125 .clone()
126 .checked_sub(&other.get_lower().clone())
127 .unwrap_or(T::max_value());
128
129 Range::new(a, b, RangeType::Regular)
130 }
131
132 pub fn mul(&self, other: &Range<T>) -> Range<T> {
133 let candidates = [self.get_lower().clone() * other.get_lower().clone(),
134 self.get_lower().clone() * other.get_upper().clone(),
135 self.get_upper().clone() * other.get_lower().clone(),
136 self.get_upper().clone() * other.get_upper().clone()];
137 let min = candidates
138 .iter()
139 .cloned()
140 .min_by(|a, b| a.partial_cmp(b).unwrap())
141 .unwrap();
142 let max = candidates
143 .iter()
144 .cloned()
145 .max_by(|a, b| a.partial_cmp(b).unwrap())
146 .unwrap();
147 Range::new(min, max, RangeType::Regular)
148 }
149
150 pub fn intersectwith(&self, other: &Range<T>) -> Range<T> {
151 if self.is_unknown() {
152 Range::new(
153 other.get_lower().clone(),
154 other.get_upper().clone(),
155 RangeType::Regular,
156 )
157 } else if other.is_unknown() {
158 Range::new(
159 self.get_lower().clone(),
160 self.get_upper().clone(),
161 RangeType::Regular,
162 )
163 } else {
164 let result = self.range.clone().intersection(&other.range.clone());
165 let mut range = Range::bottom();
166
167 if let r = result {
168 range = Range::init(r);
169 range
170 } else {
171 range
172 }
173 }
174 }
175
176 pub fn unionwith(&self, other: &Range<T>) -> Range<T> {
177 if self.is_unknown() {
178 Range::new(
179 other.get_lower().clone(),
180 other.get_upper().clone(),
181 RangeType::Regular,
182 )
183 } else if other.is_unknown() {
184 Range::new(
185 self.get_lower().clone(),
186 self.get_upper().clone(),
187 RangeType::Regular,
188 )
189 } else {
190 let left = std::cmp::min_by(self.get_lower(), other.get_lower(), |a, b| {
191 a.partial_cmp(b).unwrap()
192 });
193 let right = std::cmp::max_by(self.get_upper(), other.get_upper(), |a, b| {
194 a.partial_cmp(b).unwrap()
195 });
196 Range::new(left.clone(), right.clone(), RangeType::Regular)
197 }
198 }
199}
200
201pub trait Lattice {
202 fn widen(&self, other: &Self) -> Self;
203 fn narrow(&self, other: &Self) -> Self;
204}
205
206impl<T> Range<T>
207where
208 T: IntervalArithmetic,
209{
210 pub fn widen(&self, other: &Range<T>) -> Range<T> {
211 if self.is_unknown() {
212 return other.clone();
213 }
214 let a_lower = self.get_lower();
215 let a_upper = self.get_upper();
216 let b_lower = other.get_lower();
217 let b_upper = other.get_upper();
218
219 if b_lower < a_lower && b_upper > a_upper {
220 Range::top()
221 } else if b_lower < a_lower {
222 Range::new(T::min_value(), a_upper.clone(), RangeType::Regular)
223 } else if b_upper > a_upper {
224 Range::new(a_lower.clone(), T::max_value(), RangeType::Regular)
225 } else {
226 self.clone()
227 }
228 }
229
230 pub fn narrow(&self, other: &Range<T>) -> Range<T> {
231 let a_lower = self.get_lower();
232 let a_upper = self.get_upper();
233 let b_lower = other.get_lower();
234 let b_upper = other.get_upper();
235
236 let final_lower = if a_lower == T::min_value() && b_lower > T::min_value() {
237 b_lower.clone()
238 } else if a_lower <= b_lower {
239 b_lower.clone()
240 } else {
241 a_lower.clone()
242 };
243
244 let final_upper = if a_upper == T::max_value() && b_upper < T::max_value() {
245 b_upper.clone()
246 } else if a_upper >= b_upper {
247 b_upper.clone()
248 } else {
249 a_upper.clone()
250 };
251
252 Range::new(final_lower, final_upper, RangeType::Regular)
253 }
254}
255
256impl<T: IntervalArithmetic> Lattice for Range<T> {
257 fn widen(&self, other: &Range<T>) -> Range<T> {
258 Range::widen(self, other)
259 }
260
261 fn narrow(&self, other: &Range<T>) -> Range<T> {
262 Range::narrow(self, other)
263 }
264}