Skip to content

Commit

Permalink
chore: better placement of mul_with_witness
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench committed Jul 24, 2023
1 parent b25c7d0 commit 92a42a3
Showing 1 changed file with 45 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,51 +109,6 @@ impl GeneratedAcir {
pub(crate) fn push_return_witness(&mut self, witness: Witness) {
self.return_witnesses.push(witness);
}

/// Returns an expression which represents `lhs * rhs`
///
/// If one has multiplicative term and the other is of degree one or more,
/// the function creates [intermediate variables][`Witness`] accordingly.
/// There are two cases where we can optimize the multiplication between two expressions:
/// 1. If both expressions have at most a total degree of 1 in each term, then we can just multiply them
/// as each term in the result will be degree-2.
/// 2. If one expression is a constant, then we can just multiply the constant with the other expression
///
/// (1) is because an [`Expression`] can hold at most a degree-2 univariate polynomial
/// which is what you get when you multiply two degree-1 univariate polynomials.
pub(crate) fn mul_with_witness(&mut self, lhs: &Expression, rhs: &Expression) -> Expression {
use std::borrow::Cow;
let lhs_is_linear = lhs.is_linear();
let rhs_is_linear = rhs.is_linear();

// Case 1: Both expressions have at most a total degree of 1 in each term
if lhs_is_linear && rhs_is_linear {
return (lhs * rhs)
.expect("one of the expressions is a constant and so this should not fail");
}

// Case 2: One or both of the sides needs to be reduced to a degree-1 univariate polynomial
let lhs_reduced = if lhs_is_linear {
Cow::Borrowed(lhs)
} else {
Cow::Owned(self.get_or_create_witness(lhs).into())
};

// If the lhs and rhs are the same, then we do not need to reduce
// rhs, we only need to square the lhs.
if lhs == rhs {
return (&*lhs_reduced * &*lhs_reduced)
.expect("Both expressions are reduced to be degree<=1");
};

let rhs_reduced = if rhs_is_linear {
Cow::Borrowed(rhs)
} else {
Cow::Owned(self.get_or_create_witness(rhs).into())
};

(&*lhs_reduced * &*rhs_reduced).expect("Both expressions are reduced to be degree<=1")
}
}

impl GeneratedAcir {
Expand Down Expand Up @@ -383,6 +338,51 @@ impl GeneratedAcir {
lhs.add_mul(FieldElement::from(2_i128), &inter.unwrap())
}

/// Returns an expression which represents `lhs * rhs`
///
/// If one has multiplicative term and the other is of degree one or more,
/// the function creates [intermediate variables][`Witness`] accordingly.
/// There are two cases where we can optimize the multiplication between two expressions:
/// 1. If both expressions have at most a total degree of 1 in each term, then we can just multiply them
/// as each term in the result will be degree-2.
/// 2. If one expression is a constant, then we can just multiply the constant with the other expression
///
/// (1) is because an [`Expression`] can hold at most a degree-2 univariate polynomial
/// which is what you get when you multiply two degree-1 univariate polynomials.
pub(crate) fn mul_with_witness(&mut self, lhs: &Expression, rhs: &Expression) -> Expression {
use std::borrow::Cow;
let lhs_is_linear = lhs.is_linear();
let rhs_is_linear = rhs.is_linear();

// Case 1: Both expressions have at most a total degree of 1 in each term
if lhs_is_linear && rhs_is_linear {
return (lhs * rhs)
.expect("one of the expressions is a constant and so this should not fail");
}

// Case 2: One or both of the sides needs to be reduced to a degree-1 univariate polynomial
let lhs_reduced = if lhs_is_linear {
Cow::Borrowed(lhs)
} else {
Cow::Owned(self.get_or_create_witness(lhs).into())
};

// If the lhs and rhs are the same, then we do not need to reduce
// rhs, we only need to square the lhs.
if lhs == rhs {
return (&*lhs_reduced * &*lhs_reduced)
.expect("Both expressions are reduced to be degree<=1");
};

let rhs_reduced = if rhs_is_linear {
Cow::Borrowed(rhs)
} else {
Cow::Owned(self.get_or_create_witness(rhs).into())
};

(&*lhs_reduced * &*rhs_reduced).expect("Both expressions are reduced to be degree<=1")
}

/// Signed division lhs / rhs
/// We derive the signed division from the unsigned euclidian division.
/// note that this is not euclidian division!
Expand Down

0 comments on commit 92a42a3

Please sign in to comment.