Skip to content

Commit 72df358

Browse files
committed
memory: more unit tests for extension field getters
1 parent bc44db5 commit 72df358

File tree

1 file changed

+223
-7
lines changed
  • crates/leanVm/src/memory

1 file changed

+223
-7
lines changed

crates/leanVm/src/memory/mem.rs

Lines changed: 223 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,13 @@ impl Memory {
220220
(0..len)
221221
.map(|i| {
222222
// Calculate the address for the i-th vector.
223-
let current_addr = (start_address + i).map_err(MemoryError::Math)?;
223+
//
224+
// Each vector has a fixed size of `DIMENSION` field elements.
225+
// We advance by `i * DIMENSION` to get to the i-th vector.
226+
let current_addr = (start_address + i * DIMENSION)?;
224227

225-
// Read the DIMENSION base field elements for the i-th vector.
226-
let vector_coeffs = self.get_array_as::<F, DIMENSION>(current_addr)?;
227-
228-
// Convert the base field elements into an extension field element.
229-
EF::from_basis_coefficients_slice(&vector_coeffs)
230-
.ok_or(MemoryError::InvalidExtensionFieldConversion)
228+
// Read the extension field element for the i-th vector.
229+
self.get_extension(current_addr)
231230
})
232231
.collect()
233232
}
@@ -480,4 +479,221 @@ mod tests {
480479
})
481480
);
482481
}
482+
483+
#[test]
484+
fn test_get_extension_successful() {
485+
// Setup
486+
//
487+
// Create a memory instance with one segment.
488+
let mut memory = create_memory_with_segments(1);
489+
// Define the address where the vector will be stored.
490+
let addr = MemoryAddress::new(0, 0);
491+
492+
// Data Preparation
493+
//
494+
// Create a simple, hardcoded array of 8 field elements.
495+
let values: [F; DIMENSION] = [
496+
F::from_u64(1),
497+
F::from_u64(2),
498+
F::from_u64(3),
499+
F::from_u64(4),
500+
F::from_u64(5),
501+
F::from_u64(6),
502+
F::from_u64(7),
503+
F::from_u64(8),
504+
];
505+
// Create the expected Extension Field element from these coefficients.
506+
let expected_ef = EF::from_basis_coefficients_slice(&values).unwrap();
507+
508+
// Memory Population
509+
//
510+
// Insert each of the 8 field elements into consecutive memory cells.
511+
for (i, &val) in values.iter().enumerate() {
512+
memory.insert((addr + i).unwrap(), val).unwrap();
513+
}
514+
515+
// Execution
516+
//
517+
// Call the function to read the extension field element from memory.
518+
let result = memory.get_extension(addr);
519+
520+
// Verification
521+
//
522+
// Assert that the retrieved element matches the expected one.
523+
assert_eq!(result.unwrap(), expected_ef);
524+
}
525+
526+
#[test]
527+
fn test_get_extension_fails_on_uninitialized() {
528+
// Setup
529+
//
530+
// Create a memory instance with one segment (segment 0), which is currently empty.
531+
let memory = create_memory_with_segments(1);
532+
// Define a valid memory address within the allocated segment. No value has been written here yet.
533+
let addr = MemoryAddress::new(0, 0);
534+
535+
// Execution
536+
//
537+
// Attempt to read an extension field element from the uninitialized memory address.
538+
let result: Result<EF, _> = memory.get_extension(addr);
539+
540+
// Verification
541+
//
542+
// Assert that the operation failed and returned the specific `UninitializedMemory` error,
543+
// confirming that the function correctly handles reads from empty memory cells.
544+
assert!(matches!(result, Err(MemoryError::UninitializedMemory(_))));
545+
}
546+
547+
#[test]
548+
fn test_get_vectorized_slice_extension_successful() {
549+
// Setup
550+
//
551+
// Create a memory instance with one segment.
552+
let mut memory = create_memory_with_segments(1);
553+
// Define the starting address for our slice of vectors.
554+
let start_addr = MemoryAddress::new(0, 5);
555+
// Define the number of vectors we want to read.
556+
let len = 2;
557+
558+
// Data Preparation
559+
//
560+
// Create the first vector's data.
561+
let vector1_coeffs: [F; DIMENSION] = [
562+
F::from_u64(1),
563+
F::from_u64(2),
564+
F::from_u64(3),
565+
F::from_u64(4),
566+
F::from_u64(5),
567+
F::from_u64(6),
568+
F::from_u64(7),
569+
F::from_u64(8),
570+
];
571+
// Create the second vector's data.
572+
let vector2_coeffs: [F; DIMENSION] = [
573+
F::from_u64(10),
574+
F::from_u64(20),
575+
F::from_u64(30),
576+
F::from_u64(40),
577+
F::from_u64(50),
578+
F::from_u64(60),
579+
F::from_u64(70),
580+
F::from_u64(80),
581+
];
582+
583+
// Convert the coefficient arrays into Extension Field elements for our expected result.
584+
let expected_ef1 = EF::from_basis_coefficients_slice(&vector1_coeffs).unwrap();
585+
let expected_ef2 = EF::from_basis_coefficients_slice(&vector2_coeffs).unwrap();
586+
let expected_vec = vec![expected_ef1, expected_ef2];
587+
588+
// Memory Population
589+
//
590+
// Insert the first vector into memory at the starting address.
591+
for (j, &val) in vector1_coeffs.iter().enumerate() {
592+
memory.insert((start_addr + j).unwrap(), val).unwrap();
593+
}
594+
// Insert the second vector into memory immediately after the first one.
595+
// The address is calculated by adding the dimension to the start address.
596+
let second_vector_addr = (start_addr + DIMENSION).unwrap();
597+
for (j, &val) in vector2_coeffs.iter().enumerate() {
598+
memory
599+
.insert((second_vector_addr + j).unwrap(), val)
600+
.unwrap();
601+
}
602+
603+
// Execution
604+
//
605+
// Call the function to read the slice of 2 vectors from memory.
606+
let result = memory.get_vectorized_slice_extension(start_addr, len);
607+
608+
// Verification
609+
//
610+
// Assert that the retrieved slice matches the expected vector of extension field elements.
611+
assert_eq!(result.unwrap(), expected_vec);
612+
}
613+
614+
#[test]
615+
fn test_get_vectorized_slice_extension_zero_len() {
616+
// Setup
617+
//
618+
// Create a memory instance with one segment.
619+
let memory = create_memory_with_segments(1);
620+
// Define a starting address (its value doesn't matter for a zero-length read).
621+
let start_addr = MemoryAddress::new(0, 0);
622+
623+
// Execution
624+
//
625+
// Call the function with a length of 0.
626+
let result = memory.get_vectorized_slice_extension(start_addr, 0);
627+
628+
// Verification
629+
//
630+
// Assert that the result is an Ok containing an empty vector.
631+
assert!(result.unwrap().is_empty());
632+
}
633+
634+
#[test]
635+
fn test_get_vectorized_slice_extension_fails_on_uninitialized() {
636+
// Setup
637+
//
638+
// Create a memory instance with one segment.
639+
let mut memory = create_memory_with_segments(1);
640+
// Define the starting address for the slice.
641+
let start_addr = MemoryAddress::new(0, 0);
642+
643+
// Memory Population
644+
//
645+
// Insert only the first vector's worth of data into memory.
646+
for i in 0..DIMENSION {
647+
memory
648+
.insert((start_addr + i).unwrap(), F::from_usize(i))
649+
.unwrap();
650+
}
651+
652+
// Execution
653+
//
654+
// Attempt to read a slice of two vectors. The read should fail on the second vector.
655+
let result: Result<Vec<EF>, _> = memory.get_vectorized_slice_extension(start_addr, 2);
656+
657+
// Verification
658+
//
659+
// Assert that the operation failed with an `UninitializedMemory` error.
660+
assert!(matches!(result, Err(MemoryError::UninitializedMemory(_))));
661+
}
662+
663+
#[test]
664+
fn test_get_vectorized_slice_extension_fails_on_type_mismatch() {
665+
// Setup
666+
//
667+
// Create a memory instance with one segment.
668+
let mut memory = create_memory_with_segments(1);
669+
// Define the starting address for the slice.
670+
let start_addr = MemoryAddress::new(0, 0);
671+
672+
// Memory Population
673+
//
674+
// Insert a complete, valid first vector (all integers).
675+
for i in 0..DIMENSION {
676+
memory
677+
.insert((start_addr + i).unwrap(), F::from_usize(i))
678+
.unwrap();
679+
}
680+
// For the second vector, insert a `MemoryAddress` where an integer (`F`) is expected.
681+
memory
682+
.insert(
683+
(start_addr + DIMENSION).unwrap(),
684+
MemoryValue::Address(MemoryAddress::new(0, 99)),
685+
)
686+
.unwrap();
687+
688+
// Execution
689+
//
690+
// Attempt to read the slice of two vectors.
691+
// This will fail when trying to convert the address to an integer.
692+
let result: Result<Vec<EF>, _> = memory.get_vectorized_slice_extension(start_addr, 2);
693+
694+
// Verification
695+
//
696+
// Assert that the operation failed with an `ExpectedInteger` error.
697+
assert!(matches!(result, Err(MemoryError::ExpectedInteger)));
698+
}
483699
}

0 commit comments

Comments
 (0)