rapx/analysis/core/range_analysis/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};
11// use std::ops::Range;
12use std::ops::{Add, Mul, Sub};
13
14use crate::{
15    analysis::core::range_analysis::{Range, RangeType, domain::SymbolicExpr::IntervalTypeTrait},
16    rap_trace,
17};
18
19use super::domain::*;
20
21// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22//     let lower: &Lazy<String> = if self.range.left.0 == T::min_value() {
23//         &STR_MIN
24//     } else if self.range.left.0 == T::max_value() {
25//         &STR_MAX
26//     } else {
27//         static DUMMY: Lazy<String> = Lazy::new(|| String::new());
28//         let tmp = format!("{}", self.range.left.0);
29//         let tmp_clone = tmp.clone();
30//         let local = Lazy::new(|| tmp);
31//         return write!(
32//             f,
33//             "{} [{}, {}]",
34//             self.rtype,
35//             *local,
36//             if self.range.right.0 == T::min_value() {
37//                 &*STR_MIN
38//             } else if self.range.right.0 == T::max_value() {
39//                 &*STR_MAX
40//             } else {
41//                 return write!(f, "{} [{}, {}]", self.rtype, tmp_clone, self.range.right.0);
42//             }
43//         );
44//     };
45
46//     let upper: &Lazy<String> = if self.range.right.0 == T::min_value() {
47//         &STR_MIN
48//     } else if self.range.right.0 == T::max_value() {
49//         &STR_MAX
50//     } else {
51//         let tmp = format!("{}", self.range.right.0);
52//         let local = Lazy::new(|| tmp);
53//         return write!(f, "{} [{}, {}]", self.rtype, &**lower, *local);
54//     };
55
56//     write!(f, "{} [{}, {}]", self.rtype, &**lower, &**upper)
57// }
58
59impl<T> Range<T>
60where
61    T: IntervalArithmetic,
62{
63    // Parameterized constructor
64    pub fn new(lb: T, ub: T, rtype: RangeType) -> Self {
65        Self {
66            rtype,
67            range: Interval::new_closed_closed(lb, ub),
68        }
69    }
70    pub fn default(default: T) -> Self {
71        Self {
72            rtype: RangeType::Unknown,
73
74            range: Interval::new_closed_closed(default, default),
75        }
76    }
77    // Getter for lower bound
78    pub fn init(r: Interval<T>) -> Self {
79        Self {
80            rtype: RangeType::Regular,
81            range: r,
82        }
83    }
84    pub fn get_lower(&self) -> T {
85        self.range.lower().unwrap().clone()
86    }
87
88    // Getter for upper bound
89    pub fn get_upper(&self) -> T {
90        self.range.upper().unwrap().clone()
91    }
92
93    // // Setter for lower bound
94    // pub fn set_lower(&mut self, newl: T) {
95    // }
96
97    // // Setter for upper bound
98    // pub fn set_upper(&mut self, newu: T) {
99    // }
100
101    // Check if the range type is unknown
102    pub fn is_unknown(&self) -> bool {
103        self.rtype == RangeType::Unknown
104    }
105
106    // Set the range type to unknown
107    pub fn set_unknown(&mut self) {
108        self.rtype = RangeType::Unknown;
109    }
110
111    // Check if the range type is regular
112    pub fn is_regular(&self) -> bool {
113        self.rtype == RangeType::Regular
114    }
115
116    // Set the range type to regular
117    pub fn set_regular(&mut self) {
118        self.rtype = RangeType::Regular;
119    }
120
121    // Check if the range type is empty
122    pub fn is_empty(&self) -> bool {
123        self.rtype == RangeType::Empty
124    }
125
126    // Set the range type to empty
127    pub fn set_empty(&mut self) {
128        self.rtype = RangeType::Empty;
129    }
130    pub fn set_default(&mut self) {
131        self.rtype = RangeType::Regular;
132        self.range = Interval::new_closed_closed(T::min_value(), T::max_value());
133    }
134    pub fn add(&self, other: &Range<T>) -> Range<T> {
135        let a = self
136            .get_lower()
137            .clone()
138            .checked_add(&other.get_lower().clone())
139            .unwrap_or(T::max_value());
140
141        let b = self
142            .get_upper()
143            .clone()
144            .checked_add(&other.get_upper().clone())
145            .unwrap_or(T::max_value());
146
147        Range::new(a, b, RangeType::Regular)
148    }
149
150    pub fn sub(&self, other: &Range<T>) -> Range<T> {
151        let a = self
152            .get_lower()
153            .clone()
154            .checked_sub(&other.get_upper().clone())
155            .unwrap_or(T::min_value());
156
157        let b = self
158            .get_upper()
159            .clone()
160            .checked_sub(&other.get_lower().clone())
161            .unwrap_or(T::max_value());
162
163        Range::new(a, b, RangeType::Regular)
164    }
165
166    pub fn mul(&self, other: &Range<T>) -> Range<T> {
167        let candidates = vec![
168            self.get_lower().clone() * other.get_lower().clone(),
169            self.get_lower().clone() * other.get_upper().clone(),
170            self.get_upper().clone() * other.get_lower().clone(),
171            self.get_upper().clone() * other.get_upper().clone(),
172        ];
173        let min = candidates
174            .iter()
175            .cloned()
176            .min_by(|a, b| a.partial_cmp(b).unwrap())
177            .unwrap();
178        let max = candidates
179            .iter()
180            .cloned()
181            .max_by(|a, b| a.partial_cmp(b).unwrap())
182            .unwrap();
183        Range::new(min, max, RangeType::Regular)
184    }
185
186    pub fn intersectwith(&self, other: &Range<T>) -> Range<T> {
187        if self.is_unknown() {
188            return Range::new(
189                other.get_lower().clone(),
190                other.get_upper().clone(),
191                RangeType::Regular,
192            );
193        } else if other.is_unknown() {
194            return Range::new(
195                self.get_lower().clone(),
196                self.get_upper().clone(),
197                RangeType::Regular,
198            );
199        } else {
200            let result = self.range.clone().intersection(&other.range.clone());
201            let mut range = Range::default(T::min_value());
202
203            if let r = result {
204                range = Range::init(r);
205                range
206            } else {
207                range
208            }
209
210            // let left = std::cmp::max_by(self.get_lower(), other.get_lower(), |a, b| {
211            //     a.partial_cmp(b).unwrap()
212            // });
213            // let right = std::cmp::min_by(self.get_upper(), other.get_upper(), |a, b| {
214            //     a.partial_cmp(b).unwrap()
215            // });
216            // if left <= right {
217            //     Range::new(left.clone(), right.clone(), RangeType::Regular)
218            // } else {
219            //     let empty = T::min_value();
220            //     Range::new(empty.clone(), empty, RangeType::Empty)
221            // }
222        }
223    }
224    pub fn unionwith(&self, other: &Range<T>) -> Range<T> {
225        if self.is_unknown() {
226            return Range::new(
227                other.get_lower().clone(),
228                other.get_upper().clone(),
229                RangeType::Regular,
230            );
231        } else if other.is_unknown() {
232            return Range::new(
233                self.get_lower().clone(),
234                self.get_upper().clone(),
235                RangeType::Regular,
236            );
237        } else {
238            let left = std::cmp::min_by(self.get_lower(), other.get_lower(), |a, b| {
239                a.partial_cmp(b).unwrap()
240            });
241            let right = std::cmp::max_by(self.get_upper(), other.get_upper(), |a, b| {
242                a.partial_cmp(b).unwrap()
243            });
244            Range::new(left.clone(), right.clone(), RangeType::Regular)
245        }
246    }
247    // Check if the range is the maximum range
248    // pub fn is_max_range(&self) -> bool {
249    //     self.range.lower() == T::min_value() && self.range.upper() == T::max_value()
250    // }
251
252    // // Print the range
253    // pub fn print(&self) {
254    //     println!("Range: [{} - {}]", self.get_lower(), self.get_upper());
255    // }
256
257    // // Arithmetic and bitwise operations (example for addition)
258    // pub fn add(&self, other: &Range<T>) -> Range<T> {
259    //     let lower = self.get_lower() + other.get_lower();
260    //     let upper = self.get_upper() + other.get_upper();
261    //     Range::with_bounds(lower, upper, RangeType::Regular)
262    // }
263}
264
265// Implement the comparison operators
266pub struct Meet;
267
268impl Meet {
269    pub fn widen<'tcx, T: IntervalArithmetic + ConstConvert>(
270        op: &mut BasicOpKind<'tcx, T>,
271        constant_vector: &[T],
272        vars: &mut VarNodes<'tcx, T>,
273    ) -> bool {
274        // use crate::range_util::{get_first_less_from_vector, get_first_greater_from_vector};
275
276        // assert!(!constant_vector.is_empty(), "Invalid constant vector");
277
278        let old_interval = op.get_intersect().get_range().clone();
279        let new_interval = op.eval(vars);
280        let old_lower = old_interval.get_lower();
281        let old_upper = old_interval.get_upper();
282        let new_lower = new_interval.get_lower();
283        let new_upper = new_interval.get_upper();
284        let nlconstant = new_lower.clone();
285        let nuconstant = new_upper.clone();
286        let updated = if old_interval.is_unknown() {
287            new_interval
288        } else if new_lower < old_lower && new_upper > old_upper {
289            Range::new(nlconstant, nuconstant, RangeType::Regular)
290        } else if new_lower < old_lower {
291            Range::new(nlconstant, old_upper.clone(), RangeType::Regular)
292        } else if new_upper > old_upper {
293            Range::new(old_lower.clone(), nuconstant, RangeType::Regular)
294        } else {
295            old_interval.clone()
296        };
297
298        op.set_intersect(updated.clone());
299        let sink = op.get_sink();
300        let new_sink_interval = op.get_intersect().get_range().clone();
301        vars.get_mut(sink)
302            .unwrap()
303            .set_range(new_sink_interval.clone());
304        rap_trace!(
305            "WIDEN::{:?}: {:?} -> {:?}",
306            sink,
307            old_interval.range,
308            new_sink_interval
309        );
310        old_interval.range != new_sink_interval.range
311    }
312    pub fn narrow<'tcx, T: IntervalArithmetic + ConstConvert>(
313        op: &mut BasicOpKind<'tcx, T>,
314        vars: &mut VarNodes<'tcx, T>,
315    ) -> bool {
316        let old_range = vars[op.get_sink()].get_range();
317        let o_lower = old_range.get_lower().clone();
318        let o_upper = old_range.get_upper().clone();
319
320        let new_range = op.eval(vars);
321        let n_lower = new_range.get_lower().clone();
322        let n_upper = new_range.get_upper().clone();
323
324        let mut has_changed = false;
325        let min = T::min_value();
326        let max = T::max_value();
327
328        let mut result_lower = o_lower.clone();
329        let mut result_upper = o_upper.clone();
330
331        if o_lower == min && n_lower != min {
332            result_lower = n_lower;
333            has_changed = true;
334        } else {
335            // let smin = o_lower.clone().min(n_lower.clone());
336            let smin = T::min_value();
337            if o_lower != smin {
338                result_lower = smin;
339                has_changed = true;
340            }
341        }
342
343        if o_upper == max && n_upper != max {
344            result_upper = n_upper;
345            has_changed = true;
346        } else {
347            // let smax = o_upper.clone().max(n_upper.clone());
348            let smax = T::max_value();
349            if o_upper != smax {
350                result_upper = smax;
351                has_changed = true;
352            }
353        }
354
355        if has_changed {
356            let new_sink_range = Range::new(
357                result_lower.clone(),
358                result_upper.clone(),
359                RangeType::Regular,
360            );
361            let sink_node = vars.get_mut(op.get_sink()).unwrap();
362            sink_node.set_range(new_sink_range.clone());
363
364            // println!(
365            //     "NARROW::{}: {:?} -> {:?}",
366            // ,
367            //     Range::new(o_lower, o_upper),
368            //     new_sink_range
369            // );
370        }
371
372        has_changed
373    }
374}