Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sumcheck macro #823

Merged
merged 16 commits into from
Jan 22, 2025
Merged

Sumcheck macro #823

merged 16 commits into from
Jan 22, 2025

Conversation

zemse
Copy link
Collaborator

@zemse zemse commented Jan 14, 2025

Issue #788.

Currently, the step 2 in the sumcheck prover has manual implementations for degree 1, 2 & 3. This requires manual implementation for degree 4.

  • This PR adds a macro that generates boilerplate for sumcheck degree to prevent boilerplate code
  • Add support for degree 4 and 5
  • Activate tests that were ignored

Code generation

Using cargo expand

code for degree 3
let _result: AdditiveArray<_, 4> = {
    let product_access = |_| &self.poly.flattened_ml_extensions[0];
    let f1 = product_access(0usize);
    let f2 = product_access(1usize);
    let f3 = product_access(2usize);
    let (f1, f2, f3) = match (
        &f1.evaluations(),
        &f2.evaluations(),
        &f3.evaluations(),
    ) {
        (FieldType::Base(_), FieldType::Ext(_), FieldType::Ext(_)) => {
            (f2, f3, f1)
        }
        (FieldType::Ext(_), FieldType::Base(_), FieldType::Ext(_)) => {
            (f1, f3, f2)
        }
        (FieldType::Base(_), FieldType::Base(_), FieldType::Ext(_)) => {
            (f3, f1, f2)
        }
        (FieldType::Base(_), FieldType::Ext(_), FieldType::Base(_)) => {
            (f2, f1, f3)
        }
        _ => (f1, f2, f3),
    };
    match (&f1.evaluations(), &f2.evaluations(), &f3.evaluations()) {
        (FieldType::Ext(v1), FieldType::Ext(v2), FieldType::Ext(v3)) => {
            let v1 = if let Some((start, offset)) = f1.evaluations_range() {
                &v1[start..][..offset]
            } else {
                &v1[..]
            };
            let v2 = if let Some((start, offset)) = f2.evaluations_range() {
                &v2[start..][..offset]
            } else {
                &v2[..]
            };
            let v3 = if let Some((start, offset)) = f3.evaluations_range() {
                &v3[start..][..offset]
            } else {
                &v3[..]
            };
            let res = (0..largest_even_below(v1.len()))
                .step_by(2)
                .rev()
                .map(|b| {
                    let c1_0 = v1[b + 1] - v1[b];
                    let c1_1 = c1_0 + c1_0;
                    let c2_0 = v2[b + 1] - v2[b];
                    let c2_1 = c2_0 + c2_0;
                    let c3_0 = v3[b + 1] - v3[b];
                    let c3_1 = c3_0 + c3_0;
                    AdditiveArray([
                        ((v1[b]) * (v2[b])) * (v3[b]),
                        ((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1]),
                        ((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                            * (c3_0 + v3[b + 1]),
                        ((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                            * (c3_1 + v3[b + 1]),
                    ])
                })
                .sum::<AdditiveArray<_, 4usize>>();
            let res = if v1.len() == 1 {
                let b = 0;
                AdditiveArray::<
                    _,
                    4usize,
                >([((v1[b]) * (v2[b])) * (v3[b]); 4usize])
            } else {
                res
            };
            let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                - (ceil_log2(v1.len()).max(1) + self.round - 1);
            if num_vars_multiplicity > 0 {
                AdditiveArray(
                    res
                        .0
                        .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                )
            } else {
                res
            }
        }
        (FieldType::Ext(v1), FieldType::Ext(v2), FieldType::Base(v3)) => {
            let v1 = if let Some((start, offset)) = f1.evaluations_range() {
                &v1[start..][..offset]
            } else {
                &v1[..]
            };
            let v2 = if let Some((start, offset)) = f2.evaluations_range() {
                &v2[start..][..offset]
            } else {
                &v2[..]
            };
            let v3 = if let Some((start, offset)) = f3.evaluations_range() {
                &v3[start..][..offset]
            } else {
                &v3[..]
            };
            let res = (0..largest_even_below(v1.len()))
                .step_by(2)
                .rev()
                .map(|b| {
                    let c1_0 = v1[b + 1] - v1[b];
                    let c1_1 = c1_0 + c1_0;
                    let c2_0 = v2[b + 1] - v2[b];
                    let c2_1 = c2_0 + c2_0;
                    let c3_0 = v3[b + 1] - v3[b];
                    let c3_1 = c3_0 + c3_0;
                    AdditiveArray([
                        ((v1[b]) * (v2[b])) * (v3[b]),
                        ((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1]),
                        ((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                            * (c3_0 + v3[b + 1]),
                        ((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                            * (c3_1 + v3[b + 1]),
                    ])
                })
                .sum::<AdditiveArray<_, 4usize>>();
            let res = if v1.len() == 1 {
                let b = 0;
                AdditiveArray::<
                    _,
                    4usize,
                >([((v1[b]) * (v2[b])) * (v3[b]); 4usize])
            } else {
                res
            };
            let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                - (ceil_log2(v1.len()).max(1) + self.round - 1);
            if num_vars_multiplicity > 0 {
                AdditiveArray(
                    res
                        .0
                        .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                )
            } else {
                res
            }
        }
        (FieldType::Ext(v1), FieldType::Base(v2), FieldType::Base(v3)) => {
            let v1 = if let Some((start, offset)) = f1.evaluations_range() {
                &v1[start..][..offset]
            } else {
                &v1[..]
            };
            let v2 = if let Some((start, offset)) = f2.evaluations_range() {
                &v2[start..][..offset]
            } else {
                &v2[..]
            };
            let v3 = if let Some((start, offset)) = f3.evaluations_range() {
                &v3[start..][..offset]
            } else {
                &v3[..]
            };
            let res = (0..largest_even_below(v1.len()))
                .step_by(2)
                .rev()
                .map(|b| {
                    let c1_0 = v1[b + 1] - v1[b];
                    let c1_1 = c1_0 + c1_0;
                    let c2_0 = v2[b + 1] - v2[b];
                    let c2_1 = c2_0 + c2_0;
                    let c3_0 = v3[b + 1] - v3[b];
                    let c3_1 = c3_0 + c3_0;
                    AdditiveArray([
                        ((v1[b]) * (v2[b])) * (v3[b]),
                        ((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1]),
                        ((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                            * (c3_0 + v3[b + 1]),
                        ((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                            * (c3_1 + v3[b + 1]),
                    ])
                })
                .sum::<AdditiveArray<_, 4usize>>();
            let res = if v1.len() == 1 {
                let b = 0;
                AdditiveArray::<
                    _,
                    4usize,
                >([((v1[b]) * (v2[b])) * (v3[b]); 4usize])
            } else {
                res
            };
            let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                - (ceil_log2(v1.len()).max(1) + self.round - 1);
            if num_vars_multiplicity > 0 {
                AdditiveArray(
                    res
                        .0
                        .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                )
            } else {
                res
            }
        }
        (FieldType::Base(v1), FieldType::Base(v2), FieldType::Base(v3)) => {
            let v1 = if let Some((start, offset)) = f1.evaluations_range() {
                &v1[start..][..offset]
            } else {
                &v1[..]
            };
            let v2 = if let Some((start, offset)) = f2.evaluations_range() {
                &v2[start..][..offset]
            } else {
                &v2[..]
            };
            let v3 = if let Some((start, offset)) = f3.evaluations_range() {
                &v3[start..][..offset]
            } else {
                &v3[..]
            };
            let result = {
                let res = (0..largest_even_below(v1.len()))
                    .step_by(2)
                    .rev()
                    .map(|b| {
                        let c1_0 = v1[b + 1] - v1[b];
                        let c1_1 = c1_0 + c1_0;
                        let c2_0 = v2[b + 1] - v2[b];
                        let c2_1 = c2_0 + c2_0;
                        let c3_0 = v3[b + 1] - v3[b];
                        let c3_1 = c3_0 + c3_0;
                        AdditiveArray([
                            ((v1[b]) * (v2[b])) * (v3[b]),
                            ((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1]),
                            ((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                                * (c3_0 + v3[b + 1]),
                            ((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                                * (c3_1 + v3[b + 1]),
                        ])
                    })
                    .sum::<AdditiveArray<_, 4usize>>();
                let res = if v1.len() == 1 {
                    let b = 0;
                    AdditiveArray::<
                        _,
                        4usize,
                    >([((v1[b]) * (v2[b])) * (v3[b]); 4usize])
                } else {
                    res
                };
                let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                    - (ceil_log2(v1.len()).max(1) + self.round - 1);
                if num_vars_multiplicity > 0 {
                    AdditiveArray(
                        res
                            .0
                            .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                    )
                } else {
                    res
                }
            };
            AdditiveArray(result.0.map(E::from))
        }
        _ => ::core::panicking::panic("internal error: entered unreachable code"),
    }
};
code for degree 4
let _result: AdditiveArray<_, 5> = {
    let product_access = |_| &self.poly.flattened_ml_extensions[0];
    let f1 = product_access(0usize);
    let f2 = product_access(1usize);
    let f3 = product_access(2usize);
    let f4 = product_access(3usize);
    let (f1, f2, f3, f4) = match (
        &f1.evaluations(),
        &f2.evaluations(),
        &f3.evaluations(),
        &f4.evaluations(),
    ) {
        (
            FieldType::Base(_),
            FieldType::Ext(_),
            FieldType::Ext(_),
            FieldType::Ext(_),
        ) => (f2, f3, f4, f1),
        (
            FieldType::Ext(_),
            FieldType::Base(_),
            FieldType::Ext(_),
            FieldType::Ext(_),
        ) => (f1, f3, f4, f2),
        (
            FieldType::Base(_),
            FieldType::Base(_),
            FieldType::Ext(_),
            FieldType::Ext(_),
        ) => (f3, f4, f1, f2),
        (
            FieldType::Ext(_),
            FieldType::Ext(_),
            FieldType::Base(_),
            FieldType::Ext(_),
        ) => (f1, f2, f4, f3),
        (
            FieldType::Base(_),
            FieldType::Ext(_),
            FieldType::Base(_),
            FieldType::Ext(_),
        ) => (f2, f4, f1, f3),
        (
            FieldType::Ext(_),
            FieldType::Base(_),
            FieldType::Base(_),
            FieldType::Ext(_),
        ) => (f1, f4, f2, f3),
        (
            FieldType::Base(_),
            FieldType::Base(_),
            FieldType::Base(_),
            FieldType::Ext(_),
        ) => (f4, f1, f2, f3),
        (
            FieldType::Base(_),
            FieldType::Ext(_),
            FieldType::Ext(_),
            FieldType::Base(_),
        ) => (f2, f3, f1, f4),
        (
            FieldType::Ext(_),
            FieldType::Base(_),
            FieldType::Ext(_),
            FieldType::Base(_),
        ) => (f1, f3, f2, f4),
        (
            FieldType::Base(_),
            FieldType::Base(_),
            FieldType::Ext(_),
            FieldType::Base(_),
        ) => (f3, f1, f2, f4),
        (
            FieldType::Base(_),
            FieldType::Ext(_),
            FieldType::Base(_),
            FieldType::Base(_),
        ) => (f2, f1, f3, f4),
        _ => (f1, f2, f3, f4),
    };
    match (
        &f1.evaluations(),
        &f2.evaluations(),
        &f3.evaluations(),
        &f4.evaluations(),
    ) {
        (
            FieldType::Ext(v1),
            FieldType::Ext(v2),
            FieldType::Ext(v3),
            FieldType::Ext(v4),
        ) => {
            let v1 = if let Some((start, offset)) = f1.evaluations_range() {
                &v1[start..][..offset]
            } else {
                &v1[..]
            };
            let v2 = if let Some((start, offset)) = f2.evaluations_range() {
                &v2[start..][..offset]
            } else {
                &v2[..]
            };
            let v3 = if let Some((start, offset)) = f3.evaluations_range() {
                &v3[start..][..offset]
            } else {
                &v3[..]
            };
            let v4 = if let Some((start, offset)) = f4.evaluations_range() {
                &v4[start..][..offset]
            } else {
                &v4[..]
            };
            let res = (0..largest_even_below(v1.len()))
                .step_by(2)
                .rev()
                .map(|b| {
                    let c1_0 = v1[b + 1] - v1[b];
                    let c1_1 = c1_0 + c1_0;
                    let c2_0 = v2[b + 1] - v2[b];
                    let c2_1 = c2_0 + c2_0;
                    let c3_0 = v3[b + 1] - v3[b];
                    let c3_1 = c3_0 + c3_0;
                    let c4_0 = v4[b + 1] - v4[b];
                    let c4_1 = c4_0 + c4_0;
                    AdditiveArray([
                        (((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]),
                        (((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]),
                        (((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                            * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]),
                        (((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                            * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]),
                        (((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                            * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]),
                    ])
                })
                .sum::<AdditiveArray<_, 5usize>>();
            let res = if v1.len() == 1 {
                let b = 0;
                AdditiveArray::<
                    _,
                    5usize,
                >([(((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]); 5usize])
            } else {
                res
            };
            let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                - (ceil_log2(v1.len()).max(1) + self.round - 1);
            if num_vars_multiplicity > 0 {
                AdditiveArray(
                    res
                        .0
                        .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                )
            } else {
                res
            }
        }
        (
            FieldType::Ext(v1),
            FieldType::Ext(v2),
            FieldType::Ext(v3),
            FieldType::Base(v4),
        ) => {
            let v1 = if let Some((start, offset)) = f1.evaluations_range() {
                &v1[start..][..offset]
            } else {
                &v1[..]
            };
            let v2 = if let Some((start, offset)) = f2.evaluations_range() {
                &v2[start..][..offset]
            } else {
                &v2[..]
            };
            let v3 = if let Some((start, offset)) = f3.evaluations_range() {
                &v3[start..][..offset]
            } else {
                &v3[..]
            };
            let v4 = if let Some((start, offset)) = f4.evaluations_range() {
                &v4[start..][..offset]
            } else {
                &v4[..]
            };
            let res = (0..largest_even_below(v1.len()))
                .step_by(2)
                .rev()
                .map(|b| {
                    let c1_0 = v1[b + 1] - v1[b];
                    let c1_1 = c1_0 + c1_0;
                    let c2_0 = v2[b + 1] - v2[b];
                    let c2_1 = c2_0 + c2_0;
                    let c3_0 = v3[b + 1] - v3[b];
                    let c3_1 = c3_0 + c3_0;
                    let c4_0 = v4[b + 1] - v4[b];
                    let c4_1 = c4_0 + c4_0;
                    AdditiveArray([
                        (((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]),
                        (((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]),
                        (((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                            * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]),
                        (((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                            * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]),
                        (((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                            * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]),
                    ])
                })
                .sum::<AdditiveArray<_, 5usize>>();
            let res = if v1.len() == 1 {
                let b = 0;
                AdditiveArray::<
                    _,
                    5usize,
                >([(((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]); 5usize])
            } else {
                res
            };
            let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                - (ceil_log2(v1.len()).max(1) + self.round - 1);
            if num_vars_multiplicity > 0 {
                AdditiveArray(
                    res
                        .0
                        .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                )
            } else {
                res
            }
        }
        (
            FieldType::Ext(v1),
            FieldType::Ext(v2),
            FieldType::Base(v3),
            FieldType::Base(v4),
        ) => {
            let v1 = if let Some((start, offset)) = f1.evaluations_range() {
                &v1[start..][..offset]
            } else {
                &v1[..]
            };
            let v2 = if let Some((start, offset)) = f2.evaluations_range() {
                &v2[start..][..offset]
            } else {
                &v2[..]
            };
            let v3 = if let Some((start, offset)) = f3.evaluations_range() {
                &v3[start..][..offset]
            } else {
                &v3[..]
            };
            let v4 = if let Some((start, offset)) = f4.evaluations_range() {
                &v4[start..][..offset]
            } else {
                &v4[..]
            };
            let res = (0..largest_even_below(v1.len()))
                .step_by(2)
                .rev()
                .map(|b| {
                    let c1_0 = v1[b + 1] - v1[b];
                    let c1_1 = c1_0 + c1_0;
                    let c2_0 = v2[b + 1] - v2[b];
                    let c2_1 = c2_0 + c2_0;
                    let c3_0 = v3[b + 1] - v3[b];
                    let c3_1 = c3_0 + c3_0;
                    let c4_0 = v4[b + 1] - v4[b];
                    let c4_1 = c4_0 + c4_0;
                    AdditiveArray([
                        (((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]),
                        (((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]),
                        (((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                            * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]),
                        (((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                            * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]),
                        (((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                            * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]),
                    ])
                })
                .sum::<AdditiveArray<_, 5usize>>();
            let res = if v1.len() == 1 {
                let b = 0;
                AdditiveArray::<
                    _,
                    5usize,
                >([(((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]); 5usize])
            } else {
                res
            };
            let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                - (ceil_log2(v1.len()).max(1) + self.round - 1);
            if num_vars_multiplicity > 0 {
                AdditiveArray(
                    res
                        .0
                        .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                )
            } else {
                res
            }
        }
        (
            FieldType::Ext(v1),
            FieldType::Base(v2),
            FieldType::Base(v3),
            FieldType::Base(v4),
        ) => {
            let v1 = if let Some((start, offset)) = f1.evaluations_range() {
                &v1[start..][..offset]
            } else {
                &v1[..]
            };
            let v2 = if let Some((start, offset)) = f2.evaluations_range() {
                &v2[start..][..offset]
            } else {
                &v2[..]
            };
            let v3 = if let Some((start, offset)) = f3.evaluations_range() {
                &v3[start..][..offset]
            } else {
                &v3[..]
            };
            let v4 = if let Some((start, offset)) = f4.evaluations_range() {
                &v4[start..][..offset]
            } else {
                &v4[..]
            };
            let res = (0..largest_even_below(v1.len()))
                .step_by(2)
                .rev()
                .map(|b| {
                    let c1_0 = v1[b + 1] - v1[b];
                    let c1_1 = c1_0 + c1_0;
                    let c2_0 = v2[b + 1] - v2[b];
                    let c2_1 = c2_0 + c2_0;
                    let c3_0 = v3[b + 1] - v3[b];
                    let c3_1 = c3_0 + c3_0;
                    let c4_0 = v4[b + 1] - v4[b];
                    let c4_1 = c4_0 + c4_0;
                    AdditiveArray([
                        (((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]),
                        (((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]),
                        (((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                            * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]),
                        (((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                            * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]),
                        (((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                            * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]),
                    ])
                })
                .sum::<AdditiveArray<_, 5usize>>();
            let res = if v1.len() == 1 {
                let b = 0;
                AdditiveArray::<
                    _,
                    5usize,
                >([(((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]); 5usize])
            } else {
                res
            };
            let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                - (ceil_log2(v1.len()).max(1) + self.round - 1);
            if num_vars_multiplicity > 0 {
                AdditiveArray(
                    res
                        .0
                        .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                )
            } else {
                res
            }
        }
        (
            FieldType::Base(v1),
            FieldType::Base(v2),
            FieldType::Base(v3),
            FieldType::Base(v4),
        ) => {
            let v1 = if let Some((start, offset)) = f1.evaluations_range() {
                &v1[start..][..offset]
            } else {
                &v1[..]
            };
            let v2 = if let Some((start, offset)) = f2.evaluations_range() {
                &v2[start..][..offset]
            } else {
                &v2[..]
            };
            let v3 = if let Some((start, offset)) = f3.evaluations_range() {
                &v3[start..][..offset]
            } else {
                &v3[..]
            };
            let v4 = if let Some((start, offset)) = f4.evaluations_range() {
                &v4[start..][..offset]
            } else {
                &v4[..]
            };
            let result = {
                let res = (0..largest_even_below(v1.len()))
                    .step_by(2)
                    .rev()
                    .map(|b| {
                        let c1_0 = v1[b + 1] - v1[b];
                        let c1_1 = c1_0 + c1_0;
                        let c2_0 = v2[b + 1] - v2[b];
                        let c2_1 = c2_0 + c2_0;
                        let c3_0 = v3[b + 1] - v3[b];
                        let c3_1 = c3_0 + c3_0;
                        let c4_0 = v4[b + 1] - v4[b];
                        let c4_1 = c4_0 + c4_0;
                        AdditiveArray([
                            (((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]),
                            (((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]),
                            (((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                                * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]),
                            (((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                                * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]),
                            (((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                                * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]),
                        ])
                    })
                    .sum::<AdditiveArray<_, 5usize>>();
                let res = if v1.len() == 1 {
                    let b = 0;
                    AdditiveArray::<
                        _,
                        5usize,
                    >([(((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]); 5usize])
                } else {
                    res
                };
                let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                    - (ceil_log2(v1.len()).max(1) + self.round - 1);
                if num_vars_multiplicity > 0 {
                    AdditiveArray(
                        res
                            .0
                            .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                    )
                } else {
                    res
                }
            };
            AdditiveArray(result.0.map(E::from))
        }
        _ => ::core::panicking::panic("internal error: entered unreachable code"),
    }
};
code for degree 5
let _result: AdditiveArray<_, 6> = {
  let product_access = |_| &self.poly.flattened_ml_extensions[0];
  let f1 = product_access(0usize);
  let f2 = product_access(1usize);
  let f3 = product_access(2usize);
  let f4 = product_access(3usize);
  let f5 = product_access(4usize);
  let (f1, f2, f3, f4, f5) = match (
      &f1.evaluations(),
      &f2.evaluations(),
      &f3.evaluations(),
      &f4.evaluations(),
      &f5.evaluations(),
  ) {
      (
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
      ) => (f2, f3, f4, f5, f1),
      (
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
      ) => (f1, f3, f4, f5, f2),
      (
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
      ) => (f3, f4, f5, f1, f2),
      (
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
      ) => (f1, f2, f4, f5, f3),
      (
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
      ) => (f2, f4, f5, f1, f3),
      (
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
      ) => (f1, f4, f5, f2, f3),
      (
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
      ) => (f4, f5, f1, f2, f3),
      (
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
      ) => (f1, f2, f3, f5, f4),
      (
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
      ) => (f2, f3, f5, f1, f4),
      (
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
      ) => (f1, f3, f5, f2, f4),
      (
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
      ) => (f3, f5, f1, f2, f4),
      (
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
      ) => (f1, f2, f5, f3, f4),
      (
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
      ) => (f2, f5, f1, f3, f4),
      (
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
      ) => (f1, f5, f2, f3, f4),
      (
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
      ) => (f5, f1, f2, f3, f4),
      (
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Base(_),
      ) => (f2, f3, f4, f1, f5),
      (
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Base(_),
      ) => (f1, f3, f4, f2, f5),
      (
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Base(_),
      ) => (f3, f4, f1, f2, f5),
      (
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
      ) => (f1, f2, f4, f3, f5),
      (
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
      ) => (f2, f4, f1, f3, f5),
      (
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
      ) => (f1, f4, f2, f3, f5),
      (
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
      ) => (f4, f1, f2, f3, f5),
      (
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Base(_),
      ) => (f2, f3, f1, f4, f5),
      (
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Base(_),
      ) => (f1, f3, f2, f4, f5),
      (
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Base(_),
      ) => (f3, f1, f2, f4, f5),
      (
          FieldType::Base(_),
          FieldType::Ext(_),
          FieldType::Base(_),
          FieldType::Base(_),
          FieldType::Base(_),
      ) => (f2, f1, f3, f4, f5),
      _ => (f1, f2, f3, f4, f5),
  };
  match (
      &f1.evaluations(),
      &f2.evaluations(),
      &f3.evaluations(),
      &f4.evaluations(),
      &f5.evaluations(),
  ) {
      (
          FieldType::Ext(v1),
          FieldType::Ext(v2),
          FieldType::Ext(v3),
          FieldType::Ext(v4),
          FieldType::Ext(v5),
      ) => {
          let v1 = if let Some((start, offset)) = f1.evaluations_range() {
              &v1[start..][..offset]
          } else {
              &v1[..]
          };
          let v2 = if let Some((start, offset)) = f2.evaluations_range() {
              &v2[start..][..offset]
          } else {
              &v2[..]
          };
          let v3 = if let Some((start, offset)) = f3.evaluations_range() {
              &v3[start..][..offset]
          } else {
              &v3[..]
          };
          let v4 = if let Some((start, offset)) = f4.evaluations_range() {
              &v4[start..][..offset]
          } else {
              &v4[..]
          };
          let v5 = if let Some((start, offset)) = f5.evaluations_range() {
              &v5[start..][..offset]
          } else {
              &v5[..]
          };
          let res = (0..largest_even_below(v1.len()))
              .step_by(2)
              .rev()
              .map(|b| {
                  let c1_0 = v1[b + 1] - v1[b];
                  let c1_1 = c1_0 + c1_0;
                  let c1_2 = c1_1 + c1_1;
                  let c2_0 = v2[b + 1] - v2[b];
                  let c2_1 = c2_0 + c2_0;
                  let c2_2 = c2_1 + c2_1;
                  let c3_0 = v3[b + 1] - v3[b];
                  let c3_1 = c3_0 + c3_0;
                  let c3_2 = c3_1 + c3_1;
                  let c4_0 = v4[b + 1] - v4[b];
                  let c4_1 = c4_0 + c4_0;
                  let c4_2 = c4_1 + c4_1;
                  let c5_0 = v5[b + 1] - v5[b];
                  let c5_1 = c5_0 + c5_0;
                  let c5_2 = c5_1 + c5_1;
                  AdditiveArray([
                      ((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b])) * (v5[b]),
                      ((((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]))
                          * (v5[b + 1]),
                      ((((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                          * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]))
                          * (c5_0 + v5[b + 1]),
                      ((((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                          * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]))
                          * (c5_1 + v5[b + 1]),
                      ((((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                          * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]))
                          * (c5_0 + c5_1 + v5[b + 1]),
                      ((((c1_2 + v1[b + 1]) * (c2_2 + v2[b + 1]))
                          * (c3_2 + v3[b + 1])) * (c4_2 + v4[b + 1]))
                          * (c5_2 + v5[b + 1]),
                  ])
              })
              .sum::<AdditiveArray<_, 6usize>>();
          let res = if v1.len() == 1 {
              let b = 0;
              AdditiveArray::<
                  _,
                  6usize,
              >(
                  [((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]))
                      * (v5[b]); 6usize],
              )
          } else {
              res
          };
          let num_vars_multiplicity = self.poly.aux_info.max_num_variables
              - (ceil_log2(v1.len()).max(1) + self.round - 1);
          if num_vars_multiplicity > 0 {
              AdditiveArray(
                  res
                      .0
                      .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
              )
          } else {
              res
          }
      }
      (
          FieldType::Ext(v1),
          FieldType::Ext(v2),
          FieldType::Ext(v3),
          FieldType::Ext(v4),
          FieldType::Base(v5),
      ) => {
          let v1 = if let Some((start, offset)) = f1.evaluations_range() {
              &v1[start..][..offset]
          } else {
              &v1[..]
          };
          let v2 = if let Some((start, offset)) = f2.evaluations_range() {
              &v2[start..][..offset]
          } else {
              &v2[..]
          };
          let v3 = if let Some((start, offset)) = f3.evaluations_range() {
              &v3[start..][..offset]
          } else {
              &v3[..]
          };
          let v4 = if let Some((start, offset)) = f4.evaluations_range() {
              &v4[start..][..offset]
          } else {
              &v4[..]
          };
          let v5 = if let Some((start, offset)) = f5.evaluations_range() {
              &v5[start..][..offset]
          } else {
              &v5[..]
          };
          let res = (0..largest_even_below(v1.len()))
              .step_by(2)
              .rev()
              .map(|b| {
                  let c1_0 = v1[b + 1] - v1[b];
                  let c1_1 = c1_0 + c1_0;
                  let c1_2 = c1_1 + c1_1;
                  let c2_0 = v2[b + 1] - v2[b];
                  let c2_1 = c2_0 + c2_0;
                  let c2_2 = c2_1 + c2_1;
                  let c3_0 = v3[b + 1] - v3[b];
                  let c3_1 = c3_0 + c3_0;
                  let c3_2 = c3_1 + c3_1;
                  let c4_0 = v4[b + 1] - v4[b];
                  let c4_1 = c4_0 + c4_0;
                  let c4_2 = c4_1 + c4_1;
                  let c5_0 = v5[b + 1] - v5[b];
                  let c5_1 = c5_0 + c5_0;
                  let c5_2 = c5_1 + c5_1;
                  AdditiveArray([
                      ((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b])) * (v5[b]),
                      ((((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]))
                          * (v5[b + 1]),
                      ((((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                          * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]))
                          * (c5_0 + v5[b + 1]),
                      ((((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                          * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]))
                          * (c5_1 + v5[b + 1]),
                      ((((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                          * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]))
                          * (c5_0 + c5_1 + v5[b + 1]),
                      ((((c1_2 + v1[b + 1]) * (c2_2 + v2[b + 1]))
                          * (c3_2 + v3[b + 1])) * (c4_2 + v4[b + 1]))
                          * (c5_2 + v5[b + 1]),
                  ])
              })
              .sum::<AdditiveArray<_, 6usize>>();
          let res = if v1.len() == 1 {
              let b = 0;
              AdditiveArray::<
                  _,
                  6usize,
              >(
                  [((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]))
                      * (v5[b]); 6usize],
              )
          } else {
              res
          };
          let num_vars_multiplicity = self.poly.aux_info.max_num_variables
              - (ceil_log2(v1.len()).max(1) + self.round - 1);
          if num_vars_multiplicity > 0 {
              AdditiveArray(
                  res
                      .0
                      .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
              )
          } else {
              res
          }
      }
      (
          FieldType::Ext(v1),
          FieldType::Ext(v2),
          FieldType::Ext(v3),
          FieldType::Base(v4),
          FieldType::Base(v5),
      ) => {
          let v1 = if let Some((start, offset)) = f1.evaluations_range() {
              &v1[start..][..offset]
          } else {
              &v1[..]
          };
          let v2 = if let Some((start, offset)) = f2.evaluations_range() {
              &v2[start..][..offset]
          } else {
              &v2[..]
          };
          let v3 = if let Some((start, offset)) = f3.evaluations_range() {
              &v3[start..][..offset]
          } else {
              &v3[..]
          };
          let v4 = if let Some((start, offset)) = f4.evaluations_range() {
              &v4[start..][..offset]
          } else {
              &v4[..]
          };
          let v5 = if let Some((start, offset)) = f5.evaluations_range() {
              &v5[start..][..offset]
          } else {
              &v5[..]
          };
          let res = (0..largest_even_below(v1.len()))
              .step_by(2)
              .rev()
              .map(|b| {
                  let c1_0 = v1[b + 1] - v1[b];
                  let c1_1 = c1_0 + c1_0;
                  let c1_2 = c1_1 + c1_1;
                  let c2_0 = v2[b + 1] - v2[b];
                  let c2_1 = c2_0 + c2_0;
                  let c2_2 = c2_1 + c2_1;
                  let c3_0 = v3[b + 1] - v3[b];
                  let c3_1 = c3_0 + c3_0;
                  let c3_2 = c3_1 + c3_1;
                  let c4_0 = v4[b + 1] - v4[b];
                  let c4_1 = c4_0 + c4_0;
                  let c4_2 = c4_1 + c4_1;
                  let c5_0 = v5[b + 1] - v5[b];
                  let c5_1 = c5_0 + c5_0;
                  let c5_2 = c5_1 + c5_1;
                  AdditiveArray([
                      ((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b])) * (v5[b]),
                      ((((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]))
                          * (v5[b + 1]),
                      ((((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                          * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]))
                          * (c5_0 + v5[b + 1]),
                      ((((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                          * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]))
                          * (c5_1 + v5[b + 1]),
                      ((((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                          * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]))
                          * (c5_0 + c5_1 + v5[b + 1]),
                      ((((c1_2 + v1[b + 1]) * (c2_2 + v2[b + 1]))
                          * (c3_2 + v3[b + 1])) * (c4_2 + v4[b + 1]))
                          * (c5_2 + v5[b + 1]),
                  ])
              })
              .sum::<AdditiveArray<_, 6usize>>();
          let res = if v1.len() == 1 {
              let b = 0;
              AdditiveArray::<
                  _,
                  6usize,
              >(
                  [((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]))
                      * (v5[b]); 6usize],
              )
          } else {
              res
          };
          let num_vars_multiplicity = self.poly.aux_info.max_num_variables
              - (ceil_log2(v1.len()).max(1) + self.round - 1);
          if num_vars_multiplicity > 0 {
              AdditiveArray(
                  res
                      .0
                      .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
              )
          } else {
              res
          }
      }
      (
          FieldType::Ext(v1),
          FieldType::Ext(v2),
          FieldType::Base(v3),
          FieldType::Base(v4),
          FieldType::Base(v5),
      ) => {
          let v1 = if let Some((start, offset)) = f1.evaluations_range() {
              &v1[start..][..offset]
          } else {
              &v1[..]
          };
          let v2 = if let Some((start, offset)) = f2.evaluations_range() {
              &v2[start..][..offset]
          } else {
              &v2[..]
          };
          let v3 = if let Some((start, offset)) = f3.evaluations_range() {
              &v3[start..][..offset]
          } else {
              &v3[..]
          };
          let v4 = if let Some((start, offset)) = f4.evaluations_range() {
              &v4[start..][..offset]
          } else {
              &v4[..]
          };
          let v5 = if let Some((start, offset)) = f5.evaluations_range() {
              &v5[start..][..offset]
          } else {
              &v5[..]
          };
          let res = (0..largest_even_below(v1.len()))
              .step_by(2)
              .rev()
              .map(|b| {
                  let c1_0 = v1[b + 1] - v1[b];
                  let c1_1 = c1_0 + c1_0;
                  let c1_2 = c1_1 + c1_1;
                  let c2_0 = v2[b + 1] - v2[b];
                  let c2_1 = c2_0 + c2_0;
                  let c2_2 = c2_1 + c2_1;
                  let c3_0 = v3[b + 1] - v3[b];
                  let c3_1 = c3_0 + c3_0;
                  let c3_2 = c3_1 + c3_1;
                  let c4_0 = v4[b + 1] - v4[b];
                  let c4_1 = c4_0 + c4_0;
                  let c4_2 = c4_1 + c4_1;
                  let c5_0 = v5[b + 1] - v5[b];
                  let c5_1 = c5_0 + c5_0;
                  let c5_2 = c5_1 + c5_1;
                  AdditiveArray([
                      ((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b])) * (v5[b]),
                      ((((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]))
                          * (v5[b + 1]),
                      ((((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                          * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]))
                          * (c5_0 + v5[b + 1]),
                      ((((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                          * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]))
                          * (c5_1 + v5[b + 1]),
                      ((((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                          * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]))
                          * (c5_0 + c5_1 + v5[b + 1]),
                      ((((c1_2 + v1[b + 1]) * (c2_2 + v2[b + 1]))
                          * (c3_2 + v3[b + 1])) * (c4_2 + v4[b + 1]))
                          * (c5_2 + v5[b + 1]),
                  ])
              })
              .sum::<AdditiveArray<_, 6usize>>();
          let res = if v1.len() == 1 {
              let b = 0;
              AdditiveArray::<
                  _,
                  6usize,
              >(
                  [((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]))
                      * (v5[b]); 6usize],
              )
          } else {
              res
          };
          let num_vars_multiplicity = self.poly.aux_info.max_num_variables
              - (ceil_log2(v1.len()).max(1) + self.round - 1);
          if num_vars_multiplicity > 0 {
              AdditiveArray(
                  res
                      .0
                      .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
              )
          } else {
              res
          }
      }
      (
          FieldType::Ext(v1),
          FieldType::Base(v2),
          FieldType::Base(v3),
          FieldType::Base(v4),
          FieldType::Base(v5),
      ) => {
          let v1 = if let Some((start, offset)) = f1.evaluations_range() {
              &v1[start..][..offset]
          } else {
              &v1[..]
          };
          let v2 = if let Some((start, offset)) = f2.evaluations_range() {
              &v2[start..][..offset]
          } else {
              &v2[..]
          };
          let v3 = if let Some((start, offset)) = f3.evaluations_range() {
              &v3[start..][..offset]
          } else {
              &v3[..]
          };
          let v4 = if let Some((start, offset)) = f4.evaluations_range() {
              &v4[start..][..offset]
          } else {
              &v4[..]
          };
          let v5 = if let Some((start, offset)) = f5.evaluations_range() {
              &v5[start..][..offset]
          } else {
              &v5[..]
          };
          let res = (0..largest_even_below(v1.len()))
              .step_by(2)
              .rev()
              .map(|b| {
                  let c1_0 = v1[b + 1] - v1[b];
                  let c1_1 = c1_0 + c1_0;
                  let c1_2 = c1_1 + c1_1;
                  let c2_0 = v2[b + 1] - v2[b];
                  let c2_1 = c2_0 + c2_0;
                  let c2_2 = c2_1 + c2_1;
                  let c3_0 = v3[b + 1] - v3[b];
                  let c3_1 = c3_0 + c3_0;
                  let c3_2 = c3_1 + c3_1;
                  let c4_0 = v4[b + 1] - v4[b];
                  let c4_1 = c4_0 + c4_0;
                  let c4_2 = c4_1 + c4_1;
                  let c5_0 = v5[b + 1] - v5[b];
                  let c5_1 = c5_0 + c5_0;
                  let c5_2 = c5_1 + c5_1;
                  AdditiveArray([
                      ((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b])) * (v5[b]),
                      ((((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]))
                          * (v5[b + 1]),
                      ((((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                          * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]))
                          * (c5_0 + v5[b + 1]),
                      ((((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                          * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]))
                          * (c5_1 + v5[b + 1]),
                      ((((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                          * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]))
                          * (c5_0 + c5_1 + v5[b + 1]),
                      ((((c1_2 + v1[b + 1]) * (c2_2 + v2[b + 1]))
                          * (c3_2 + v3[b + 1])) * (c4_2 + v4[b + 1]))
                          * (c5_2 + v5[b + 1]),
                  ])
              })
              .sum::<AdditiveArray<_, 6usize>>();
          let res = if v1.len() == 1 {
              let b = 0;
              AdditiveArray::<
                  _,
                  6usize,
              >(
                  [((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]))
                      * (v5[b]); 6usize],
              )
          } else {
              res
          };
          let num_vars_multiplicity = self.poly.aux_info.max_num_variables
              - (ceil_log2(v1.len()).max(1) + self.round - 1);
          if num_vars_multiplicity > 0 {
              AdditiveArray(
                  res
                      .0
                      .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
              )
          } else {
              res
          }
      }
      (
          FieldType::Base(v1),
          FieldType::Base(v2),
          FieldType::Base(v3),
          FieldType::Base(v4),
          FieldType::Base(v5),
      ) => {
          let v1 = if let Some((start, offset)) = f1.evaluations_range() {
              &v1[start..][..offset]
          } else {
              &v1[..]
          };
          let v2 = if let Some((start, offset)) = f2.evaluations_range() {
              &v2[start..][..offset]
          } else {
              &v2[..]
          };
          let v3 = if let Some((start, offset)) = f3.evaluations_range() {
              &v3[start..][..offset]
          } else {
              &v3[..]
          };
          let v4 = if let Some((start, offset)) = f4.evaluations_range() {
              &v4[start..][..offset]
          } else {
              &v4[..]
          };
          let v5 = if let Some((start, offset)) = f5.evaluations_range() {
              &v5[start..][..offset]
          } else {
              &v5[..]
          };
          let result = {
              let res = (0..largest_even_below(v1.len()))
                  .step_by(2)
                  .rev()
                  .map(|b| {
                      let c1_0 = v1[b + 1] - v1[b];
                      let c1_1 = c1_0 + c1_0;
                      let c1_2 = c1_1 + c1_1;
                      let c2_0 = v2[b + 1] - v2[b];
                      let c2_1 = c2_0 + c2_0;
                      let c2_2 = c2_1 + c2_1;
                      let c3_0 = v3[b + 1] - v3[b];
                      let c3_1 = c3_0 + c3_0;
                      let c3_2 = c3_1 + c3_1;
                      let c4_0 = v4[b + 1] - v4[b];
                      let c4_1 = c4_0 + c4_0;
                      let c4_2 = c4_1 + c4_1;
                      let c5_0 = v5[b + 1] - v5[b];
                      let c5_1 = c5_0 + c5_0;
                      let c5_2 = c5_1 + c5_1;
                      AdditiveArray([
                          ((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b])) * (v5[b]),
                          ((((v1[b + 1]) * (v2[b + 1])) * (v3[b + 1])) * (v4[b + 1]))
                              * (v5[b + 1]),
                          ((((c1_0 + v1[b + 1]) * (c2_0 + v2[b + 1]))
                              * (c3_0 + v3[b + 1])) * (c4_0 + v4[b + 1]))
                              * (c5_0 + v5[b + 1]),
                          ((((c1_1 + v1[b + 1]) * (c2_1 + v2[b + 1]))
                              * (c3_1 + v3[b + 1])) * (c4_1 + v4[b + 1]))
                              * (c5_1 + v5[b + 1]),
                          ((((c1_0 + c1_1 + v1[b + 1]) * (c2_0 + c2_1 + v2[b + 1]))
                              * (c3_0 + c3_1 + v3[b + 1])) * (c4_0 + c4_1 + v4[b + 1]))
                              * (c5_0 + c5_1 + v5[b + 1]),
                          ((((c1_2 + v1[b + 1]) * (c2_2 + v2[b + 1]))
                              * (c3_2 + v3[b + 1])) * (c4_2 + v4[b + 1]))
                              * (c5_2 + v5[b + 1]),
                      ])
                  })
                  .sum::<AdditiveArray<_, 6usize>>();
              let res = if v1.len() == 1 {
                  let b = 0;
                  AdditiveArray::<
                      _,
                      6usize,
                  >(
                      [((((v1[b]) * (v2[b])) * (v3[b])) * (v4[b]))
                          * (v5[b]); 6usize],
                  )
              } else {
                  res
              };
              let num_vars_multiplicity = self.poly.aux_info.max_num_variables
                  - (ceil_log2(v1.len()).max(1) + self.round - 1);
              if num_vars_multiplicity > 0 {
                  AdditiveArray(
                      res
                          .0
                          .map(|e| e * E::BaseField::from(1 << num_vars_multiplicity)),
                  )
              } else {
                  res
              }
          };
          AdditiveArray(result.0.map(E::from))
      }
      _ => ::core::panicking::panic("internal error: entered unreachable code"),
  }
};

@matthiasgoergens
Copy link
Collaborator

Could you add in the PR description a very brief overview over what we are doing and more importantly why?

(Leave the 'what' really brief, the details are in the PR diff itself. But the why is hard to get from just the code.)

Thanks!

@zemse zemse force-pushed the 788-sumcheck-macro branch from e8ec7da to 30fecbb Compare January 16, 2025 07:25
@zemse zemse force-pushed the 788-sumcheck-macro branch from 30fecbb to c847a12 Compare January 16, 2025 08:54
Copy link
Collaborator

@hero78119 hero78119 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Epic work and overall LGTM!!
There is no impact of benchmark result 🔥

sumcheck/src/prover.rs Show resolved Hide resolved
sumcheck/src/prover.rs Outdated Show resolved Hide resolved
sumcheck/src/prover.rs Show resolved Hide resolved
@hero78119
Copy link
Collaborator

Also verified on fibonacci e2e result in 32 threads, before/after remain the same

fibonacci_max_steps_1048576/prove_fibonacci/fibonacci_max_steps_1048576
                        time:   [4.0948 s 4.1154 s 4.1351 s]
                        change: [-1.0895% -0.4833% +0.1092%] (p = 0.16 > 0.05)
                        No change in performance detected.

@zemse zemse force-pushed the 788-sumcheck-macro branch from d98d04f to 8ae99b4 Compare January 21, 2025 17:07
@zemse zemse marked this pull request as ready for review January 22, 2025 08:11
Copy link
Collaborator

@hero78119 hero78119 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 👍 👍 Epic work to clean up all boipolate code

@hero78119 hero78119 added this pull request to the merge queue Jan 22, 2025
Merged via the queue into scroll-tech:master with commit 63489d1 Jan 22, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants