Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/algebra/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ impl<F: Field> TypeInfo for F {
#[derive(MontConfig)]
#[modulus = "21888242871839275222246405745257275088548364400416034343698204186575808495617"]
#[generator = "5"]
#[small_subgroup_base = "3"]
#[small_subgroup_power = "2"]
pub struct BN254Config;
pub type Field256 = Fp256<MontBackend<BN254Config, 4>>;

Expand Down
5 changes: 4 additions & 1 deletion src/algebra/linear_form/covector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ impl<F: Field> LinearForm<F> for Covector<F> {
}

fn mle_evaluate(&self, point: &[F]) -> F {
multilinear_extend(&self.vector, point)
let k = self.vector.len().trailing_zeros() as usize;
let extra = point.len().saturating_sub(k);
let head_factor: F = point[..extra].iter().map(|p| F::ONE - *p).product::<F>();
head_factor * multilinear_extend(&self.vector, &point[extra..])
}

fn accumulate(&self, accumulator: &mut [F], scalar: F) {
Expand Down
7 changes: 5 additions & 2 deletions src/algebra/linear_form/multilinear_extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ impl<F: Field> LinearForm<F> for MultilinearExtension<F> {
}

fn mle_evaluate(&self, point: &[F]) -> F {
zip_strict(&self.point, point).fold(F::ONE, |acc, (&l, &r)| {
let extra = point.len().saturating_sub(self.point.len());
let head_factor: F = point[..extra].iter().map(|p| F::ONE - *p).product::<F>();
let eq_value = zip_strict(&self.point, &point[extra..]).fold(F::ONE, |acc, (&l, &r)| {
acc * (l * r + (F::ONE - l) * (F::ONE - r))
})
});
head_factor * eq_value
}

fn accumulate(&self, accumulator: &mut [F], scalar: F) {
Expand Down
50 changes: 44 additions & 6 deletions src/algebra/linear_form/univariate_evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,59 @@ impl<F: Field> UnivariateEvaluation<F> {
}
}

/// Lagrange basis polynomial L_index(point) on {0,1}^n (MSB-first).
fn lagrange_basis_single<F: Field>(point: &[F], index: usize) -> F {
let n = point.len();
point.iter().enumerate().fold(F::ONE, |acc, (j, &r)| {
if (index >> (n - 1 - j)) & 1 == 1 {
acc * r
} else {
acc * (F::ONE - r)
}
})
}

impl<F: Field> LinearForm<F> for UnivariateEvaluation<F> {
fn size(&self) -> usize {
self.size
}

fn mle_evaluate(&self, point: &[F]) -> F {
// Multilinear extension of (1, x, x^2, ..) = ⨂_i (1, x^2^i).
let k = self.size.trailing_zeros() as usize;
let extra = point.len().saturating_sub(k);

if extra == 0 {
// Power-of-2 path: MLE of (1, x, x^2, ..) = ⊗_i (1, x^{2^i}).
let mut x2i = self.point;
let mut result = F::ONE;
for &r in point.iter().rev() {
result *= (F::ONE - r) + r * x2i;
x2i.square_in_place();
}
return result;
}

// Smooth path: size = 2^k * odd where odd = 3^b * 13^c.
let odd = self.size >> k;
let leading = &point[..extra];
let trailing = &point[extra..];

let mut x2i = self.point;
let mut result = F::ONE;
for &r in point.iter().rev() {
// TODO: Why rev?
result *= (F::ONE - r) + r * x2i;
let mut inner = F::ONE;
for &r in trailing.iter().rev() {
inner *= (F::ONE - r) + r * x2i;
x2i.square_in_place();
}
result

let x_pow_2k = x2i;
let mut outer = F::ZERO;
let mut x_h = F::ONE;
for h in 0..odd {
outer += lagrange_basis_single(leading, h) * x_h;
x_h *= x_pow_2k;
}

outer * inner
}

/// See also [`Self::accumulate_many`] for a more efficient batched version.
Expand Down
Loading
Loading