use open_hypergraphs::lax::var;
use open_hypergraphs::lax::*;
#[derive(PartialEq, Clone, Debug)]
pub struct Bit;
#[derive(PartialEq, Clone, Debug)]
pub enum Gate {
Not,
Xor,
Zero, Or,
And,
One,
Copy, }
impl var::HasVar for Gate {
fn var() -> Gate {
Gate::Copy
}
}
impl var::HasBitXor<Bit, Gate> for Gate {
fn bitxor(_: Bit, _: Bit) -> (Bit, Gate) {
(Bit, Gate::Xor)
}
}
impl var::HasBitAnd<Bit, Gate> for Gate {
fn bitand(_: Bit, _: Bit) -> (Bit, Gate) {
(Bit, Gate::And)
}
}
impl var::HasBitOr<Bit, Gate> for Gate {
fn bitor(_: Bit, _: Bit) -> (Bit, Gate) {
(Bit, Gate::Or)
}
}
impl var::HasNot<Bit, Gate> for Gate {
fn not(_: Bit) -> (Bit, Gate) {
(Bit, Gate::Not)
}
}
use std::cell::RefCell;
use std::rc::Rc;
type Term = OpenHypergraph<Bit, Gate>;
type Builder = Rc<RefCell<Term>>;
type Var = var::Var<Bit, Gate>;
fn zero(state: Builder) -> Var {
var::fn_operation(&state, &[], Bit, Gate::Zero)
}
fn full_adder(a: Var, b: Var, cin: Var) -> (Var, Var) {
let a_xor_b = a.clone() ^ b.clone();
let sum = a_xor_b.clone() ^ cin.clone();
let cout = (a & b) | (cin & a_xor_b.clone());
(sum, cout)
}
fn ripple_carry_adder(state: Builder, a: &[Var], b: &[Var]) -> (Vec<Var>, Var) {
let n = a.len();
assert_eq!(n, b.len(), "Input bit arrays must have the same length");
let mut sum = Vec::with_capacity(n);
let mut carry = zero(state);
for i in 0..n {
let (s, c) = full_adder(a[i].clone(), b[i].clone(), carry);
sum.push(s);
carry = c;
}
(sum, carry)
}
fn n_bit_adder(n: usize) -> Term {
var::build(|state| {
let xs = (0..2 * n)
.map(|_| Var::new(state.clone(), Bit))
.collect::<Vec<_>>();
let (mut zs, cout) = ripple_carry_adder(state.clone(), &xs[..n], &xs[n..]);
zs.push(cout);
(xs, zs)
})
.unwrap()
}
fn xor() -> Term {
var::build(|state| {
let xs = vec![Var::new(state.clone(), Bit); 2];
let y = xs[0].clone() ^ xs[1].clone();
(xs, vec![y])
})
.unwrap()
}
fn main() {
let _xor_term = xor();
let adder_term = n_bit_adder(8);
println!("{:?}", adder_term);
}