libreda_logic/
adaptors.rs

1// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5//! Adaptors for Boolean functions.
6
7use crate::traits::*;
8
9/// Wrap a multi-output Boolean function by selecting a single output.
10/// # Example
11/// ```
12/// use libreda_logic::traits::*;
13/// use libreda_logic::native_boolean_functions::*;
14/// use libreda_logic::adaptors::*;
15///
16/// fn f([a]: [bool; 1]) -> [bool; 2] {
17///     [a, !a]   
18/// }
19///
20/// // Wrap the native Rust function such that it implements the traits of Boolean functions.
21/// let f2 = NativeBooleanFunction::new(f);
22///
23/// // Select the first output.
24/// let f_0 = OutputSelection::new(&f2, 0);
25///
26/// // Select the second output.
27/// let f_1 = OutputSelection::new(&f2, 1);
28///
29/// assert_eq!(f_0.eval(&[false]), false);
30/// assert_eq!(f_0.eval(&[true]), true);
31///
32/// assert_eq!(f_1.eval(&[false]), true);
33/// assert_eq!(f_1.eval(&[true]), false);
34/// ```
35pub struct OutputSelection<'a, T, TermId> {
36    s: &'a T,
37    output: TermId,
38}
39
40impl<'a, T: BooleanSystem> OutputSelection<'a, T, T::TermId> {
41    /// Create a boolean function by selecting a single output.
42    pub fn new(boolean_system: &'a T, output: T::TermId) -> Self {
43        Self {
44            s: boolean_system,
45            output,
46        }
47    }
48}
49
50impl<'a, T: NumInputs, TermId> NumInputs for OutputSelection<'a, T, TermId> {
51    fn num_inputs(&self) -> usize {
52        self.s.num_inputs()
53    }
54}
55
56impl<'a, T: NumOutputs, TermId> NumOutputs for OutputSelection<'a, T, TermId> {
57    fn num_outputs(&self) -> usize {
58        self.s.num_outputs()
59    }
60}
61
62impl<'a, T: PartialBooleanSystem> PartialBooleanSystem for OutputSelection<'a, T, T::TermId> {
63    type LiteralId = T::LiteralId;
64
65    type TermId = ();
66
67    fn evaluate_term_partial(&self, _term: &Self::TermId, input_values: &[bool]) -> Option<bool> {
68        self.s.evaluate_term_partial(&self.output, input_values)
69    }
70}
71
72impl<'a, T: BooleanSystem> BooleanSystem for OutputSelection<'a, T, T::TermId> {
73    fn evaluate_term(&self, _term: &Self::TermId, input_values: &[bool]) -> bool {
74        self.s.evaluate_term(&self.output, input_values)
75    }
76}
77
78impl<'a, T, TermId> StaticNumOutputs<1> for OutputSelection<'a, T, TermId> {}
79
80impl<'a, T: PartialBooleanSystem> PartialBooleanFunction for OutputSelection<'a, T, T::TermId> {
81    fn partial_eval(&self, input_values: &[bool]) -> Option<bool> {
82        self.evaluate_term_partial(&(), input_values)
83    }
84}
85
86impl<'a, T: BooleanSystem> BooleanFunction for OutputSelection<'a, T, T::TermId> {
87    fn eval(&self, input_values: &[bool]) -> bool {
88        self.evaluate_term(&(), input_values)
89    }
90}