diff --git a/extensions/native/compiler/src/asm/compiler.rs b/extensions/native/compiler/src/asm/compiler.rs index 7d32358a94..cff4a47288 100644 --- a/extensions/native/compiler/src/asm/compiler.rs +++ b/extensions/native/compiler/src/asm/compiler.rs @@ -617,6 +617,15 @@ impl + TwoAdicField> AsmCo debug_info, ); } + DslIr::ExtFromBaseVec(ext, base_vec) => { + assert_eq!(base_vec.len(), EF::D); + for (i, base) in base_vec.into_iter().enumerate() { + self.push( + AsmInstruction::CopyF(ext.fp() + (i as i32), base.fp()), + debug_info.clone(), + ); + } + } _ => unimplemented!(), } } diff --git a/extensions/native/compiler/src/ir/builder.rs b/extensions/native/compiler/src/ir/builder.rs index 82b43ab53d..0a50e030fe 100644 --- a/extensions/native/compiler/src/ir/builder.rs +++ b/extensions/native/compiler/src/ir/builder.rs @@ -620,6 +620,10 @@ impl Builder { self.witness_space.get(id.value()).unwrap() } + pub fn ext_from_base_vec(&mut self, ext: Ext, base_vec: Vec>) { + self.push(DslIr::ExtFromBaseVec(ext, base_vec)); + } + /// Throws an error. pub fn error(&mut self) { self.operations.trace_push(DslIr::Error()); diff --git a/extensions/native/compiler/src/ir/instructions.rs b/extensions/native/compiler/src/ir/instructions.rs index 24ea9d0830..f3c3fd86f7 100644 --- a/extensions/native/compiler/src/ir/instructions.rs +++ b/extensions/native/compiler/src/ir/instructions.rs @@ -229,6 +229,9 @@ pub enum DslIr { /// Operation to halt the program. Should be the last instruction in the program. Halt, + /// Packs a vector of felts into an ext. + ExtFromBaseVec(Ext, Vec>), + // Public inputs for circuits. /// Publish a field element as the ith public value. Should only be used when target is a circuit. CircuitPublish(Var, usize), diff --git a/extensions/native/compiler/tests/ext.rs b/extensions/native/compiler/tests/ext.rs index 5da70cb53b..70584fd926 100644 --- a/extensions/native/compiler/tests/ext.rs +++ b/extensions/native/compiler/tests/ext.rs @@ -35,7 +35,7 @@ fn test_ext2felt() { } #[test] -fn test_ext_from_base_slice() { +fn test_ext_from_base_vec() { const D: usize = 4; type F = BabyBear; type EF = BinomialExtensionField; @@ -52,8 +52,9 @@ fn test_ext_from_base_slice() { let val = EF::from_base_slice(base_slice); let expected: Ext<_, _> = builder.constant(val); - let felts = base_slice.map(|e| builder.constant::>(e)); - let actual = builder.ext_from_base_slice(&felts); + let felts = base_slice.map(|e| builder.constant::>(e)).to_vec(); + let actual = builder.uninit(); + builder.ext_from_base_vec(actual, felts); builder.assert_ext_eq(actual, expected); builder.halt(); diff --git a/extensions/native/recursion/src/challenger/duplex.rs b/extensions/native/recursion/src/challenger/duplex.rs index 7c0cd4dd88..2d45d896be 100644 --- a/extensions/native/recursion/src/challenger/duplex.rs +++ b/extensions/native/recursion/src/challenger/duplex.rs @@ -101,7 +101,9 @@ impl DuplexChallengerVariable { let b = self.sample(builder); let c = self.sample(builder); let d = self.sample(builder); - builder.ext_from_base_slice(&[a, b, c, d]) + let ext = builder.uninit(); + builder.ext_from_base_vec(ext, vec![a, b, c, d]); + ext } fn sample_bits(&self, builder: &mut Builder, nb_bits: RVar) -> Array>