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 = vec![
134 self.get_lower().clone() * other.get_lower().clone(),
135 self.get_lower().clone() * other.get_upper().clone(),
136 self.get_upper().clone() * other.get_lower().clone(),
137 self.get_upper().clone() * other.get_upper().clone(),
138 ];
139 let min = candidates
140 .iter()
141 .cloned()
142 .min_by(|a, b| a.partial_cmp(b).unwrap())
143 .unwrap();
144 let max = candidates
145 .iter()
146 .cloned()
147 .max_by(|a, b| a.partial_cmp(b).unwrap())
148 .unwrap();
149 Range::new(min, max, RangeType::Regular)
150 }
151
152 pub fn intersectwith(&self, other: &Range<T>) -> Range<T> {
153 if self.is_unknown() {
154 return Range::new(
155 other.get_lower().clone(),
156 other.get_upper().clone(),
157 RangeType::Regular,
158 );
159 } else if other.is_unknown() {
160 return Range::new(
161 self.get_lower().clone(),
162 self.get_upper().clone(),
163 RangeType::Regular,
164 );
165 } else {
166 let result = self.range.clone().intersection(&other.range.clone());
167 let mut range = Range::bottom();
168
169 if let r = result {
170 range = Range::init(r);
171 range
172 } else {
173 range
174 }
175 }
176 }
177
178 pub fn unionwith(&self, other: &Range<T>) -> Range<T> {
179 if self.is_unknown() {
180 return Range::new(
181 other.get_lower().clone(),
182 other.get_upper().clone(),
183 RangeType::Regular,
184 );
185 } else if other.is_unknown() {
186 return Range::new(
187 self.get_lower().clone(),
188 self.get_upper().clone(),
189 RangeType::Regular,
190 );
191 } else {
192 let left = std::cmp::min_by(self.get_lower(), other.get_lower(), |a, b| {
193 a.partial_cmp(b).unwrap()
194 });
195 let right = std::cmp::max_by(self.get_upper(), other.get_upper(), |a, b| {
196 a.partial_cmp(b).unwrap()
197 });
198 Range::new(left.clone(), right.clone(), RangeType::Regular)
199 }
200 }
201}
202
203pub trait Lattice {
204 fn widen(&self, other: &Self) -> Self;
205 fn narrow(&self, other: &Self) -> Self;
206}
207
208impl<T> Range<T>
209where
210 T: IntervalArithmetic,
211{
212 pub fn widen(&self, other: &Range<T>) -> Range<T> {
213 if self.is_unknown() {
214 return other.clone();
215 }
216 let a_lower = self.get_lower();
217 let a_upper = self.get_upper();
218 let b_lower = other.get_lower();
219 let b_upper = other.get_upper();
220
221 if b_lower < a_lower && b_upper > a_upper {
222 Range::top()
223 } else if b_lower < a_lower {
224 Range::new(T::min_value(), a_upper.clone(), RangeType::Regular)
225 } else if b_upper > a_upper {
226 Range::new(a_lower.clone(), T::max_value(), RangeType::Regular)
227 } else {
228 self.clone()
229 }
230 }
231
232 pub fn narrow(&self, other: &Range<T>) -> Range<T> {
233 let a_lower = self.get_lower();
234 let a_upper = self.get_upper();
235 let b_lower = other.get_lower();
236 let b_upper = other.get_upper();
237
238 let final_lower = if a_lower == T::min_value() && b_lower > T::min_value() {
239 b_lower.clone()
240 } else if a_lower <= b_lower {
241 b_lower.clone()
242 } else {
243 a_lower.clone()
244 };
245
246 let final_upper = if a_upper == T::max_value() && b_upper < T::max_value() {
247 b_upper.clone()
248 } else if a_upper >= b_upper {
249 b_upper.clone()
250 } else {
251 a_upper.clone()
252 };
253
254 Range::new(final_lower, final_upper, RangeType::Regular)
255 }
256}
257
258impl<T: IntervalArithmetic> Lattice for Range<T> {
259 fn widen(&self, other: &Range<T>) -> Range<T> {
260 Range::widen(self, other)
261 }
262
263 fn narrow(&self, other: &Range<T>) -> Range<T> {
264 Range::narrow(self, other)
265 }
266}