in air/src/air/divisor.rs [238:328]
fn constraint_divisor_equivalence() {
let n = 8_usize;
let g = BaseElement::get_root_of_unity(n.trailing_zeros());
let k = 4 as u32;
let j = n as u32 / k;
// ----- periodic assertion divisor, no offset --------------------------------------------
// create a divisor for assertion which repeats every 2 steps starting at step 0
let assertion = Assertion::periodic(0, 0, j as usize, BaseElement::ONE);
let divisor = ConstraintDivisor::from_assertion(&assertion, n);
// z(x) = x^4 - 1 = (x - 1) * (x - g^2) * (x - g^4) * (x - g^6)
let poly = polynom::mul(
&polynom::mul(
&[-BaseElement::ONE, BaseElement::ONE],
&[-g.exp(j.into()), BaseElement::ONE],
),
&polynom::mul(
&[-g.exp((2 * j).into()), BaseElement::ONE],
&[-g.exp((3 * j).into()), BaseElement::ONE],
),
);
for i in 0..n {
let expected = polynom::eval(&poly, g.exp((i as u32).into()));
let actual = divisor.evaluate_at(g.exp((i as u32).into()));
assert_eq!(expected, actual);
if i % (j as usize) == 0 {
assert_eq!(BaseElement::ZERO, actual);
}
}
// ----- periodic assertion divisor, with offset ------------------------------------------
// create a divisor for assertion which repeats every 2 steps starting at step 1
let offset = 1u32;
let assertion = Assertion::periodic(0, offset as usize, j as usize, BaseElement::ONE);
let divisor = ConstraintDivisor::from_assertion(&assertion, n);
assert_eq!(
ConstraintDivisor::new(vec![(k as usize, g.exp(k.into()))], vec![]),
divisor
);
// z(x) = x^4 - g^4 = (x - g) * (x - g^3) * (x - g^5) * (x - g^7)
let poly = polynom::mul(
&polynom::mul(
&[-g.exp(offset.into()), BaseElement::ONE],
&[-g.exp((offset + j).into()), BaseElement::ONE],
),
&polynom::mul(
&[-g.exp((offset + 2 * j).into()), BaseElement::ONE],
&[-g.exp((offset + 3 * j).into()), BaseElement::ONE],
),
);
for i in 0..n {
let expected = polynom::eval(&poly, g.exp((i as u32).into()));
let actual = divisor.evaluate_at(g.exp((i as u32).into()));
assert_eq!(expected, actual);
if i % (j as usize) == offset as usize {
assert_eq!(BaseElement::ZERO, actual);
}
}
// create a divisor for assertion which repeats every 4 steps starting at step 3
let offset = 3u32;
let k = 2 as u32;
let j = n as u32 / k;
let assertion = Assertion::periodic(0, offset as usize, j as usize, BaseElement::ONE);
let divisor = ConstraintDivisor::from_assertion(&assertion, n);
assert_eq!(
ConstraintDivisor::new(vec![(k as usize, g.exp((offset * k).into()))], vec![]),
divisor
);
// z(x) = x^2 - g^6 = (x - g^3) * (x - g^7)
let poly = polynom::mul(
&[-g.exp(offset.into()), BaseElement::ONE],
&[-g.exp((offset + j).into()), BaseElement::ONE],
);
for i in 0..n {
let expected = polynom::eval(&poly, g.exp((i as u32).into()));
let actual = divisor.evaluate_at(g.exp((i as u32).into()));
assert_eq!(expected, actual);
if i % (j as usize) == offset as usize {
assert_eq!(BaseElement::ZERO, actual);
}
}
}