Skip to content
Merged
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: 0 additions & 2 deletions crates/backend/field/src/packed/packed_traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ pub trait PackedFieldExtension<BaseField: Field, ExtField: ExtensionField<BaseFi

/// Unpack one packed element into the `BaseField::Packing::WIDTH` extension field elements
/// it holds. Use `.flat_map(Self::to_ext_lanes)` to unpack an iterator of packed elements.
#[must_use]
fn to_ext_lanes(self) -> impl Iterator<Item = ExtField>;

/// Given a iterator of packed extension field elements, convert to an iterator of
Expand All @@ -360,7 +359,6 @@ pub trait PackedFieldExtension<BaseField: Field, ExtField: ExtensionField<BaseFi
/// Note that the length of the returned iterator will be `unpacked_len / WIDTH` and
/// not `len` as the iterator is over packed extension field elements. If `unpacked_len`
/// is not divisible by `WIDTH`, `unpacked_len` will be rounded up to the next multiple of `WIDTH`.
#[must_use]
fn packed_ext_powers_capped(base: ExtField, unpacked_len: usize) -> impl Iterator<Item = Self> {
Self::packed_ext_powers(base).take(unpacked_len.div_ceil(BaseField::Packing::WIDTH))
}
Expand Down
30 changes: 25 additions & 5 deletions crates/backend/poly/src/eq_mle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1021,12 +1021,9 @@ fn base_eval_eq_packed_with_packed_output<F, EF, const INITIALIZED: bool>(
F: Field,
EF: ExtensionField<F>,
{
// Ensure that the output buffer size is correct:
// It should be of size `2^n`, where `n` is the number of variables.
let width = F::Packing::WIDTH;
let log_packing_width = log2_strict_usize(width);
// `eval_points` is the middle slice from `par_eval_eq`, so its length says nothing about the
// packing width (the callers assert that against the full point).
debug_assert_eq!(out.len(), 1 << eval_points.len());
debug_assert!(log_packing_width <= eval_points.len());

match eval_points.len() {
0 => {
Expand Down Expand Up @@ -1320,6 +1317,29 @@ mod tests {
}
}

/// `par_eval_eq` hands the kernel a middle slice of any length >= 2, so the hardcoded arms
/// below `log_packing_width` must agree with the unpacked-output twin. Calling the kernel
/// directly keeps this independent of the SIMD width and thread count.
#[test]
fn base_packed_kernel_handles_short_slices() {
let mut rng = StdRng::seed_from_u64(11);
let scalar: EF = rng.random();
let eq_evals = <F as Field>::Packing::from_fn(|_| rng.random());

for len in 1..=3 {
let points: Vec<F> = (0..len).map(|_| rng.random()).collect();

let mut expected = EF::zero_vec(<F as Field>::Packing::WIDTH << len);
base_eval_eq_packed::<F, EF, false>(&points, &mut expected, eq_evals, scalar);

let mut packed = EFPacking::<EF>::zero_vec(1 << len);
let packed_scalar = EFPacking::<EF>::from(scalar);
base_eval_eq_packed_with_packed_output::<F, EF, false>(&points, &mut packed, eq_evals, packed_scalar);

assert_eq!(expected, EFPacking::<EF>::to_ext_iter_vec(packed), "len = {len}");
}
}

#[test]
fn test_compute_eval_eq_packed_dual() {
let packing_width = <F as Field>::Packing::WIDTH;
Expand Down
Loading