lattices/
vec_union.rs
1use std::cmp::Ordering::{self, *};
2
3use cc_traits::Iter;
4
5use crate::{DeepReveal, IsBot, IsTop, LatticeFrom, LatticeOrd, Merge};
6
7#[derive(Clone, Debug, Eq)]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub struct VecUnion<Lat> {
17 vec: Vec<Lat>,
18}
19
20impl<Lat> VecUnion<Lat> {
21 pub fn new(vec: Vec<Lat>) -> Self {
23 Self { vec }
24 }
25
26 pub fn new_from(vec: impl Into<Vec<Lat>>) -> Self {
28 Self::new(vec.into())
29 }
30
31 pub fn as_reveal_ref(&self) -> &Vec<Lat> {
33 &self.vec
34 }
35
36 pub fn as_reveal_mut(&mut self) -> &mut Vec<Lat> {
38 &mut self.vec
39 }
40
41 pub fn into_reveal(self) -> Vec<Lat> {
43 self.vec
44 }
45}
46
47impl<Lat> DeepReveal for VecUnion<Lat>
48where
49 Lat: DeepReveal,
50{
51 type Revealed = Vec<Lat::Revealed>;
52
53 fn deep_reveal(self) -> Self::Revealed {
54 self.vec.into_iter().map(DeepReveal::deep_reveal).collect()
55 }
56}
57
58impl<Lat> Default for VecUnion<Lat> {
59 fn default() -> Self {
60 Self {
61 vec: Default::default(),
62 }
63 }
64}
65
66impl<LatSelf, LatOther> Merge<VecUnion<LatOther>> for VecUnion<LatSelf>
67where
68 LatSelf: Merge<LatOther> + LatticeFrom<LatOther>,
69{
70 fn merge(&mut self, mut other: VecUnion<LatOther>) -> bool {
71 let mut changed = false;
72 if self.vec.len() < other.vec.len() {
74 self.vec
75 .extend(other.vec.drain(self.vec.len()..).map(LatSelf::lattice_from));
76 changed = true;
77 }
78 for (self_val, other_val) in self.vec.iter_mut().zip(other.vec) {
80 changed |= self_val.merge(other_val);
81 }
82 changed
83 }
84}
85
86impl<LatSelf, LatOther> LatticeFrom<VecUnion<LatOther>> for VecUnion<LatSelf>
87where
88 LatSelf: LatticeFrom<LatOther>,
89{
90 fn lattice_from(other: VecUnion<LatOther>) -> Self {
91 Self::new(other.vec.into_iter().map(LatSelf::lattice_from).collect())
92 }
93}
94
95impl<LatSelf, LatOther> PartialEq<VecUnion<LatOther>> for VecUnion<LatSelf>
96where
97 LatSelf: PartialEq<LatOther>,
98{
99 fn eq(&self, other: &VecUnion<LatOther>) -> bool {
100 if self.vec.len() != other.vec.len() {
101 false
102 } else {
103 self.vec
104 .iter()
105 .zip(other.vec.iter())
106 .all(|(val_self, val_other)| val_self == val_other)
107 }
108 }
109}
110
111impl<LatSelf, LatOther> PartialOrd<VecUnion<LatOther>> for VecUnion<LatSelf>
112where
113 LatSelf: PartialOrd<LatOther>,
114{
115 fn partial_cmp(&self, other: &VecUnion<LatOther>) -> Option<Ordering> {
116 let (self_len, other_len) = (self.vec.len(), other.vec.len());
117 let mut self_any_greater = other_len < self_len;
118 let mut other_any_greater = self_len < other_len;
119 for (self_val, other_val) in self.vec.iter().zip(other.vec.iter()) {
120 match self_val.partial_cmp(other_val) {
121 None => {
122 return None;
123 }
124 Some(Less) => {
125 other_any_greater = true;
126 }
127 Some(Greater) => {
128 self_any_greater = true;
129 }
130 Some(Equal) => {}
131 }
132 if self_any_greater && other_any_greater {
133 return None;
134 }
135 }
136 match (self_any_greater, other_any_greater) {
137 (true, false) => Some(Greater),
138 (false, true) => Some(Less),
139 (false, false) => Some(Equal),
140 (true, true) => unreachable!(),
142 }
143 }
144}
145impl<LatSelf, LatOther> LatticeOrd<VecUnion<LatOther>> for VecUnion<LatSelf> where
146 Self: PartialOrd<VecUnion<LatOther>>
147{
148}
149
150impl<Lat> IsBot for VecUnion<Lat> {
151 fn is_bot(&self) -> bool {
152 self.vec.is_empty()
153 }
154}
155
156impl<Lat> IsTop for VecUnion<Lat> {
157 fn is_top(&self) -> bool {
158 false
159 }
160}
161
162#[cfg(test)]
163mod test {
164 use std::collections::HashSet;
165
166 use super::*;
167 use crate::Max;
168 use crate::set_union::SetUnionHashSet;
169 use crate::test::{cartesian_power, check_all};
170
171 #[test]
172 fn basic() {
173 let mut my_vec_a = VecUnion::<Max<usize>>::default();
174 let my_vec_b = VecUnion::new(vec![Max::new(9), Max::new(4), Max::new(5)]);
175 let my_vec_c = VecUnion::new(vec![Max::new(2), Max::new(5)]);
176
177 assert!(my_vec_a.merge(my_vec_b.clone()));
178 assert!(!my_vec_a.merge(my_vec_b));
179 assert!(my_vec_a.merge(my_vec_c.clone()));
180 assert!(!my_vec_a.merge(my_vec_c));
181 }
182
183 #[test]
184 fn consistency() {
185 let mut test_vec = vec![VecUnion::new(vec![] as Vec<SetUnionHashSet<_>>)];
186
187 let vals = [vec![], vec![0], vec![1], vec![0, 1]]
188 .map(HashSet::from_iter)
189 .map(SetUnionHashSet::new);
190
191 test_vec.extend(
192 cartesian_power::<_, 1>(&vals)
193 .map(|row| VecUnion::new(row.into_iter().cloned().collect())),
194 );
195 test_vec.extend(
196 cartesian_power::<_, 2>(&vals)
197 .map(|row| VecUnion::new(row.into_iter().cloned().collect())),
198 );
199
200 check_all(&test_vec);
201 }
202}