sp1_recursion_core/air/
is_ext_zero.rsuse crate::air::Block;
use p3_air::AirBuilder;
use p3_field::{
extension::{BinomialExtensionField, BinomiallyExtendable},
AbstractField, Field,
};
use sp1_derive::AlignedBorrow;
use sp1_stark::air::{BinomialExtension, SP1AirBuilder};
use crate::air::extension::BinomialExtensionUtils;
use crate::runtime::D;
#[derive(AlignedBorrow, Default, Debug, Clone, Copy)]
#[repr(C)]
pub struct IsExtZeroOperation<T> {
pub inverse: Block<T>,
pub result: T,
}
impl<F: Field + BinomiallyExtendable<D>> IsExtZeroOperation<F> {
pub fn populate(&mut self, a: Block<F>) -> F {
let a = BinomialExtensionField::<F, D>::from_block(a);
let (inverse, result) = if a.is_zero() {
(BinomialExtensionField::zero(), F::one())
} else {
(a.inverse(), F::zero())
};
self.inverse = inverse.as_block();
self.result = result;
let prod = inverse * a;
debug_assert!(prod == BinomialExtensionField::<F, D>::one() || prod.is_zero());
result
}
}
impl<F: Field> IsExtZeroOperation<F> {
pub fn eval<AB: SP1AirBuilder>(
builder: &mut AB,
a: BinomialExtension<AB::Expr>,
cols: IsExtZeroOperation<AB::Var>,
is_real: AB::Expr,
) {
builder.assert_bool(is_real.clone());
builder.when(is_real.clone()).assert_bool(cols.result);
let one_ext = BinomialExtension::<AB::Expr>::from_base(AB::Expr::one());
let inverse = cols.inverse.as_extension::<AB>();
let is_zero = one_ext.clone() - inverse * a.clone();
let result_ext = BinomialExtension::<AB::Expr>::from_base(cols.result.into());
for (eq_z, res) in is_zero.into_iter().zip(result_ext.0) {
builder.when(is_real.clone()).assert_eq(eq_z, res);
}
builder.when(is_real.clone()).assert_bool(cols.result);
for x in a {
builder.when(is_real.clone()).when(cols.result).assert_zero(x.clone());
}
}
}