libreda_logic/
native_boolean_functions.rs1use super::traits::*;
8
9impl<F> NumInputs for F
10where
11 F: Fn(bool, bool) -> bool,
12{
13 fn num_inputs(&self) -> usize {
14 2
15 }
16}
17impl<F> NumOutputs for F
18where
19 F: Fn(bool, bool) -> bool,
20{
21 fn num_outputs(&self) -> usize {
22 1
23 }
24}
25impl<F> PartialBooleanSystem for F
27where
28 F: Fn(bool, bool) -> bool,
29{
30 type LiteralId = usize;
31
32 type TermId = ();
33
34 fn evaluate_term_partial(&self, _term: &Self::TermId, input_values: &[bool]) -> Option<bool> {
35 Some((self)(input_values[0], input_values[1]))
36 }
37}
38
39impl<F> BooleanSystem for F
41where
42 F: Fn(bool, bool) -> bool + PartialBooleanSystem<LiteralId = usize>,
43{
44 fn evaluate_term(&self, _term: &Self::TermId, input_values: &[bool]) -> bool {
45 (self)(input_values[0], input_values[1])
46 }
47}
48
49pub struct NativeBooleanFunction<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize>
74where
75 F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
76{
77 f: F,
78}
79
80impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> From<F>
81 for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
82where
83 F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
84{
85 fn from(f: F) -> Self {
86 Self::new(f)
87 }
88}
89
90impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> StaticNumInputs<NUM_INPUTS>
91 for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
92where
93 F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
94{
95}
96
97impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> StaticNumOutputs<NUM_OUTPUTS>
98 for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
99where
100 F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
101{
102}
103
104impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize>
105 NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
106where
107 F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
108{
109 pub fn new(f: F) -> Self {
121 Self { f }
122 }
123}
124
125impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> NumInputs
126 for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
127where
128 F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
129{
130 fn num_inputs(&self) -> usize {
131 NUM_INPUTS
132 }
133}
134
135impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> NumOutputs
136 for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
137where
138 F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
139{
140 fn num_outputs(&self) -> usize {
141 NUM_OUTPUTS
142 }
143}
144
145impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> PartialBooleanSystem
146 for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
147where
148 F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
149{
150 type LiteralId = usize;
151
152 type TermId = usize;
153
154 fn evaluate_term_partial(&self, term: &Self::TermId, input_values: &[bool]) -> Option<bool> {
155 Some(self.evaluate_term(term, input_values))
156 }
157}
158
159impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> BooleanSystem
160 for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
161where
162 F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
163{
164 fn evaluate_term(&self, term: &Self::TermId, input_values: &[bool]) -> bool {
165 let mut inputs = [false; NUM_INPUTS];
166 (0..NUM_INPUTS).for_each(|i| inputs[i] = input_values[i]);
168 (self.f)(inputs)[*term]
169 }
170}
171
172#[test]
173fn test_2x2_function() {
174 let f = |a: bool, b: bool| -> bool { a ^ b };
175
176 let result = f.evaluate_term(&(), &[true, true]);
177
178 assert_eq!(result, false);
179}
180
181#[test]
182fn test_evaluate_nary_function() {
183 let f = NativeBooleanFunction::new(|[a, b, c]| [a ^ b ^ c]);
184 let result = f.evaluate_term(&0, &[true, true, true]);
185 assert_eq!(result, true);
186}