Skip to content

Commit 1c504a5

Browse files
author
Kunming Jiang
committed
Much simpler interleaving method
1 parent a0f20c0 commit 1c504a5

File tree

1 file changed

+73
-14
lines changed

1 file changed

+73
-14
lines changed

mpcs/src/lib.rs

+73-14
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ fn compute_binary_with_length(length: usize, mut value: usize) -> Vec<bool> {
7777
bin
7878
}
7979

80+
/* Old Interleaving Approach for bookkeeping
81+
8082
// Given the sizes of a list of polys sorted in decreasing order,
8183
// Compute which list each entry of their interleaved form belong to
8284
// e.g.: [4, 2, 1, 1] => [0, 1, 0, 2, 0, 1, 0, 3]
@@ -165,6 +167,61 @@ fn interleave_polys<E: ExtensionField>(
165167
}
166168
DenseMultilinearExtension { num_vars: interleaved_num_vars, evaluations: interleaved_evaluations }
167169
}
170+
*/
171+
172+
// Interleave the polys give their position on the binary tree
173+
// Assume the polys are sorted by decreasing size
174+
// Denote: N - size of the interleaved poly; M - num of polys
175+
// This function performs interleave in O(M) + O(N) time and is *potentially* parallelizable (maybe? idk)
176+
fn interleave_polys<E: ExtensionField>(
177+
polys: Vec<&DenseMultilinearExtension<E>>,
178+
comps: &Vec<Vec<bool>>,
179+
) -> DenseMultilinearExtension<E> {
180+
assert!(polys.len() > 0);
181+
let sizes: Vec<usize> = polys.iter().map(|p| p.evaluations.len()).collect();
182+
let interleaved_size = sizes.iter().sum::<usize>().next_power_of_two();
183+
let interleaved_num_vars = interleaved_size.ilog2() as usize;
184+
// Initialize the interleaved poly
185+
// Is there a better way to deal with field types?
186+
let mut interleaved_evaluations = match polys[0].evaluations {
187+
FieldType::Base(_) => FieldType::Base(vec![E::BaseField::ZERO; interleaved_size]),
188+
FieldType::Ext(_) => FieldType::Ext(vec![E::ZERO; interleaved_size]),
189+
_ => unreachable!()
190+
};
191+
// For every poly, determine its:
192+
// * Start: where's its first entry in the interleaved poly?
193+
// * Gap: how many entires are between its consecutive entries in the interleaved poly?
194+
// Then fill in the corresponding entries in the interleaved poly
195+
for (poly, comp) in polys.iter().zip(comps) {
196+
// Start is the decimal representation of the inverse of comp
197+
let mut start = 0;
198+
let mut pow_2 = 1;
199+
for b in comp {
200+
start += if *b { pow_2 } else { 0 };
201+
pow_2 *= 2;
202+
}
203+
// Gap is 2 ** (interleaved_num_vars - poly_num_vars)
204+
let gap = 1 << (interleaved_num_vars - poly.num_vars);
205+
// Fill in the blank
206+
match (&mut interleaved_evaluations, &poly.evaluations) {
207+
(FieldType::Base(ie), FieldType::Base(pe)) => {
208+
for (i, e) in pe.iter().enumerate() {
209+
ie[start + gap * i] = *e;
210+
}
211+
}
212+
(FieldType::Ext(ie), FieldType::Ext(pe)) => {
213+
for (i, e) in pe.iter().enumerate() {
214+
ie[start + gap * i] = *e;
215+
}
216+
}
217+
(a, b) => panic!(
218+
"do not support merge different field type DME a: {:?} b: {:?}",
219+
a, b
220+
),
221+
}
222+
}
223+
DenseMultilinearExtension { num_vars: interleaved_num_vars, evaluations: interleaved_evaluations }
224+
}
168225

169226
// Pack polynomials of different sizes into the same, returns
170227
// 0: A list of packed polys
@@ -239,8 +296,10 @@ fn pack_poly_prover<E: ExtensionField>(
239296
}
240297
}
241298
// Interleave every poly
242-
let mut packed_polys: Vec<_> = packed_polys.into_iter().map(|ps| interleave_polys(ps)).collect();
243-
let next_packed_poly = interleave_polys(next_packed_poly);
299+
let mut packed_polys: Vec<_> = packed_polys.into_iter().zip(&packed_comps).map(|(ps, pc)|
300+
interleave_polys(ps, pc)
301+
).collect();
302+
let next_packed_poly = interleave_polys(next_packed_poly, &next_packed_comp);
244303

245304
// Final packed poly
246305
if next_packed_poly.num_vars == max_poly_num_vars {
@@ -1119,7 +1178,7 @@ pub mod test_util {
11191178
{
11201179
use crate::{pcs_batch_commit_diff_size_and_write, pcs_batch_open_diff_size, pcs_batch_verify_diff_size};
11211180

1122-
for vars_gap in 1..=max_vars_gap {
1181+
for vars_gap in 0..=max_vars_gap {
11231182
println!("GAP: {vars_gap}");
11241183
assert!(max_num_vars > vars_gap * batch_size);
11251184
let (pp, vp) = setup_pcs::<E, Pcs>(max_num_vars);
@@ -1182,19 +1241,19 @@ mod test {
11821241
use p3_field::PrimeCharacteristicRing;
11831242
use p3_goldilocks::Goldilocks;
11841243

1185-
use crate::interleave_pattern;
1244+
// use crate::interleave_pattern;
11861245
type E = GoldilocksExt2;
11871246

1188-
#[test]
1189-
fn test_interleave() {
1190-
let poly_num_vars = [vec![27, 26, 25, 25], vec![4, 4, 4, 4, 4], vec![8], vec![23, 23, 19, 13]];
1191-
for num_vars in poly_num_vars {
1192-
println!("NUM_VARS: {:?}", num_vars);
1193-
let sizes = num_vars.iter().map(|n| 2_i32.pow(*n) as usize).collect();
1194-
let interleaved_indices = interleave_pattern(sizes);
1195-
println!("INDICES: {:?}", interleaved_indices);
1196-
}
1197-
}
1247+
// #[test]
1248+
// fn test_interleave() {
1249+
// let poly_num_vars = [vec![27, 26, 25, 25], vec![4, 4, 4, 4, 4], vec![8], vec![23, 23, 19, 13]];
1250+
// for num_vars in poly_num_vars {
1251+
// println!("NUM_VARS: {:?}", num_vars);
1252+
// let sizes = num_vars.iter().map(|n| 2_i32.pow(*n) as usize).collect();
1253+
// let interleaved_indices = interleave_pattern(sizes);
1254+
// println!("INDICES: {:?}", interleaved_indices);
1255+
// }
1256+
// }
11981257

11991258
#[test]
12001259
fn test_packing() {

0 commit comments

Comments
 (0)