use clock_curve_math::{FieldElement, FieldOps, MathError, field::batch_ops::*};
#[cfg(feature = "alloc")]
mod batch_inverse_tests {
use super::*;
#[test]
fn test_batch_inverse_empty_input() {
let result = batch_inverse(&[]).unwrap();
assert!(result.is_empty());
assert_eq!(result.len(), 0);
assert_eq!(result.into_vec().len(), 0);
}
#[test]
fn test_batch_inverse_single_element() {
let element = FieldElement::from_u64(42);
let result = batch_inverse(&[element]).unwrap();
assert_eq!(result.len(), 1);
assert_eq!(element.mul(result.get(0)), FieldElement::from_u64(1));
let vec = result.into_vec();
assert_eq!(vec.len(), 1);
assert_eq!(element.mul(&vec[0]), FieldElement::from_u64(1));
}
#[test]
fn test_batch_inverse_single_zero() {
let zero = FieldElement::from_u64(0);
let result = batch_inverse(&[zero]);
assert!(result.is_none());
}
#[test]
fn test_batch_inverse_two_elements() {
let a = FieldElement::from_u64(2);
let b = FieldElement::from_u64(3);
let result = batch_inverse(&[a, b]).unwrap();
assert_eq!(result.len(), 2);
assert_eq!(a.mul(result.get(0)), FieldElement::from_u64(1));
assert_eq!(b.mul(result.get(1)), FieldElement::from_u64(1));
assert_eq!(*result.get(0), a.inv());
assert_eq!(*result.get(1), b.inv());
}
#[test]
fn test_batch_inverse_three_elements() {
let elements = [
FieldElement::from_u64(2),
FieldElement::from_u64(3),
FieldElement::from_u64(5),
];
let result = batch_inverse(&elements).unwrap();
assert_eq!(result.len(), 3);
for (i, elem) in elements.iter().enumerate() {
assert_eq!(elem.mul(result.get(i)), FieldElement::from_u64(1));
}
}
#[test]
fn test_batch_inverse_large_batch() {
let elements: Vec<FieldElement> = (1..=20).map(|i| FieldElement::from_u64(i + 1)).collect();
let result = batch_inverse(&elements).unwrap();
assert_eq!(result.len(), 20);
for (i, elem) in elements.iter().enumerate() {
assert_eq!(elem.mul(result.get(i)), FieldElement::from_u64(1));
}
}
#[test]
fn test_batch_inverse_with_zero_anywhere() {
let elements = vec![
FieldElement::from_u64(2),
FieldElement::from_u64(0), FieldElement::from_u64(3),
];
let result = batch_inverse(&elements);
assert!(result.is_none());
}
#[test]
fn test_batch_inverse_all_same_element() {
let element = FieldElement::from_u64(7);
let elements = vec![element; 5];
let result = batch_inverse(&elements).unwrap();
assert_eq!(result.len(), 5);
for inv in result.inverses.iter() {
assert_eq!(element.mul(inv), FieldElement::from_u64(1));
}
}
#[test]
fn test_batch_inverse_montgomery_algorithm_correctness() {
let elements = vec![
FieldElement::from_u64(2),
FieldElement::from_u64(3),
FieldElement::from_u64(5),
FieldElement::from_u64(7),
FieldElement::from_u64(11),
];
let batch_result = batch_inverse(&elements).unwrap();
for (i, elem) in elements.iter().enumerate() {
let individual_inv = elem.inv();
assert_eq!(*batch_result.get(i), individual_inv);
}
}
#[test]
fn test_batch_inverse_order_preservation() {
let elements = vec![
FieldElement::from_u64(13),
FieldElement::from_u64(17),
FieldElement::from_u64(19),
FieldElement::from_u64(23),
];
let result = batch_inverse(&elements).unwrap();
assert_eq!(elements[0].mul(result.get(0)), FieldElement::from_u64(1));
assert_eq!(elements[1].mul(result.get(1)), FieldElement::from_u64(1));
assert_eq!(elements[2].mul(result.get(2)), FieldElement::from_u64(1));
assert_eq!(elements[3].mul(result.get(3)), FieldElement::from_u64(1));
}
#[test]
fn test_batch_inverse_result_clone() {
let elements = vec![FieldElement::from_u64(2), FieldElement::from_u64(3)];
let original = batch_inverse(&elements).unwrap();
let cloned = original.clone();
assert_eq!(original.len(), cloned.len());
assert_eq!(original.inverses, cloned.inverses);
}
#[test]
fn test_batch_inverse_result_debug() {
let elements = vec![FieldElement::from_u64(2)];
let result = batch_inverse(&elements).unwrap();
let debug_str = format!("{:?}", result);
assert!(debug_str.contains("BatchInverseResult"));
}
}
#[cfg(feature = "alloc")]
mod batch_inverse_checked_tests {
use super::*;
#[test]
fn test_batch_inverse_checked_empty() {
let result = batch_inverse_checked(&[]);
assert!(result.is_ok());
assert!(result.unwrap().is_empty());
}
#[test]
fn test_batch_inverse_checked_valid_elements() {
let elements = vec![
FieldElement::from_u64(2),
FieldElement::from_u64(3),
FieldElement::from_u64(5),
];
let result = batch_inverse_checked(&elements).unwrap();
assert_eq!(result.len(), 3);
for (i, elem) in elements.iter().enumerate() {
assert_eq!(elem.mul(result.get(i)), FieldElement::from_u64(1));
}
}
#[test]
fn test_batch_inverse_checked_with_zero() {
let elements = vec![
FieldElement::from_u64(2),
FieldElement::from_u64(0),
FieldElement::from_u64(3),
];
let result = batch_inverse_checked(&elements);
assert!(result.is_err());
assert_eq!(result.unwrap_err(), MathError::DivisionByZero);
}
#[test]
fn test_batch_inverse_checked_single_zero() {
let result = batch_inverse_checked(&[FieldElement::from_u64(0)]);
assert!(result.is_err());
assert_eq!(result.unwrap_err(), MathError::DivisionByZero);
}
}
#[cfg(feature = "alloc")]
mod batch_inverse_small_tests {
use super::*;
#[test]
fn test_batch_inverse_small_empty() {
let result = batch_inverse_small(&[]).unwrap();
assert!(result.is_empty());
}
#[test]
fn test_batch_inverse_small_single() {
let element = FieldElement::from_u64(7);
let result = batch_inverse_small(&[element]).unwrap();
assert_eq!(result.len(), 1);
assert_eq!(element.mul(result.get(0)), FieldElement::from_u64(1));
}
#[test]
fn test_batch_inverse_small_single_zero() {
let result = batch_inverse_small(&[FieldElement::from_u64(0)]);
assert!(result.is_none());
}
#[test]
fn test_batch_inverse_small_two_elements() {
let a = FieldElement::from_u64(2);
let b = FieldElement::from_u64(3);
let result = batch_inverse_small(&[a, b]).unwrap();
assert_eq!(result.len(), 2);
assert_eq!(a.mul(result.get(0)), FieldElement::from_u64(1));
assert_eq!(b.mul(result.get(1)), FieldElement::from_u64(1));
}
#[test]
fn test_batch_inverse_small_two_with_zero() {
let result = batch_inverse_small(&[FieldElement::from_u64(2), FieldElement::from_u64(0)]);
assert!(result.is_none());
let result2 = batch_inverse_small(&[FieldElement::from_u64(0), FieldElement::from_u64(3)]);
assert!(result2.is_none());
}
#[test]
fn test_batch_inverse_small_three_elements() {
let elements = [
FieldElement::from_u64(2),
FieldElement::from_u64(3),
FieldElement::from_u64(5),
];
let result = batch_inverse_small(&elements).unwrap();
assert_eq!(result.len(), 3);
for (i, elem) in elements.iter().enumerate() {
assert_eq!(elem.mul(result.get(i)), FieldElement::from_u64(1));
}
}
#[test]
fn test_batch_inverse_small_large_batch() {
let elements: Vec<FieldElement> = (1..=10).map(|i| FieldElement::from_u64(i + 1)).collect();
let result = batch_inverse_small(&elements).unwrap();
assert_eq!(result.len(), 10);
for (i, elem) in elements.iter().enumerate() {
assert_eq!(elem.mul(result.get(i)), FieldElement::from_u64(1));
}
}
}
#[cfg(feature = "alloc")]
mod performance_and_correctness_tests {
use super::*;
#[test]
fn test_batch_inverse_correctness_comprehensive() {
let test_values = [
1u64, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
];
let elements: Vec<FieldElement> = test_values
.iter()
.map(|&v| FieldElement::from_u64(v))
.collect();
let result = batch_inverse(&elements).unwrap();
assert_eq!(result.len(), test_values.len());
for (i, &expected_value) in test_values.iter().enumerate() {
let elem = FieldElement::from_u64(expected_value);
assert_eq!(elem.mul(result.get(i)), FieldElement::from_u64(1));
}
}
#[test]
fn test_batch_inverse_consistency_with_individual() {
let elements = vec![
FieldElement::from_u64(2),
FieldElement::from_u64(7),
FieldElement::from_u64(11),
FieldElement::from_u64(13),
];
let batch_result = batch_inverse(&elements).unwrap();
let individual_inverses: Vec<FieldElement> = elements.iter().map(|e| e.inv()).collect();
for (i, individual_inv) in individual_inverses.iter().enumerate() {
assert_eq!(*batch_result.get(i), *individual_inv);
}
}
#[test]
fn test_batch_inverse_mathematical_properties() {
let a = FieldElement::from_u64(3);
let b = FieldElement::from_u64(5);
let result = batch_inverse(&[a, b]).unwrap();
let inv_a = result.get(0);
let inv_b = result.get(1);
let product = a.mul(&b);
let inv_product = product.inv();
let inv_b_times_inv_a = inv_b.mul(inv_a);
assert_eq!(inv_product, inv_b_times_inv_a);
let inv_a_squared = inv_a.mul(inv_a);
let a_squared = a.mul(&a);
let inv_a_squared_direct = a_squared.inv();
assert_eq!(inv_a_squared, inv_a_squared_direct);
}
#[test]
fn test_batch_inverse_result_access_methods() {
let elements = vec![
FieldElement::from_u64(2),
FieldElement::from_u64(3),
FieldElement::from_u64(5),
];
let result = batch_inverse(&elements).unwrap();
assert_eq!(result.len(), 3);
assert!(!result.is_empty());
for i in 0..3 {
let elem = &elements[i];
let inv = result.get(i);
assert_eq!(elem.mul(inv), FieldElement::from_u64(1));
}
let vec = result.into_vec();
assert_eq!(vec.len(), 3);
for (i, elem) in elements.iter().enumerate() {
assert_eq!(elem.mul(&vec[i]), FieldElement::from_u64(1));
}
}
}
#[cfg(feature = "alloc")]
mod edge_cases_and_error_handling {
use super::*;
#[test]
fn test_batch_inverse_max_reasonable_size() {
let elements: Vec<FieldElement> =
(1..=100).map(|i| FieldElement::from_u64(i + 1)).collect();
let result = batch_inverse(&elements).unwrap();
assert_eq!(result.len(), 100);
assert_eq!(elements[0].mul(result.get(0)), FieldElement::from_u64(1));
assert_eq!(elements[50].mul(result.get(50)), FieldElement::from_u64(1));
assert_eq!(elements[99].mul(result.get(99)), FieldElement::from_u64(1));
}
#[test]
fn test_batch_inverse_result_panic_on_out_of_bounds() {
let elements = vec![FieldElement::from_u64(2)];
let _result = batch_inverse(&elements).unwrap();
}
#[test]
fn test_batch_inverse_algorithm_robustness() {
let elements = vec![
FieldElement::from_u64(1), FieldElement::from_u64(2),
FieldElement::from_u64(1), FieldElement::from_u64(2), ];
let result = batch_inverse(&elements).unwrap();
assert_eq!(result.len(), 4);
for (i, elem) in elements.iter().enumerate() {
assert_eq!(elem.mul(result.get(i)), FieldElement::from_u64(1));
}
}
}
#[cfg(feature = "alloc")]
mod memory_and_performance_tests {
use super::*;
#[test]
fn test_batch_inverse_memory_efficiency() {
let elements = vec![FieldElement::from_u64(2), FieldElement::from_u64(3)];
let result = batch_inverse(&elements).unwrap();
let vec = result.into_vec();
assert_eq!(vec.len(), 2);
assert_eq!(elements[0].mul(&vec[0]), FieldElement::from_u64(1));
}
#[test]
fn test_batch_inverse_result_reuse() {
let elements = vec![FieldElement::from_u64(2), FieldElement::from_u64(3)];
let result = batch_inverse(&elements).unwrap();
let _inv0 = result.get(0);
let _inv1 = result.get(1);
let _inv0_again = result.get(0);
assert_eq!(elements[0].mul(result.get(0)), FieldElement::from_u64(1));
assert_eq!(elements[1].mul(result.get(1)), FieldElement::from_u64(1));
}
}