logic/operators/
and.rs

1use super::error::BinaryError;
2use crate::{Formula, Metric};
3
4pub struct And<L, R> {
5    left: L,
6    right: R,
7}
8
9impl<L, R> And<L, R> {
10    pub fn new(left: L, right: R) -> And<L, R> {
11        And { left, right }
12    }
13}
14
15impl<T, L, R> Formula<T> for And<L, R>
16where
17    L: Formula<T>,
18    R: Formula<T>,
19{
20    type Error = BinaryError<L::Error, R::Error>;
21
22    fn satisfied_by(&self, value: &T) -> Result<bool, Self::Error> {
23        let left = self.left.satisfied_by(value).map_err(BinaryError::Left)?;
24        let right = self.right.satisfied_by(value).map_err(BinaryError::Right)?;
25
26        Ok(left && right)
27    }
28}
29
30impl<T, L, R> Metric<T> for And<L, R>
31where
32    L: Metric<T>,
33    R: Metric<T>,
34{
35    type Error = BinaryError<L::Error, R::Error>;
36
37    fn distance(&self, value: &T) -> Result<f64, Self::Error> {
38        // This method is derived from DeMorgan's Laws of Negation
39        // a /\ b === !(!a \/ !b)
40        // The operators are unrolled explicitly to improve performance
41
42        let left_dist = self.left.distance(value).map_err(BinaryError::Left)?;
43        let right_dist = self.right.distance(value).map_err(BinaryError::Right)?;
44
45        Ok(f64::min(left_dist, right_dist))
46    }
47}