Add iterative version of count_variables_add
This commit is contained in:
parent
019d8104ca
commit
7080e382e1
1 changed files with 262 additions and 225 deletions
487
src/r1cs.rs
487
src/r1cs.rs
|
@ -9,139 +9,6 @@ use absy::*;
|
|||
use absy::Expression::*;
|
||||
use field::Field;
|
||||
|
||||
/// Returns a `HashMap` containing variables and the number of occurences
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `expr` - Expression only containing Numbers, Variables, Add and Mult
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// `7 * x + 4 * y + x` -> { x => 8, y = 4 }
|
||||
fn count_variables_add<T: Field>(expr: &Expression<T>) -> HashMap<String, T> {
|
||||
let mut count = HashMap::new();
|
||||
match expr.clone() {
|
||||
NumberLiteral(x) => { count.insert("~one".to_string(), x); },
|
||||
VariableReference(var) => { count.insert(var, T::one()); },
|
||||
Mult(box NumberLiteral(x1), box NumberLiteral(x2)) => { count.insert("~one".to_string(), x1 * x2); },
|
||||
Mult(box NumberLiteral(x), box VariableReference(var)) |
|
||||
Mult(box VariableReference(var), box NumberLiteral(x)) => { count.insert(var, x); },
|
||||
Add(box lhs, box rhs) => {
|
||||
match (lhs, rhs) {
|
||||
(NumberLiteral(x), NumberLiteral(y)) => {
|
||||
let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
*num = num.clone() + x + y;
|
||||
},
|
||||
(VariableReference(v), NumberLiteral(x)) |
|
||||
(NumberLiteral(x), VariableReference(v)) => {
|
||||
{
|
||||
let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
*num = num.clone() + x;
|
||||
}
|
||||
let var = count.entry(v).or_insert(T::zero());
|
||||
*var = var.clone() + T::one();
|
||||
},
|
||||
(VariableReference(v1), VariableReference(v2)) => {
|
||||
{
|
||||
let var1 = count.entry(v1).or_insert(T::zero());
|
||||
*var1 = var1.clone() + T::one();
|
||||
}
|
||||
let var2 = count.entry(v2).or_insert(T::zero());
|
||||
*var2 = var2.clone() + T::one();
|
||||
},
|
||||
(NumberLiteral(x), e @ Add(..)) |
|
||||
(e @ Add(..), NumberLiteral(x)) => {
|
||||
{
|
||||
let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
*num = num.clone() + x;
|
||||
}
|
||||
let vars = count_variables_add(&e);
|
||||
for (key, value) in &vars {
|
||||
let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
*val = val.clone() + value;
|
||||
}
|
||||
},
|
||||
(VariableReference(v), e @ Add(..)) |
|
||||
(e @ Add(..), VariableReference(v)) => {
|
||||
{
|
||||
let var = count.entry(v).or_insert(T::zero());
|
||||
*var = var.clone() + T::one();
|
||||
}
|
||||
let vars = count_variables_add(&e);
|
||||
for (key, value) in &vars {
|
||||
let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
*val = val.clone() + value;
|
||||
}
|
||||
},
|
||||
(NumberLiteral(x), Mult(box NumberLiteral(n), box VariableReference(v))) |
|
||||
(NumberLiteral(x), Mult(box VariableReference(v), box NumberLiteral(n))) |
|
||||
(Mult(box NumberLiteral(n), box VariableReference(v)), NumberLiteral(x)) |
|
||||
(Mult(box VariableReference(v), box NumberLiteral(n)), NumberLiteral(x)) => {
|
||||
{
|
||||
let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
*num = num.clone() + x;
|
||||
}
|
||||
let var = count.entry(v).or_insert(T::zero());
|
||||
*var = var.clone() + n;
|
||||
},
|
||||
(VariableReference(v1), Mult(box NumberLiteral(n), box VariableReference(v2))) |
|
||||
(VariableReference(v1), Mult(box VariableReference(v2), box NumberLiteral(n))) |
|
||||
(Mult(box NumberLiteral(n), box VariableReference(v2)), VariableReference(v1)) |
|
||||
(Mult(box VariableReference(v2), box NumberLiteral(n)), VariableReference(v1)) => {
|
||||
{
|
||||
let var = count.entry(v1).or_insert(T::zero());
|
||||
*var = var.clone() + T::one();
|
||||
}
|
||||
let var = count.entry(v2).or_insert(T::zero());
|
||||
*var = var.clone() + n;
|
||||
},
|
||||
(e @ Add(..), Mult(box NumberLiteral(n), box VariableReference(v))) |
|
||||
(e @ Add(..), Mult(box VariableReference(v), box NumberLiteral(n))) |
|
||||
(Mult(box NumberLiteral(n), box VariableReference(v)), e @ Add(..)) |
|
||||
(Mult(box VariableReference(v), box NumberLiteral(n)), e @ Add(..)) => {
|
||||
{
|
||||
let var = count.entry(v).or_insert(T::zero());
|
||||
*var = var.clone() + n;
|
||||
}
|
||||
let vars = count_variables_add(&e);
|
||||
for (key, value) in &vars {
|
||||
let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
*val = val.clone() + value;
|
||||
}
|
||||
},
|
||||
(Mult(box NumberLiteral(n1), box VariableReference(v1)), Mult(box NumberLiteral(n2), box VariableReference(v2))) |
|
||||
(Mult(box VariableReference(v1), box NumberLiteral(n1)), Mult(box NumberLiteral(n2), box VariableReference(v2))) |
|
||||
(Mult(box NumberLiteral(n1), box VariableReference(v1)), Mult(box VariableReference(v2), box NumberLiteral(n2))) |
|
||||
(Mult(box VariableReference(v1), box NumberLiteral(n1)), Mult(box VariableReference(v2), box NumberLiteral(n2))) => {
|
||||
{
|
||||
let var = count.entry(v1).or_insert(T::zero());
|
||||
*var = var.clone() + n1;
|
||||
}
|
||||
let var = count.entry(v2).or_insert(T::zero());
|
||||
*var = var.clone() + n2;
|
||||
},
|
||||
(e1 @ Add(..), e2 @ Add(..)) => {
|
||||
{
|
||||
let vars = count_variables_add(&e1);
|
||||
for (key, value) in &vars {
|
||||
let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
*val = val.clone() + value;
|
||||
}
|
||||
}
|
||||
let vars = count_variables_add(&e2);
|
||||
for (key, value) in &vars {
|
||||
let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
*val = val.clone() + value;
|
||||
}
|
||||
}
|
||||
e @ _ => panic!("Error: unexpected Add({}, {})", e.0, e.1),
|
||||
}
|
||||
},
|
||||
e @ _ => panic!("Statement::Add/Mult[linear] expected, got: {}", e),
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
/// Returns a vector of summands of the given `Expression`.
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -161,9 +28,7 @@ fn get_summands<T: Field>(expr: &Expression<T>) -> Vec<&Expression<T>> {
|
|||
ref e @ NumberLiteral(_) |
|
||||
ref e @ VariableReference(_) |
|
||||
ref e @ Mult(..) |
|
||||
ref e @ Sub(..) if e.is_linear() => {
|
||||
add.push(e);
|
||||
},
|
||||
ref e @ Sub(..) if e.is_linear() => add.push(e),
|
||||
Add(ref l, ref r) => {
|
||||
trace.push(l);
|
||||
trace.push(r);
|
||||
|
@ -176,6 +41,43 @@ fn get_summands<T: Field>(expr: &Expression<T>) -> Vec<&Expression<T>> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns a `HashMap` containing variables and the number of occurences
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `expr` - Expression only containing Numbers, Variables, Add and Mult
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// `7 * x + 4 * y + x` -> { x => 8, y = 4 }
|
||||
fn count_variables_add<T: Field>(expr: &Expression<T>) -> HashMap<String, T> {
|
||||
let summands = get_summands(expr);
|
||||
let mut count = HashMap::new();
|
||||
for s in summands {
|
||||
match *s {
|
||||
NumberLiteral(ref x) => {
|
||||
let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
*num = num.clone() + x;
|
||||
},
|
||||
VariableReference(ref v) => {
|
||||
let num = count.entry(v.to_string()).or_insert(T::zero());
|
||||
*num = num.clone() + T::one();
|
||||
},
|
||||
Mult(box NumberLiteral(ref x1), box NumberLiteral(ref x2)) => {
|
||||
let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
*num = num.clone() + x1 + x2;
|
||||
},
|
||||
Mult(box NumberLiteral(ref x), box VariableReference(ref v)) |
|
||||
Mult(box VariableReference(ref v), box NumberLiteral(ref x)) => {
|
||||
let num = count.entry(v.to_string()).or_insert(T::zero());
|
||||
*num = num.clone() + x;
|
||||
},
|
||||
ref e => panic!("Not covered: {}", e),
|
||||
}
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
/// Returns an equotation equivalent to `lhs == rhs` only using `Add` and `Mult`
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -188,7 +90,7 @@ fn swap_sub<T: Field>(lhs: &Expression<T>, rhs: &Expression<T>) -> (Expression<T
|
|||
let mut run = true;
|
||||
while run {
|
||||
run = false;
|
||||
for mut i in 0..left.len() {
|
||||
for i in 0..left.len() {
|
||||
match *left[i] {
|
||||
ref e @ NumberLiteral(_) |
|
||||
ref e @ VariableReference(_) |
|
||||
|
@ -202,7 +104,7 @@ fn swap_sub<T: Field>(lhs: &Expression<T>, rhs: &Expression<T>) -> (Expression<T
|
|||
ref e => panic!("Unexpected: {}", e),
|
||||
}
|
||||
}
|
||||
for mut i in 0..right.len() {
|
||||
for i in 0..right.len() {
|
||||
match *right[i] {
|
||||
ref e @ NumberLiteral(_) |
|
||||
ref e @ VariableReference(_) |
|
||||
|
@ -228,93 +130,6 @@ fn swap_sub<T: Field>(lhs: &Expression<T>, rhs: &Expression<T>) -> (Expression<T
|
|||
panic!("Unexpected");
|
||||
}
|
||||
|
||||
/// Returns an equotation equivalent to `lhs == rhs` only using `Add` and `Mult`
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `lhs` - Leht hand side of the equotation
|
||||
/// * `rhs` - Right hand side of the equotation
|
||||
// fn swap_sub_recursive<T: Field>(lhs: &Expression<T>, rhs: &Expression<T>) -> (Expression<T>, Expression<T>) {
|
||||
// // assert that Mult on lhs or rhs is linear!
|
||||
// match (lhs.clone(), rhs.clone()) {
|
||||
// // recursion end
|
||||
// (v1 @ NumberLiteral(_), v2 @ NumberLiteral(_)) |
|
||||
// (v1 @ VariableReference(_), v2 @ NumberLiteral(_)) |
|
||||
// (v1 @ NumberLiteral(_), v2 @ VariableReference(_)) |
|
||||
// (v1 @ VariableReference(_), v2 @ VariableReference(_)) |
|
||||
// (v1 @ VariableReference(_), v2 @ Mult(..)) |
|
||||
// (v1 @ Mult(..), v2 @ VariableReference(_)) |
|
||||
// (v1 @ NumberLiteral(_), v2 @ Mult(..)) |
|
||||
// (v1 @ Mult(..), v2 @ NumberLiteral(_)) |
|
||||
// (v1 @ Mult(..), v2 @ Mult(..)) => {
|
||||
// assert!(v1.is_linear());
|
||||
// assert!(v2.is_linear());
|
||||
// (v1, v2)
|
||||
// },
|
||||
// // Num/Var/Mult = Add
|
||||
// (v @ NumberLiteral(_), Add(left, right)) |
|
||||
// (v @ VariableReference(_), Add(left, right)) |
|
||||
// (v @ Mult(..), Add(left, right)) => {
|
||||
// assert!(v.is_linear());
|
||||
// let (l1, r1) = swap_sub(&v, &left);
|
||||
// let (l2, r2) = swap_sub(&l1, &right);
|
||||
// (l2, Add(box r1, box r2))
|
||||
// },
|
||||
// // Add = Num/Var/Mult
|
||||
// (Add(left, right), v @ NumberLiteral(_)) |
|
||||
// (Add(left, right), v @ VariableReference(_)) |
|
||||
// (Add(left, right), v @ Mult(..)) => { // v = left + right
|
||||
// assert!(v.is_linear());
|
||||
// let (l1, r1) = swap_sub(&left, &v);
|
||||
// let (l2, r2) = swap_sub(&right, &r1);
|
||||
// (Add(box l1, box l2), r2)
|
||||
// },
|
||||
// // Sub = Var/Num/Mult
|
||||
// (Sub(box left, box right), v @ VariableReference(_)) |
|
||||
// (Sub(box left, box right), v @ NumberLiteral(_)) |
|
||||
// (Sub(box left, box right), v @ Mult(..)) => {
|
||||
// assert!(v.is_linear());
|
||||
// let (l, r) = swap_sub(&left, &right);
|
||||
// (l, Add(box v, box r))
|
||||
// },
|
||||
// // Var/Num/Mult = Sub
|
||||
// (v @ VariableReference(_), Sub(box left, box right)) |
|
||||
// (v @ NumberLiteral(_), Sub(box left, box right)) |
|
||||
// (v @ Mult(..), Sub(box left, box right)) => {
|
||||
// assert!(v.is_linear());
|
||||
// let (l, r) = swap_sub(&left, &right);
|
||||
// (Add(box v, box r), l)
|
||||
// },
|
||||
// // Add = Add
|
||||
// (Add(box left1, box right1), Add(box left2, box right2)) => {
|
||||
// let (l1, r1) = swap_sub(&left1, &left2);
|
||||
// let (l2, r2) = swap_sub(&right1, &right2);
|
||||
// (Add(box l1, box l2), Add(box r1, box r2))
|
||||
// },
|
||||
// // Sub = Add
|
||||
// (Sub(box left_s, box right_s), Add(box left_a, box right_a)) => {
|
||||
// let (l1, r1) = swap_sub(&left_s, &right_s);
|
||||
// let (l2, r2) = swap_sub(&l1, &left_a);
|
||||
// let (l3, r3) = swap_sub(&l2, &right_a);
|
||||
// (l3, Add(box r1, box Add(box r2, box r3)))
|
||||
// },
|
||||
// // Add = Sub
|
||||
// (Add(box left_a, box right_a), Sub(box left_s, box right_s)) => {
|
||||
// let (l1, r1) = swap_sub(&left_s, &right_s);
|
||||
// let (l2, r2) = swap_sub(&l1, &left_a);
|
||||
// let (l3, r3) = swap_sub(&l2, &right_a);
|
||||
// (Add(box r1, box Add(box r2, box r3)), l3)
|
||||
// },
|
||||
// // Sub = Sub
|
||||
// (Sub(box l1, box r1), Sub(l2, r2)) => {
|
||||
// let (lhs1, rhs1) = swap_sub(&l1, &r1);
|
||||
// let (lhs2, rhs2) = swap_sub(&l2, &r2);
|
||||
// (Add(box lhs1, box rhs2), Add(box lhs2, box rhs1))
|
||||
// },
|
||||
// e @ _ => panic!("Input not covered: {} = {}", e.0, e.1),
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Calculates one R1CS row representation for `linear_expr` = `expr`.
|
||||
/// (<A,x>*<B,c> = <C,x>)
|
||||
///
|
||||
|
@ -647,3 +462,225 @@ mod tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// old recursive implementations
|
||||
|
||||
// /// Returns a `HashMap` containing variables and the number of occurences
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `expr` - Expression only containing Numbers, Variables, Add and Mult
|
||||
// ///
|
||||
// /// # Example
|
||||
// ///
|
||||
// /// `7 * x + 4 * y + x` -> { x => 8, y = 4 }
|
||||
// fn count_variables_add<T: Field>(expr: &Expression<T>) -> HashMap<String, T> {
|
||||
// let mut count = HashMap::new();
|
||||
// match expr.clone() {
|
||||
// NumberLiteral(x) => { count.insert("~one".to_string(), x); },
|
||||
// VariableReference(var) => { count.insert(var, T::one()); },
|
||||
// Mult(box NumberLiteral(x1), box NumberLiteral(x2)) => { count.insert("~one".to_string(), x1 * x2); },
|
||||
// Mult(box NumberLiteral(x), box VariableReference(var)) |
|
||||
// Mult(box VariableReference(var), box NumberLiteral(x)) => { count.insert(var, x); },
|
||||
// Add(box lhs, box rhs) => {
|
||||
// match (lhs, rhs) {
|
||||
// (NumberLiteral(x), NumberLiteral(y)) => {
|
||||
// let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
// *num = num.clone() + x + y;
|
||||
// },
|
||||
// (VariableReference(v), NumberLiteral(x)) |
|
||||
// (NumberLiteral(x), VariableReference(v)) => {
|
||||
// {
|
||||
// let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
// *num = num.clone() + x;
|
||||
// }
|
||||
// let var = count.entry(v).or_insert(T::zero());
|
||||
// *var = var.clone() + T::one();
|
||||
// },
|
||||
// (VariableReference(v1), VariableReference(v2)) => {
|
||||
// {
|
||||
// let var1 = count.entry(v1).or_insert(T::zero());
|
||||
// *var1 = var1.clone() + T::one();
|
||||
// }
|
||||
// let var2 = count.entry(v2).or_insert(T::zero());
|
||||
// *var2 = var2.clone() + T::one();
|
||||
// },
|
||||
// (NumberLiteral(x), e @ Add(..)) |
|
||||
// (e @ Add(..), NumberLiteral(x)) => {
|
||||
// {
|
||||
// let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
// *num = num.clone() + x;
|
||||
// }
|
||||
// let vars = count_variables_add(&e);
|
||||
// for (key, value) in &vars {
|
||||
// let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
// *val = val.clone() + value;
|
||||
// }
|
||||
// },
|
||||
// (VariableReference(v), e @ Add(..)) |
|
||||
// (e @ Add(..), VariableReference(v)) => {
|
||||
// {
|
||||
// let var = count.entry(v).or_insert(T::zero());
|
||||
// *var = var.clone() + T::one();
|
||||
// }
|
||||
// let vars = count_variables_add(&e);
|
||||
// for (key, value) in &vars {
|
||||
// let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
// *val = val.clone() + value;
|
||||
// }
|
||||
// },
|
||||
// (NumberLiteral(x), Mult(box NumberLiteral(n), box VariableReference(v))) |
|
||||
// (NumberLiteral(x), Mult(box VariableReference(v), box NumberLiteral(n))) |
|
||||
// (Mult(box NumberLiteral(n), box VariableReference(v)), NumberLiteral(x)) |
|
||||
// (Mult(box VariableReference(v), box NumberLiteral(n)), NumberLiteral(x)) => {
|
||||
// {
|
||||
// let num = count.entry("~one".to_string()).or_insert(T::zero());
|
||||
// *num = num.clone() + x;
|
||||
// }
|
||||
// let var = count.entry(v).or_insert(T::zero());
|
||||
// *var = var.clone() + n;
|
||||
// },
|
||||
// (VariableReference(v1), Mult(box NumberLiteral(n), box VariableReference(v2))) |
|
||||
// (VariableReference(v1), Mult(box VariableReference(v2), box NumberLiteral(n))) |
|
||||
// (Mult(box NumberLiteral(n), box VariableReference(v2)), VariableReference(v1)) |
|
||||
// (Mult(box VariableReference(v2), box NumberLiteral(n)), VariableReference(v1)) => {
|
||||
// {
|
||||
// let var = count.entry(v1).or_insert(T::zero());
|
||||
// *var = var.clone() + T::one();
|
||||
// }
|
||||
// let var = count.entry(v2).or_insert(T::zero());
|
||||
// *var = var.clone() + n;
|
||||
// },
|
||||
// (e @ Add(..), Mult(box NumberLiteral(n), box VariableReference(v))) |
|
||||
// (e @ Add(..), Mult(box VariableReference(v), box NumberLiteral(n))) |
|
||||
// (Mult(box NumberLiteral(n), box VariableReference(v)), e @ Add(..)) |
|
||||
// (Mult(box VariableReference(v), box NumberLiteral(n)), e @ Add(..)) => {
|
||||
// {
|
||||
// let var = count.entry(v).or_insert(T::zero());
|
||||
// *var = var.clone() + n;
|
||||
// }
|
||||
// let vars = count_variables_add(&e);
|
||||
// for (key, value) in &vars {
|
||||
// let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
// *val = val.clone() + value;
|
||||
// }
|
||||
// },
|
||||
// (Mult(box NumberLiteral(n1), box VariableReference(v1)), Mult(box NumberLiteral(n2), box VariableReference(v2))) |
|
||||
// (Mult(box VariableReference(v1), box NumberLiteral(n1)), Mult(box NumberLiteral(n2), box VariableReference(v2))) |
|
||||
// (Mult(box NumberLiteral(n1), box VariableReference(v1)), Mult(box VariableReference(v2), box NumberLiteral(n2))) |
|
||||
// (Mult(box VariableReference(v1), box NumberLiteral(n1)), Mult(box VariableReference(v2), box NumberLiteral(n2))) => {
|
||||
// {
|
||||
// let var = count.entry(v1).or_insert(T::zero());
|
||||
// *var = var.clone() + n1;
|
||||
// }
|
||||
// let var = count.entry(v2).or_insert(T::zero());
|
||||
// *var = var.clone() + n2;
|
||||
// },
|
||||
// (e1 @ Add(..), e2 @ Add(..)) => {
|
||||
// {
|
||||
// let vars = count_variables_add(&e1);
|
||||
// for (key, value) in &vars {
|
||||
// let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
// *val = val.clone() + value;
|
||||
// }
|
||||
// }
|
||||
// let vars = count_variables_add(&e2);
|
||||
// for (key, value) in &vars {
|
||||
// let val = count.entry(key.to_string()).or_insert(T::zero());
|
||||
// *val = val.clone() + value;
|
||||
// }
|
||||
// }
|
||||
// e @ _ => panic!("Error: unexpected Add({}, {})", e.0, e.1),
|
||||
// }
|
||||
// },
|
||||
// e @ _ => panic!("Statement::Add/Mult[linear] expected, got: {}", e),
|
||||
// }
|
||||
// count
|
||||
// }
|
||||
|
||||
// /// Returns an equotation equivalent to `lhs == rhs` only using `Add` and `Mult`
|
||||
// ///
|
||||
// /// # Arguments
|
||||
// ///
|
||||
// /// * `lhs` - Leht hand side of the equotation
|
||||
// /// * `rhs` - Right hand side of the equotation
|
||||
// fn swap_sub_recursive<T: Field>(lhs: &Expression<T>, rhs: &Expression<T>) -> (Expression<T>, Expression<T>) {
|
||||
// // assert that Mult on lhs or rhs is linear!
|
||||
// match (lhs.clone(), rhs.clone()) {
|
||||
// // recursion end
|
||||
// (v1 @ NumberLiteral(_), v2 @ NumberLiteral(_)) |
|
||||
// (v1 @ VariableReference(_), v2 @ NumberLiteral(_)) |
|
||||
// (v1 @ NumberLiteral(_), v2 @ VariableReference(_)) |
|
||||
// (v1 @ VariableReference(_), v2 @ VariableReference(_)) |
|
||||
// (v1 @ VariableReference(_), v2 @ Mult(..)) |
|
||||
// (v1 @ Mult(..), v2 @ VariableReference(_)) |
|
||||
// (v1 @ NumberLiteral(_), v2 @ Mult(..)) |
|
||||
// (v1 @ Mult(..), v2 @ NumberLiteral(_)) |
|
||||
// (v1 @ Mult(..), v2 @ Mult(..)) => {
|
||||
// assert!(v1.is_linear());
|
||||
// assert!(v2.is_linear());
|
||||
// (v1, v2)
|
||||
// },
|
||||
// // Num/Var/Mult = Add
|
||||
// (v @ NumberLiteral(_), Add(left, right)) |
|
||||
// (v @ VariableReference(_), Add(left, right)) |
|
||||
// (v @ Mult(..), Add(left, right)) => {
|
||||
// assert!(v.is_linear());
|
||||
// let (l1, r1) = swap_sub(&v, &left);
|
||||
// let (l2, r2) = swap_sub(&l1, &right);
|
||||
// (l2, Add(box r1, box r2))
|
||||
// },
|
||||
// // Add = Num/Var/Mult
|
||||
// (Add(left, right), v @ NumberLiteral(_)) |
|
||||
// (Add(left, right), v @ VariableReference(_)) |
|
||||
// (Add(left, right), v @ Mult(..)) => { // v = left + right
|
||||
// assert!(v.is_linear());
|
||||
// let (l1, r1) = swap_sub(&left, &v);
|
||||
// let (l2, r2) = swap_sub(&right, &r1);
|
||||
// (Add(box l1, box l2), r2)
|
||||
// },
|
||||
// // Sub = Var/Num/Mult
|
||||
// (Sub(box left, box right), v @ VariableReference(_)) |
|
||||
// (Sub(box left, box right), v @ NumberLiteral(_)) |
|
||||
// (Sub(box left, box right), v @ Mult(..)) => {
|
||||
// assert!(v.is_linear());
|
||||
// let (l, r) = swap_sub(&left, &right);
|
||||
// (l, Add(box v, box r))
|
||||
// },
|
||||
// // Var/Num/Mult = Sub
|
||||
// (v @ VariableReference(_), Sub(box left, box right)) |
|
||||
// (v @ NumberLiteral(_), Sub(box left, box right)) |
|
||||
// (v @ Mult(..), Sub(box left, box right)) => {
|
||||
// assert!(v.is_linear());
|
||||
// let (l, r) = swap_sub(&left, &right);
|
||||
// (Add(box v, box r), l)
|
||||
// },
|
||||
// // Add = Add
|
||||
// (Add(box left1, box right1), Add(box left2, box right2)) => {
|
||||
// let (l1, r1) = swap_sub(&left1, &left2);
|
||||
// let (l2, r2) = swap_sub(&right1, &right2);
|
||||
// (Add(box l1, box l2), Add(box r1, box r2))
|
||||
// },
|
||||
// // Sub = Add
|
||||
// (Sub(box left_s, box right_s), Add(box left_a, box right_a)) => {
|
||||
// let (l1, r1) = swap_sub(&left_s, &right_s);
|
||||
// let (l2, r2) = swap_sub(&l1, &left_a);
|
||||
// let (l3, r3) = swap_sub(&l2, &right_a);
|
||||
// (l3, Add(box r1, box Add(box r2, box r3)))
|
||||
// },
|
||||
// // Add = Sub
|
||||
// (Add(box left_a, box right_a), Sub(box left_s, box right_s)) => {
|
||||
// let (l1, r1) = swap_sub(&left_s, &right_s);
|
||||
// let (l2, r2) = swap_sub(&l1, &left_a);
|
||||
// let (l3, r3) = swap_sub(&l2, &right_a);
|
||||
// (Add(box r1, box Add(box r2, box r3)), l3)
|
||||
// },
|
||||
// // Sub = Sub
|
||||
// (Sub(box l1, box r1), Sub(l2, r2)) => {
|
||||
// let (lhs1, rhs1) = swap_sub(&l1, &r1);
|
||||
// let (lhs2, rhs2) = swap_sub(&l2, &r2);
|
||||
// (Add(box lhs1, box rhs2), Add(box lhs2, box rhs1))
|
||||
// },
|
||||
// e @ _ => panic!("Input not covered: {} = {}", e.0, e.1),
|
||||
// }
|
||||
// }
|
||||
|
|
Loading…
Reference in a new issue