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::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() -> Term {
let state = Rc::new(RefCell::new(Term::empty()));
{
let n = 10;
let xs = vec![Var::new(state.clone(), Bit); 2 * n];
let (zs, _cout) = ripple_carry_adder(state.clone(), &xs[..n], &xs[n..]);
let sources: Vec<NodeId> = xs.into_iter().map(|x| x.new_source()).collect();
let targets: Vec<NodeId> = zs.into_iter().map(|x| x.new_target()).collect();
let mut term = state.borrow_mut();
term.sources = sources;
term.targets = targets;
}
println!("reference count: {:?}", Rc::strong_count(&state));
Rc::try_unwrap(state).unwrap().into_inner()
}
fn xor() -> Term {
let state = Rc::new(RefCell::new(Term::empty()));
{
let xs = vec![Var::new(state.clone(), Bit); 2];
let y = xs[0].clone() ^ xs[1].clone();
state.borrow_mut().sources = vec![xs[0].new_source(), xs[1].new_source()];
state.borrow_mut().targets = vec![y.new_target()];
}
Rc::try_unwrap(state).unwrap().into_inner()
}
fn main() {
let _xor_term = xor();
let adder_term = n_bit_adder();
println!("{:?}", adder_term);
}