1use crate::algebra::Algebra;
20use crate::bits::TriBit;
21use crate::value::Ternary;
22
23#[derive(Debug, thiserror::Error)]
25#[error("TriVec 长度不匹配:{left} vs {right}")]
26pub struct ShapeError {
27 pub left: usize,
29 pub right: usize,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
35pub enum TriVecError {
36 #[error("位平面不足以覆盖 {len} 位:需要 {need} words,实际 {actual}")]
38 PlaneTooSmall {
39 len: usize,
41 need: usize,
43 actual: usize,
45 },
46 #[error("索引 {index} 越界(len={len})")]
48 IndexOutOfRange {
49 index: usize,
51 len: usize,
53 },
54 #[error("字索引 {word} 越界(words={words})")]
56 WordOutOfRange {
57 word: usize,
59 words: usize,
61 },
62}
63
64#[derive(Debug, Clone)]
69pub struct TriVec {
70 len: usize,
71 ones: Vec<u64>,
72 unknowns: Option<Vec<u64>>,
73}
74
75impl PartialEq for TriVec {
76 fn eq(&self, other: &Self) -> bool {
77 if self.len != other.len {
78 return false;
79 }
80 for (w, ones) in self.ones.iter().enumerate() {
81 let left = self.unknowns.as_ref().map_or(0, |p| p[w]);
82 let right = other.unknowns.as_ref().map_or(0, |p| p[w]);
83 if *ones != other.ones[w] || left != right {
84 return false;
85 }
86 }
87 true
88 }
89}
90
91impl Eq for TriVec {}
92
93impl TriVec {
94 pub fn from_binary(ones: Vec<u64>, len: usize) -> Self {
102 Self::try_from_binary(ones, len).unwrap_or_else(|e| panic!("{e}"))
103 }
104
105 pub fn try_from_binary(mut ones: Vec<u64>, len: usize) -> Result<Self, TriVecError> {
107 let need = len.div_ceil(64);
108 if ones.len() < need {
109 return Err(TriVecError::PlaneTooSmall {
110 len,
111 need,
112 actual: ones.len(),
113 });
114 }
115 ones.truncate(need);
116 if let Some(last) = ones.last_mut() {
117 *last &= last_mask(len);
118 }
119 Ok(Self {
120 len,
121 ones,
122 unknowns: None,
123 })
124 }
125
126 pub fn from_bools(bits: &[bool]) -> Self {
128 let mut ones = vec![0u64; bits.len().div_ceil(64)];
129 for (i, &bit) in bits.iter().enumerate() {
130 if bit {
131 ones[i / 64] |= 1u64 << (i % 64);
132 }
133 }
134 Self {
135 len: bits.len(),
136 ones,
137 unknowns: None,
138 }
139 }
140
141 pub fn from_ternary(values: &[Ternary]) -> Self {
143 let mut ones = vec![0u64; values.len().div_ceil(64)];
144 let mut unknowns: Option<Vec<u64>> = None;
145 for (i, &value) in values.iter().enumerate() {
146 match value {
147 Ternary::False => {}
148 Ternary::True => ones[i / 64] |= 1u64 << (i % 64),
149 Ternary::Unknown => {
150 let planes = unknowns.get_or_insert_with(|| vec![0u64; ones.len()]);
151 planes[i / 64] |= 1u64 << (i % 64);
152 }
153 }
154 }
155 Self {
156 len: values.len(),
157 ones,
158 unknowns,
159 }
160 }
161
162 pub fn to_bools(&self) -> Option<Vec<bool>> {
164 if !self.is_binary() {
165 return None;
166 }
167 let mut out = Vec::with_capacity(self.len);
168 for i in 0..self.len {
169 out.push(self.get(i).is_true());
170 }
171 Some(out)
172 }
173
174 pub fn len(&self) -> usize {
176 self.len
177 }
178
179 pub fn is_empty(&self) -> bool {
181 self.len == 0
182 }
183
184 pub fn words(&self) -> usize {
186 self.ones.len()
187 }
188
189 pub fn is_binary(&self) -> bool {
191 self.unknowns
192 .as_ref()
193 .is_none_or(|planes| planes.iter().all(|&w| w == 0))
194 }
195
196 pub fn ones(&self) -> &[u64] {
198 &self.ones
199 }
200
201 pub fn unknowns(&self) -> Option<&[u64]> {
203 self.unknowns.as_deref()
204 }
205
206 pub fn get(&self, i: usize) -> Ternary {
212 self.try_get(i).unwrap_or_else(|e| panic!("{e}"))
213 }
214
215 pub fn try_get(&self, i: usize) -> Result<Ternary, TriVecError> {
217 if i >= self.len {
218 return Err(TriVecError::IndexOutOfRange {
219 index: i,
220 len: self.len,
221 });
222 }
223 let ones = (self.ones[i / 64] >> (i % 64)) & 1;
224 let unknowns = self
225 .unknowns
226 .as_ref()
227 .map_or(0, |planes| (planes[i / 64] >> (i % 64)) & 1);
228 Ok(match (ones, unknowns) {
229 (1, 0) => Ternary::True,
230 (0, 1) => Ternary::Unknown,
231 _ => Ternary::False,
232 })
233 }
234
235 pub fn set(&mut self, i: usize, value: Ternary) {
241 self.try_set(i, value).unwrap_or_else(|e| panic!("{e}"));
242 }
243
244 pub fn try_set(&mut self, i: usize, value: Ternary) -> Result<(), TriVecError> {
246 if i >= self.len {
247 return Err(TriVecError::IndexOutOfRange {
248 index: i,
249 len: self.len,
250 });
251 }
252 let word = i / 64;
253 let bit = 1u64 << (i % 64);
254 let mut cleared_last_unknown = false;
255 match value {
256 Ternary::False => {
257 self.ones[word] &= !bit;
258 if let Some(planes) = &mut self.unknowns {
259 planes[word] &= !bit;
260 cleared_last_unknown = planes.iter().all(|w| *w == 0);
261 }
262 }
263 Ternary::True => {
264 self.ones[word] |= bit;
265 if let Some(planes) = &mut self.unknowns {
266 planes[word] &= !bit;
267 cleared_last_unknown = planes.iter().all(|w| *w == 0);
268 }
269 }
270 Ternary::Unknown => {
271 let planes = self
272 .unknowns
273 .get_or_insert_with(|| vec![0u64; self.ones.len()]);
274 planes[word] |= bit;
275 self.ones[word] &= !bit;
276 }
277 }
278 if cleared_last_unknown {
279 self.unknowns = None;
280 }
281 Ok(())
282 }
283
284 pub fn count_unknowns(&self) -> usize {
286 self.unknowns.as_ref().map_or(0, |planes| {
287 planes.iter().map(|w| w.count_ones() as usize).sum()
288 })
289 }
290
291 pub fn word(&self, word: usize) -> TriBit {
297 self.try_word(word).unwrap_or_else(|e| panic!("{e}"))
298 }
299
300 pub fn try_word(&self, word: usize) -> Result<TriBit, TriVecError> {
302 if word >= self.ones.len() {
303 return Err(TriVecError::WordOutOfRange {
304 word,
305 words: self.ones.len(),
306 });
307 }
308 Ok(TriBit {
309 ones: crate::bits::BitPlane(self.ones[word]),
310 unknowns: crate::bits::BitPlane(
311 self.unknowns.as_ref().map_or(0, |planes| planes[word]),
312 ),
313 })
314 }
315
316 pub fn not(&mut self) {
318 let mask = last_mask(self.len);
319 for (w, ones) in self.ones.iter_mut().enumerate() {
320 let x = self.unknowns.as_ref().map_or(0, |planes| planes[w]);
321 *ones = !(*ones | x) & mask_of(w, self.len, mask);
322 }
323 }
324
325 pub fn and_assign(&mut self, other: &Self, alg: Algebra) -> Result<(), ShapeError> {
327 self.check_shape(other)?;
328 let mask = last_mask(self.len);
329 let both_binary = self.unknowns.is_none() && other.unknowns.is_none();
330 let mut new_unknowns = if both_binary {
331 None
332 } else {
333 Some(Vec::with_capacity(self.ones.len()))
334 };
335 for w in 0..self.ones.len() {
336 let o1 = self.ones[w];
337 let o2 = other.ones[w];
338 let x1 = self.unknowns.as_ref().map_or(0, |p| p[w]);
339 let x2 = other.unknowns.as_ref().map_or(0, |p| p[w]);
340 let m = mask_of(w, self.len, mask);
341 let (o, x) = match alg {
342 Algebra::Bochvar => {
343 let x_out = (x1 | x2) & m;
344 ((o1 & o2) & !x_out & m, x_out)
345 }
346 Algebra::Kleene | Algebra::Lukasiewicz => {
347 let f1 = !o1 & !x1;
348 let f2 = !o2 & !x2;
349 let o_out = (o1 & o2) & m;
350 let f_out = (f1 | f2) & m;
351 (o_out, !(o_out | f_out) & m)
352 }
353 };
354 self.ones[w] = o;
355 if let Some(planes) = &mut new_unknowns {
356 planes.push(x);
357 }
358 }
359 match new_unknowns {
360 Some(planes) => self.replace_unknowns(planes),
361 None => self.unknowns = None,
362 }
363 Ok(())
364 }
365
366 pub fn or_assign(&mut self, other: &Self, alg: Algebra) -> Result<(), ShapeError> {
368 self.check_shape(other)?;
369 let mask = last_mask(self.len);
370 let both_binary = self.unknowns.is_none() && other.unknowns.is_none();
371 let mut new_unknowns = if both_binary {
372 None
373 } else {
374 Some(Vec::with_capacity(self.ones.len()))
375 };
376 for w in 0..self.ones.len() {
377 let o1 = self.ones[w];
378 let o2 = other.ones[w];
379 let x1 = self.unknowns.as_ref().map_or(0, |p| p[w]);
380 let x2 = other.unknowns.as_ref().map_or(0, |p| p[w]);
381 let m = mask_of(w, self.len, mask);
382 let (o, x) = match alg {
383 Algebra::Bochvar => {
384 let x_out = (x1 | x2) & m;
385 ((o1 | o2) & !x_out & m, x_out)
386 }
387 Algebra::Kleene | Algebra::Lukasiewicz => {
388 let f1 = !o1 & !x1;
389 let f2 = !o2 & !x2;
390 let o_out = (o1 | o2) & m;
391 let f_out = (f1 & f2) & m;
392 (o_out, !(o_out | f_out) & m)
393 }
394 };
395 self.ones[w] = o;
396 if let Some(planes) = &mut new_unknowns {
397 planes.push(x);
398 }
399 }
400 match new_unknowns {
401 Some(planes) => self.replace_unknowns(planes),
402 None => self.unknowns = None,
403 }
404 Ok(())
405 }
406
407 fn replace_unknowns(&mut self, planes: Vec<u64>) {
408 if planes.iter().all(|&w| w == 0) {
409 self.unknowns = None;
410 } else {
411 self.unknowns = Some(planes);
412 }
413 }
414
415 fn check_shape(&self, other: &Self) -> Result<(), ShapeError> {
416 if self.len == other.len {
417 Ok(())
418 } else {
419 Err(ShapeError {
420 left: self.len,
421 right: other.len,
422 })
423 }
424 }
425}
426
427fn last_mask(len: usize) -> u64 {
428 match len % 64 {
429 0 => u64::MAX,
430 r => (1u64 << r) - 1,
431 }
432}
433
434fn mask_of(word: usize, len: usize, last: u64) -> u64 {
435 let words = len.div_ceil(64);
436 if word + 1 == words { last } else { u64::MAX }
437}
438
439#[cfg(test)]
440mod tests {
441 use super::*;
442
443 fn sample(len: usize, seed: u64) -> Vec<Ternary> {
444 let mut x = seed;
445 (0..len)
446 .map(|_| {
447 x = x.wrapping_mul(6364136223846793005).wrapping_add(1);
448 match (x >> 32) % 3 {
449 0 => Ternary::False,
450 1 => Ternary::True,
451 _ => Ternary::Unknown,
452 }
453 })
454 .collect()
455 }
456
457 #[test]
458 fn binary_view_is_zero_copy_and_roundtrips() {
459 for len in [0usize, 1, 63, 64, 65, 130] {
460 let bits: Vec<bool> = (0..len).map(|i| i % 3 == 0).collect();
461 let v = TriVec::from_bools(&bits);
462 assert_eq!(v.unknowns(), None);
463 assert!(v.is_binary());
464 assert_eq!(v.to_bools().unwrap(), bits);
465 let words = v.ones().to_vec();
466 let moved = TriVec::from_binary(words, len);
467 assert_eq!(moved.to_bools().unwrap(), bits);
468 }
469 }
470
471 #[test]
472 fn from_binary_normalizes_oversized_planes() {
473 let normalized = TriVec::from_binary(vec![0, 0], 1);
474 assert_eq!(normalized.words(), 1);
475 assert_eq!(normalized, TriVec::from_binary(vec![0], 1));
476
477 let masked = TriVec::from_binary(vec![u64::MAX], 3);
479 assert_eq!(masked.to_bools().unwrap(), vec![true, true, true]);
480
481 let mut left = TriVec::from_binary(vec![1, 0], 1);
483 let right = TriVec::from_binary(vec![1], 1);
484 left.and_assign(&right, Algebra::Kleene).unwrap();
485 assert_eq!(left.to_bools().unwrap(), vec![true]);
486 }
487
488 #[test]
489 fn unknown_allocates_lazily() {
490 let mut v = TriVec::from_bools(&[true, false]);
491 assert_eq!(v.unknowns(), None);
492 v.set(1, Ternary::Unknown);
493 assert!(v.unknowns().is_some());
494 assert_eq!(v.get(1), Ternary::Unknown);
495 assert_eq!(v.to_bools(), None);
496 assert_eq!(v.count_unknowns(), 1);
497 }
498
499 #[test]
500 fn bit_ops_match_scalar() {
501 for alg in Algebra::ALL {
502 let a = sample(130, 7);
503 let b = sample(130, 11);
504 let mut va = TriVec::from_ternary(&a);
505 let vb = TriVec::from_ternary(&b);
506 va.and_assign(&vb, alg).unwrap();
507 for i in 0..a.len() {
508 assert_eq!(va.get(i), alg.and(a[i], b[i]), "{alg:?} and at {i}");
509 }
510 let mut va = TriVec::from_ternary(&a);
511 va.or_assign(&vb, alg).unwrap();
512 for i in 0..a.len() {
513 assert_eq!(va.get(i), alg.or(a[i], b[i]), "{alg:?} or at {i}");
514 }
515 }
516 }
517
518 #[test]
519 fn not_matches_scalar() {
520 let a = sample(96, 3);
521 let mut v = TriVec::from_ternary(&a);
522 v.not();
523 for (i, &value) in a.iter().enumerate() {
524 assert_eq!(v.get(i), Algebra::Kleene.not(value), "not at {i}");
525 }
526 }
527
528 #[test]
529 fn shape_mismatch_is_an_error() {
530 let mut a = TriVec::from_bools(&[true, false]);
531 let b = TriVec::from_bools(&[true]);
532 assert!(a.and_assign(&b, Algebra::Kleene).is_err());
533 }
534
535 #[test]
536 fn eq_compares_values_not_storage() {
537 let mut a = TriVec::from_ternary(&[Ternary::Unknown]);
538 assert!(a.unknowns().is_some());
539 a.set(0, Ternary::False);
540 assert_eq!(a.unknowns(), None);
542 assert_eq!(a, TriVec::from_bools(&[false]));
543 assert_ne!(a, TriVec::from_bools(&[true]));
544 assert_ne!(
546 TriVec::from_ternary(&[Ternary::Unknown]),
547 TriVec::from_bools(&[false])
548 );
549 }
550
551 #[test]
552 fn fallible_constructors_and_accessors_report_bounds() {
553 assert_eq!(
554 TriVec::try_from_binary(vec![], 1).unwrap_err(),
555 TriVecError::PlaneTooSmall {
556 len: 1,
557 need: 1,
558 actual: 0
559 }
560 );
561 let v = TriVec::from_bools(&[true]);
562 assert_eq!(
563 v.try_get(1).unwrap_err(),
564 TriVecError::IndexOutOfRange { index: 1, len: 1 }
565 );
566 assert_eq!(
567 v.try_word(1).unwrap_err(),
568 TriVecError::WordOutOfRange { word: 1, words: 1 }
569 );
570 let mut w = v.clone();
571 assert!(w.try_set(1, Ternary::False).is_err());
572 assert_eq!(w, v);
573 }
574}