Skip to main content

rapx/analysis/range/domain/
range.rs

1#![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    // Parameterized constructor
25    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    // Getter for lower bound
39    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    // Getter for upper bound
63    pub fn get_upper(&self) -> T {
64        self.range.upper().unwrap().clone()
65    }
66
67    // Check if the range type is unknown
68    pub fn is_unknown(&self) -> bool {
69        self.rtype == RangeType::Unknown
70    }
71
72    // Set the range type to unknown
73    pub fn set_unknown(&mut self) {
74        self.rtype = RangeType::Unknown;
75    }
76
77    // Check if the range type is regular
78    pub fn is_regular(&self) -> bool {
79        self.rtype == RangeType::Regular
80    }
81
82    // Set the range type to regular
83    pub fn set_regular(&mut self) {
84        self.rtype = RangeType::Regular;
85    }
86
87    // Check if the range type is empty
88    pub fn is_empty(&self) -> bool {
89        self.rtype == RangeType::Empty
90    }
91
92    // Set the range type to empty
93    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}