use clock_curve_math::{BigInt, FieldElement, FieldOps, api_extensions::*};
#[test]
fn test_field_extensions_try_sqrt() {
let zero = FieldElement::from_u64(0);
let one = FieldElement::from_u64(1);
let four = FieldElement::from_u64(4);
let sqrt_zero = zero.try_sqrt();
assert!(sqrt_zero.is_some());
assert_eq!(sqrt_zero.unwrap(), zero);
let sqrt_one = one.try_sqrt();
assert!(sqrt_one.is_some());
assert_eq!(sqrt_one.unwrap(), one);
let sqrt_four = four.try_sqrt();
assert!(sqrt_four.is_some());
let sqrt_val = sqrt_four.unwrap();
assert_eq!(sqrt_val.square(), four);
}
#[test]
fn test_field_extensions_legendre() {
let zero = FieldElement::from_u64(0);
let one = FieldElement::from_u64(1);
let quadratic_residue = FieldElement::from_u64(4);
assert_eq!(zero.legendre(), 0);
assert_eq!(one.legendre(), 1);
assert_eq!(
quadratic_residue.is_quadratic_residue(),
quadratic_residue.legendre() == 1
);
}
#[test]
fn test_field_extensions_order() {
let one = FieldElement::from_u64(1);
let minus_one = FieldElement::from_u64(1).neg();
let order_one = one.order();
assert!(order_one.is_some());
assert_eq!(order_one.unwrap(), BigInt::from_u64(1));
let order_minus_one = minus_one.order();
assert!(order_minus_one.is_some());
assert_eq!(order_minus_one.unwrap(), BigInt::from_u64(2));
}
#[test]
fn test_exponentiation_builder_basic() {
let base = FieldElement::from_u64(2);
let exp = BigInt::from_u64(10);
let result = ExponentiationBuilder::new(&base, &exp).build().compute();
assert_eq!(result, base.pow(&exp));
assert_eq!(result, FieldElement::from_u64(1024));
}
#[test]
fn test_exponentiation_builder_with_algorithm() {
let base = FieldElement::from_u64(3);
let exp = BigInt::from_u64(5);
let binary_result = ExponentiationBuilder::new(&base, &exp)
.algorithm(Algorithm::Binary)
.build()
.compute();
let sliding_result = ExponentiationBuilder::new(&base, &exp)
.algorithm(Algorithm::SlidingWindow(4))
.build()
.compute();
let expected = base.pow(&exp);
assert_eq!(binary_result, expected);
assert_eq!(sliding_result, expected);
assert_eq!(binary_result, sliding_result);
}
#[test]
fn test_exponentiation_builder_fixed_window() {
let base = FieldElement::from_u64(2);
let exp1 = BigInt::from_u64(1);
let result1 = ExponentiationBuilder::new(&base, &exp1)
.algorithm(Algorithm::FixedWindow(3))
.build()
.compute();
assert_eq!(result1, FieldElement::from_u64(2));
let exp2 = BigInt::from_u64(2);
let result2 = ExponentiationBuilder::new(&base, &exp2)
.algorithm(Algorithm::FixedWindow(3))
.build()
.compute();
assert_eq!(result2, FieldElement::from_u64(4));
let exp7 = BigInt::from_u64(7);
let result7 = ExponentiationBuilder::new(&base, &exp7)
.algorithm(Algorithm::FixedWindow(3))
.build()
.compute();
assert_eq!(result7, FieldElement::from_u64(128));
}
#[test]
fn test_exponentiation_builder_adaptive() {
let base = FieldElement::from_u64(2);
let small_exp = BigInt::from_u64(5);
let small_result = ExponentiationBuilder::new(&base, &small_exp)
.algorithm(Algorithm::Adaptive)
.build()
.compute();
assert_eq!(small_result, FieldElement::from_u64(32));
let large_exp = BigInt::from_u64(100);
let large_result = ExponentiationBuilder::new(&base, &large_exp)
.algorithm(Algorithm::Adaptive)
.build()
.compute();
assert!(large_result.is_valid());
}
#[test]
fn test_exponentiation_config_default() {
let config = ExponentiationConfig::default();
assert_eq!(config.algorithm, Algorithm::Adaptive);
assert_eq!(config.max_bits, None);
assert_eq!(config.constant_time, true);
}
#[test]
fn test_exponentiation_builder_config_methods() {
let base = FieldElement::from_u64(2);
let exp = BigInt::from_u64(3);
let builder = ExponentiationBuilder::new(&base, &exp)
.algorithm(Algorithm::SlidingWindow(4))
.max_bits(64)
.constant_time(false);
let configured = builder.build();
assert_eq!(configured.get_algorithm(), Algorithm::SlidingWindow(4));
assert_eq!(configured.get_max_bits(), Some(64));
assert_eq!(configured.get_constant_time(), false);
}
#[test]
fn test_multiplication_config_default() {
let config = MultiplicationConfig::default();
assert_eq!(config.algorithm, MultiplicationAlgorithm::Standard);
assert_eq!(config.optimize_squaring, true);
}
#[test]
fn test_configurable_arithmetic_field_element() {
let a = FieldElement::from_u64(6);
let b = FieldElement::from_u64(7);
let config = MultiplicationConfig {
algorithm: MultiplicationAlgorithm::Standard,
optimize_squaring: true,
};
let result_standard = a.mul_with_config(&b, &config);
assert_eq!(result_standard, a.mul(&b));
let config_karatsuba = MultiplicationConfig {
algorithm: MultiplicationAlgorithm::Karatsuba,
optimize_squaring: true,
};
let result_karatsuba = a.mul_with_config(&b, &config_karatsuba);
assert_eq!(result_karatsuba, a.mul(&b));
}
#[test]
fn test_configurable_arithmetic_bigint() {
let a = BigInt::from_u64(12);
let b = BigInt::from_u64(8);
let config = MultiplicationConfig {
algorithm: MultiplicationAlgorithm::Standard,
optimize_squaring: true,
};
let result_standard = a.mul_with_config(&b, &config);
assert_eq!(result_standard, a.mul(&b));
let config_karatsuba = MultiplicationConfig {
algorithm: MultiplicationAlgorithm::Karatsuba,
optimize_squaring: true,
};
let result_karatsuba = a.mul_with_config(&b, &config_karatsuba);
assert_eq!(result_karatsuba, a.mul(&b));
}
#[test]
fn test_configurable_arithmetic_exponentiation() {
let base = FieldElement::from_u64(2);
let exp = BigInt::from_u64(8);
let config = ExponentiationConfig {
algorithm: Algorithm::Binary,
max_bits: Some(32),
constant_time: true,
};
let result = base.pow_with_config(&exp, &config);
assert_eq!(result, FieldElement::from_u64(256)); }
#[test]
fn test_bigint_configurable_exponentiation() {
let base = BigInt::from_u64(3);
let exp = BigInt::from_u64(4);
let config = ExponentiationConfig::default();
let result = base.pow_with_config(&exp, &config);
assert_eq!(result, BigInt::from_u64(81)); }
#[cfg(feature = "alloc")]
mod batch_tests {
use super::*;
#[test]
fn test_batch_config_default() {
let config = BatchConfig::default();
assert_eq!(config.max_batch_size, 1000);
assert_eq!(config.parallel, false);
assert_eq!(config.allocation_strategy, AllocationStrategy::Preallocate);
}
#[test]
fn test_batch_inverse_builder_basic() {
let elements = vec![
FieldElement::from_u64(1),
FieldElement::from_u64(2),
FieldElement::from_u64(3),
];
let builder = BatchInverseBuilder::new(&elements);
let result = builder.compute().unwrap();
assert_eq!(result.inverses.len(), 3);
for (i, inv) in result.inverses.iter().enumerate() {
assert_eq!(elements[i].mul(inv), FieldElement::from_u64(1));
}
}
#[test]
fn test_batch_inverse_builder_with_config() {
let elements = vec![FieldElement::from_u64(5), FieldElement::from_u64(7)];
let result = BatchInverseBuilder::new(&elements)
.max_batch_size(10)
.parallel(false)
.allocation_strategy(AllocationStrategy::OnDemand)
.compute()
.unwrap();
assert_eq!(result.inverses.len(), 2);
for (i, inv) in result.inverses.iter().enumerate() {
assert_eq!(elements[i].mul(inv), FieldElement::from_u64(1));
}
}
#[test]
fn test_batch_inverse_builder_empty() {
let elements: Vec<FieldElement> = vec![];
let result = BatchInverseBuilder::new(&elements).compute().unwrap();
assert_eq!(result.inverses.len(), 0);
}
#[test]
fn test_batch_inverse_builder_single_element() {
let elements = vec![FieldElement::from_u64(42)];
let result = BatchInverseBuilder::new(&elements).compute().unwrap();
assert_eq!(result.inverses.len(), 1);
assert_eq!(
elements[0].mul(&result.inverses[0]),
FieldElement::from_u64(1)
);
}
#[test]
fn test_batch_inverse_result_access() {
let elements = vec![FieldElement::from_u64(2), FieldElement::from_u64(3)];
let result = BatchInverseBuilder::new(&elements).compute().unwrap();
assert_eq!(
elements[0].mul(&result.inverses[0]),
FieldElement::from_u64(1)
);
assert_eq!(
elements[1].mul(&result.inverses[1]),
FieldElement::from_u64(1)
);
}
}
#[test]
fn test_algorithm_enum_variants() {
assert_eq!(Algorithm::Binary, Algorithm::Binary);
assert_eq!(Algorithm::SlidingWindow(4), Algorithm::SlidingWindow(4));
assert_eq!(Algorithm::MontgomeryLadder, Algorithm::MontgomeryLadder);
assert_eq!(Algorithm::FixedWindow(5), Algorithm::FixedWindow(5));
assert_eq!(Algorithm::Adaptive, Algorithm::Adaptive);
assert_ne!(Algorithm::Binary, Algorithm::Adaptive);
assert_ne!(Algorithm::SlidingWindow(3), Algorithm::SlidingWindow(4));
}
#[test]
fn test_multiplication_algorithm_enum() {
assert_eq!(
MultiplicationAlgorithm::Standard,
MultiplicationAlgorithm::Standard
);
assert_eq!(
MultiplicationAlgorithm::Schoolbook,
MultiplicationAlgorithm::Schoolbook
);
assert_eq!(
MultiplicationAlgorithm::Karatsuba,
MultiplicationAlgorithm::Karatsuba
);
assert_eq!(
MultiplicationAlgorithm::ToomCook,
MultiplicationAlgorithm::ToomCook
);
assert_eq!(MultiplicationAlgorithm::FFT, MultiplicationAlgorithm::FFT);
assert_ne!(
MultiplicationAlgorithm::Standard,
MultiplicationAlgorithm::Schoolbook
);
}
#[test]
fn test_allocation_strategy_enum() {
assert_eq!(
AllocationStrategy::Preallocate,
AllocationStrategy::Preallocate
);
assert_eq!(AllocationStrategy::OnDemand, AllocationStrategy::OnDemand);
assert_eq!(AllocationStrategy::Reuse, AllocationStrategy::Reuse);
assert_eq!(
AllocationStrategy::default(),
AllocationStrategy::Preallocate
);
}
#[test]
fn test_exponentiation_edge_cases() {
let base = FieldElement::from_u64(5);
let exp_zero = BigInt::from_u64(0);
let result_zero = ExponentiationBuilder::new(&base, &exp_zero)
.build()
.compute();
assert_eq!(result_zero, FieldElement::from_u64(1));
let exp_one = BigInt::from_u64(1);
let result_one = ExponentiationBuilder::new(&base, &exp_one)
.build()
.compute();
assert_eq!(result_one, base);
}
#[test]
fn test_multiplication_algorithms_consistency() {
let a = BigInt::from_u64(25);
let b = BigInt::from_u64(30);
let expected = a.mul(&b);
let algorithms = vec![
MultiplicationAlgorithm::Standard,
MultiplicationAlgorithm::Schoolbook,
MultiplicationAlgorithm::Karatsuba,
MultiplicationAlgorithm::ToomCook,
MultiplicationAlgorithm::FFT,
];
for algorithm in algorithms {
let config = MultiplicationConfig {
algorithm,
optimize_squaring: true,
};
let result = a.mul_with_config(&b, &config);
assert_eq!(result, expected, "Algorithm {:?} failed", algorithm);
}
}
#[test]
fn test_algorithm_display_and_debug() {
let algo = Algorithm::SlidingWindow(4);
let debug_str = format!("{:?}", algo);
assert!(debug_str.contains("SlidingWindow"));
assert!(debug_str.contains("4"));
}
#[cfg(feature = "alloc")]
#[test]
fn test_batch_builder_config_methods() {
let elements = vec![FieldElement::from_u64(1)];
let builder = BatchInverseBuilder::new(&elements)
.max_batch_size(500)
.parallel(true);
assert_eq!(builder.get_max_batch_size(), 500);
assert_eq!(builder.get_parallel(), true);
}