use crate::{prelude::*, *};
use snarkvm_fields::PrimeField;
use snarkvm_utilities::dev_eprintln;
#[derive(Clone, Debug, Hash)]
pub struct Constraint<F: PrimeField>(
pub(crate) Scope,
pub(crate) LinearCombination<F>,
pub(crate) LinearCombination<F>,
pub(crate) LinearCombination<F>,
);
impl<F: PrimeField> Constraint<F> {
pub(crate) fn num_nonzeros(&self) -> (u64, u64, u64) {
let (a, b, c) = (&self.1, &self.2, &self.3);
(a.num_nonzeros(), b.num_nonzeros(), c.num_nonzeros())
}
pub(crate) fn is_satisfied(&self) -> bool {
let a = self.1.value();
let b = self.2.value();
let c = self.3.value();
let satisfied = a * b == c;
if !satisfied {
dev_eprintln!("Failed constraint at {scope}:\n\t({a} * {b}) != {c}", scope = self.0);
}
satisfied
}
pub fn to_terms(&self) -> (&LinearCombination<F>, &LinearCombination<F>, &LinearCombination<F>) {
(&self.1, &self.2, &self.3)
}
}
impl<F: PrimeField> Display for Constraint<F> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (scope, a, b, c) = (&self.0, &self.1, &self.2, &self.3);
let a = a.value();
let b = b.value();
let c = c.value();
match (a * b) == c {
true => write!(f, "Constraint {scope}:\n\t{a} * {b} == {c}\n"),
false => write!(f, "Constraint {scope}:\n\t{a} * {b} != {c} (Unsatisfied)\n"),
}
}
}