Skip to content

Commit 6799294

Browse files
committed
vm core: implement execute_extension_mul
1 parent c6658e1 commit 6799294

File tree

2 files changed

+74
-14
lines changed

2 files changed

+74
-14
lines changed

crates/leanVm/src/constant.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
use p3_field::extension::BinomialExtensionField;
12
use p3_koala_bear::KoalaBear;
23

34
pub(crate) const DIMENSION: usize = 8;
45
pub(crate) type F = KoalaBear;
6+
pub(crate) type EF = BinomialExtensionField<F, DIMENSION>;

crates/leanVm/src/core.rs

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use p3_field::{Field, PrimeField64};
1+
use p3_field::{BasedVectorSpace, Field, PrimeField64};
22
use p3_symmetric::Permutation;
33

44
use crate::{
@@ -7,7 +7,7 @@ use crate::{
77
operand::{MemOrConstant, MemOrFp, MemOrFpOrConstant},
88
operation::Operation,
99
},
10-
constant::{DIMENSION, F},
10+
constant::{DIMENSION, EF, F},
1111
context::run_context::RunContext,
1212
errors::{math::MathError, memory::MemoryError, vm::VirtualMachineError},
1313
memory::{address::MemoryAddress, manager::MemoryManager, val::MemoryValue},
@@ -380,11 +380,13 @@ impl<PERM16, PERM24> VirtualMachine<PERM16, PERM24> {
380380
where
381381
PERM24: Permutation<[F; 3 * DIMENSION]>,
382382
{
383-
// Load 6 pointers from memory at `fp + shift`.
383+
// Read Pointers from Memory
384+
//
385+
// The instruction specifies 6 consecutive pointers starting at `fp + shift`.
384386
let ptr_addr = (self.run_context.fp + shift)?;
385387
let ptrs: [MemoryAddress; 6] = self.memory_manager.memory.get_array_as(ptr_addr)?;
386388

387-
// Destructure input and output vector pointers.
389+
// Convert the raw memory values into memory addresses.
388390
let [
389391
ptr_arg_0,
390392
ptr_arg_1,
@@ -394,40 +396,96 @@ impl<PERM16, PERM24> VirtualMachine<PERM16, PERM24> {
394396
ptr_res_2,
395397
] = ptrs;
396398

397-
// Load input vectors of length DIMENSION from memory.
398-
let in0 = self
399+
// Read Input Vectors
400+
//
401+
// Each is an 8-element array of field elements.
402+
let arg0 = self
399403
.memory_manager
400404
.memory
401405
.get_array_as::<F, DIMENSION>(ptr_arg_0)?;
402-
let in1 = self
406+
let arg1 = self
403407
.memory_manager
404408
.memory
405409
.get_array_as::<F, DIMENSION>(ptr_arg_1)?;
406-
let in2 = self
410+
let arg2 = self
407411
.memory_manager
408412
.memory
409413
.get_array_as::<F, DIMENSION>(ptr_arg_2)?;
410414

411-
// Concatenate the three inputs into a single 24-element state.
412-
let mut state: [F; 3 * DIMENSION] = [in0, in1, in2].concat().try_into().unwrap();
415+
// Perform Hashing
416+
//
417+
// Concatenate the three input vectors into a single 24-element array for the permutation.
418+
let mut state = [arg0, arg1, arg2].concat().try_into().unwrap();
413419

414-
// Apply the Poseidon permutation.
420+
// Apply the Poseidon2 permutation to the state.
415421
self.poseidon2_24.permute_mut(&mut state);
416422

417-
// Split and write the outputs to the designated memory locations.
423+
// Write Output Vectors
424+
//
425+
// Split the permuted state back into three 8-element output vectors.
418426
let res0: [F; DIMENSION] = state[..DIMENSION].try_into().unwrap();
419427
let res1: [F; DIMENSION] = state[DIMENSION..2 * DIMENSION].try_into().unwrap();
420428
let res2: [F; DIMENSION] = state[2 * DIMENSION..].try_into().unwrap();
421429

430+
// Write the output vectors to the memory locations pointed to by the result pointers.
422431
self.memory_manager.load_data(ptr_res_0, &res0)?;
423432
self.memory_manager.load_data(ptr_res_1, &res1)?;
424433
self.memory_manager.load_data(ptr_res_2, &res2)?;
425434

426435
Ok(())
427436
}
428437

429-
fn execute_extension_mul(&self, _args: [usize; 3]) -> Result<(), VirtualMachineError> {
430-
// TODO: implement this instruction.
438+
/// Executes the `ExtensionMul` instruction.
439+
///
440+
/// Multiplies two extension field elements stored in memory and writes the result back.
441+
///
442+
/// ## Memory Layout
443+
/// The instruction takes three argument offsets `[a, b, c]` from the frame pointer `fp`:
444+
///
445+
/// - `fp + a`: address of a pointer to the first operand
446+
/// - `fp + b`: address of a pointer to the second operand
447+
/// - `fp + c`: address of a pointer to the output location
448+
///
449+
/// The multiplication is:
450+
///
451+
/// ```text
452+
/// m_vec[ptr_out] = EF::from(m_vec[ptr_lhs]) * EF::from(m_vec[ptr_rhs])
453+
/// ```
454+
///
455+
/// where `ptr_lhs`, `ptr_rhs`, and `ptr_out` are memory addresses stored at `fp + args[0..=2]`.
456+
fn execute_extension_mul(&mut self, args: [usize; 3]) -> Result<(), VirtualMachineError> {
457+
// Get the frame pointer.
458+
let fp = self.run_context.fp;
459+
460+
// Read the memory addresses where the operands and result will reside.
461+
let ptr_lhs: MemoryAddress = self.memory_manager.memory.get_as((fp + args[0])?)?;
462+
let ptr_rhs: MemoryAddress = self.memory_manager.memory.get_as((fp + args[1])?)?;
463+
let ptr_out: MemoryAddress = self.memory_manager.memory.get_as((fp + args[2])?)?;
464+
465+
// Load the `[F; EF::DIMENSION]` input arrays from memory and convert them into EF elements.
466+
let lhs = EF::from_basis_coefficients_slice(
467+
&self
468+
.memory_manager
469+
.memory
470+
.get_array_as::<F, DIMENSION>(ptr_lhs)?,
471+
)
472+
.unwrap();
473+
474+
let rhs = EF::from_basis_coefficients_slice(
475+
&self
476+
.memory_manager
477+
.memory
478+
.get_array_as::<F, DIMENSION>(ptr_rhs)?,
479+
)
480+
.unwrap();
481+
482+
// Perform the field multiplication in the extension field.
483+
let product = lhs * rhs;
484+
485+
// Write the result converted back into `[F; EF::DIMENSION]` to memory.
486+
let result_coeffs: &[F] = product.as_basis_coefficients_slice();
487+
self.memory_manager.load_data(ptr_out, result_coeffs)?;
488+
431489
Ok(())
432490
}
433491
}

0 commit comments

Comments
 (0)