use super::traits::*;
impl<F> NumInputs for F
where
F: Fn(bool, bool) -> bool,
{
fn num_inputs(&self) -> usize {
2
}
}
impl<F> NumOutputs for F
where
F: Fn(bool, bool) -> bool,
{
fn num_outputs(&self) -> usize {
1
}
}
impl<F> PartialBooleanSystem for F
where
F: Fn(bool, bool) -> bool,
{
type LiteralId = usize;
type TermId = ();
fn evaluate_term_partial(&self, _term: &Self::TermId, input_values: &[bool]) -> Option<bool> {
Some((self)(input_values[0], input_values[1]))
}
}
impl<F> BooleanSystem for F
where
F: Fn(bool, bool) -> bool + PartialBooleanSystem<LiteralId = usize>,
{
fn evaluate_term(&self, _term: &Self::TermId, input_values: &[bool]) -> bool {
(self)(input_values[0], input_values[1])
}
}
pub struct NativeBooleanFunction<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize>
where
F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
{
f: F,
}
impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> From<F>
for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
where
F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
{
fn from(f: F) -> Self {
Self::new(f)
}
}
impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> StaticNumInputs<NUM_INPUTS>
for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
where
F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
{
}
impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> StaticNumOutputs<NUM_OUTPUTS>
for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
where
F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
{
}
impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize>
NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
where
F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
{
pub fn new(f: F) -> Self {
Self { f }
}
}
impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> NumInputs
for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
where
F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
{
fn num_inputs(&self) -> usize {
NUM_INPUTS
}
}
impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> NumOutputs
for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
where
F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
{
fn num_outputs(&self) -> usize {
NUM_OUTPUTS
}
}
impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> PartialBooleanSystem
for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
where
F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
{
type LiteralId = usize;
type TermId = usize;
fn evaluate_term_partial(&self, term: &Self::TermId, input_values: &[bool]) -> Option<bool> {
Some(self.evaluate_term(term, input_values))
}
}
impl<F, const NUM_INPUTS: usize, const NUM_OUTPUTS: usize> BooleanSystem
for NativeBooleanFunction<F, NUM_INPUTS, NUM_OUTPUTS>
where
F: Fn([bool; NUM_INPUTS]) -> [bool; NUM_OUTPUTS],
{
fn evaluate_term(&self, term: &Self::TermId, input_values: &[bool]) -> bool {
let mut inputs = [false; NUM_INPUTS];
(0..NUM_INPUTS).for_each(|i| inputs[i] = input_values[i]);
(self.f)(inputs)[*term]
}
}
#[test]
fn test_2x2_function() {
let f = |a: bool, b: bool| -> bool { a ^ b };
let result = f.evaluate_term(&(), &[true, true]);
assert_eq!(result, false);
}
#[test]
fn test_evaluate_nary_function() {
let f = NativeBooleanFunction::new(|[a, b, c]| [a ^ b ^ c]);
let result = f.evaluate_term(&0, &[true, true, true]);
assert_eq!(result, true);
}