1- use p3_field:: { Field , PrimeField64 } ;
1+ use p3_field:: { BasedVectorSpace , Field , PrimeField64 } ;
22use p3_symmetric:: Permutation ;
33
44use 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