clock_curve_math/
api_extensions.rs

1//! Extended API patterns for future extensibility.
2//!
3//! This module provides advanced API design patterns that enable future
4//! extensions while maintaining backward compatibility. These patterns
5//! allow for optional features, alternative implementations, and
6//! configurable algorithms.
7//!
8//! # Extension Traits
9//!
10//! Extension traits provide optional functionality that can be implemented
11//! by different backends or added in future versions:
12//!
13//! ```rust
14//! use clock_curve_math::{api_extensions::FieldExtensions, FieldElement, FieldOps};
15//!
16//! // Use extended functionality if available
17//! let element = FieldElement::from_u64(42);
18//! if let Some(sqrt) = element.try_sqrt() {
19//!     // Square root is available
20//!     assert_eq!(sqrt.square(), element);
21//! }
22//! ```
23//!
24//! # Operation Builders
25//!
26//! Builders allow complex operations to be configured and executed:
27//!
28//! ```rust
29//! use clock_curve_math::{api_extensions::{ExponentiationBuilder, Algorithm}, FieldElement, BigInt};
30//!
31//! let base = FieldElement::from_u64(2);
32//! let exp = BigInt::from_u64(1000);
33//!
34//! let result = ExponentiationBuilder::new(&base, &exp)
35//!     .algorithm(Algorithm::SlidingWindow(4))
36//!     .build()
37//!     .compute();
38//! ```
39//!
40//! # Configurable Operations
41//!
42//! Operations can be configured with different algorithms and parameters:
43//!
44//! ```rust
45//! use clock_curve_math::{api_extensions::{MultiplicationConfig, MultiplicationAlgorithm, ConfigurableArithmetic}, FieldElement, FieldOps};
46//!
47//! let a = FieldElement::from_u64(42);
48//! let b = FieldElement::from_u64(24);
49//!
50//! let config = MultiplicationConfig {
51//!     algorithm: MultiplicationAlgorithm::Standard,
52//!     ..Default::default()
53//! };
54//!
55//! // Configurable multiplication with algorithm selection
56//! let product = a.mul_with_config(&b, &config);
57//! ```
58
59use crate::bigint::BigInt;
60use crate::error::MathError;
61use crate::extensible::{mul_fft_standalone, mul_karatsuba_standalone, mul_toom_cook_standalone};
62use crate::field::{FieldElement, FieldOps};
63#[cfg(feature = "alloc")]
64extern crate alloc;
65#[cfg(feature = "alloc")]
66use alloc::vec::Vec;
67
68/// Extension trait for optional field operations.
69///
70/// This trait provides operations that may not be available in all
71/// implementations or may have different performance characteristics.
72pub trait FieldExtensions {
73    /// Attempt to compute the square root.
74    ///
75    /// Returns `Some(sqrt)` if a square root exists, `None` otherwise.
76    /// This is an optional operation that may not be implemented by all backends.
77    fn try_sqrt(&self) -> Option<Self>
78    where
79        Self: Sized;
80
81    /// Compute the Legendre symbol (a/p).
82    ///
83    /// Returns 1 if self is a quadratic residue, -1 if not, 0 if zero.
84    /// This operation may be expensive and is provided as an extension.
85    fn legendre(&self) -> i32;
86
87    /// Check if this element is a quadratic residue.
88    fn is_quadratic_residue(&self) -> bool {
89        self.legendre() == 1
90    }
91
92    /// Get the order of this element (if it generates the field).
93    ///
94    /// Returns the smallest positive integer d such that self^d ≡ 1 mod p.
95    /// This is a potentially expensive operation.
96    fn order(&self) -> Option<BigInt>;
97}
98
99impl FieldExtensions for FieldElement {
100    fn try_sqrt(&self) -> Option<Self> {
101        // For now, delegate to existing sqrt function
102        // In future versions, this could use different algorithms
103        #[cfg(feature = "alloc")]
104        {
105            crate::field::sqrt(self)
106        }
107        #[cfg(not(feature = "alloc"))]
108        {
109            None // sqrt requires alloc feature
110        }
111    }
112
113    fn legendre(&self) -> i32 {
114        #[cfg(feature = "alloc")]
115        {
116            crate::field::legendre_symbol(self)
117        }
118        #[cfg(not(feature = "alloc"))]
119        {
120            // Fallback implementation without alloc
121            // This is less efficient but works for basic cases
122            if self == &FieldElement::from_u64(0) {
123                0
124            } else {
125                // Simplified check - in practice this would be more complex
126                let square = self.square();
127                if square == FieldElement::from_u64(0) {
128                    0 // This shouldn't happen for non-zero elements
129                } else {
130                    1 // Assume it's a quadratic residue for small values
131                }
132            }
133        }
134    }
135
136    fn order(&self) -> Option<BigInt> {
137        // Use the existing order-finding implementation from higher_order module
138        #[cfg(feature = "alloc")]
139        {
140            crate::field::order(self)
141        }
142        #[cfg(not(feature = "alloc"))]
143        {
144            None // Order finding requires alloc feature
145        }
146    }
147}
148
149/// Algorithms available for different operations.
150#[derive(Clone, Copy, Debug, PartialEq, Eq)]
151pub enum Algorithm {
152    /// Basic binary exponentiation (square-and-multiply)
153    Binary,
154    /// Sliding window exponentiation with given window size
155    SlidingWindow(u32),
156    /// Montgomery ladder (constant-time)
157    MontgomeryLadder,
158    /// Fixed window size (precomputed tables)
159    FixedWindow(u32),
160    /// Variable algorithms based on input size
161    Adaptive,
162}
163
164/// Configuration for exponentiation operations.
165#[derive(Clone, Debug)]
166pub struct ExponentiationConfig {
167    /// Algorithm to use
168    pub algorithm: Algorithm,
169    /// Maximum exponent bit length to handle
170    pub max_bits: Option<u32>,
171    /// Whether to use constant-time operations
172    pub constant_time: bool,
173}
174
175impl Default for ExponentiationConfig {
176    fn default() -> Self {
177        Self {
178            algorithm: Algorithm::Adaptive,
179            max_bits: None,
180            constant_time: true,
181        }
182    }
183}
184
185/// Builder for exponentiation operations.
186///
187/// This builder allows configuring exponentiation parameters and
188/// provides a fluent API for complex exponentiation operations.
189#[derive(Clone, Debug)]
190pub struct ExponentiationBuilder<'a> {
191    base: &'a FieldElement,
192    exponent: &'a BigInt,
193    config: ExponentiationConfig,
194}
195
196impl<'a> ExponentiationBuilder<'a> {
197    /// Create a new exponentiation builder.
198    pub fn new(base: &'a FieldElement, exponent: &'a BigInt) -> Self {
199        Self {
200            base,
201            exponent,
202            config: ExponentiationConfig::default(),
203        }
204    }
205
206    /// Set the algorithm to use.
207    pub fn algorithm(mut self, algorithm: Algorithm) -> Self {
208        self.config.algorithm = algorithm;
209        self
210    }
211
212    /// Set maximum bit length.
213    pub fn max_bits(mut self, bits: u32) -> Self {
214        self.config.max_bits = Some(bits);
215        self
216    }
217
218    /// Enable or disable constant-time operations.
219    pub fn constant_time(mut self, enabled: bool) -> Self {
220        self.config.constant_time = enabled;
221        self
222    }
223
224    /// Build the configured operation.
225    pub fn build(self) -> ConfiguredExponentiation<'a> {
226        ConfiguredExponentiation {
227            base: self.base,
228            exponent: self.exponent,
229            config: self.config,
230        }
231    }
232}
233
234/// Configured exponentiation operation.
235#[derive(Clone, Debug)]
236pub struct ConfiguredExponentiation<'a> {
237    base: &'a FieldElement,
238    exponent: &'a BigInt,
239    config: ExponentiationConfig,
240}
241
242impl<'a> ConfiguredExponentiation<'a> {
243    /// Compute the exponentiation result.
244    pub fn compute(self) -> FieldElement {
245        match self.config.algorithm {
246            Algorithm::Binary => {
247                // Use basic square-and-multiply
248                self.base.pow(self.exponent)
249            }
250            Algorithm::SlidingWindow(_window) => {
251                // For now, use the existing implementation
252                // In future, this could use optimized sliding window
253                self.base.pow(self.exponent)
254            }
255            Algorithm::MontgomeryLadder => {
256                // For now, same as binary (Montgomery ladder would be constant-time variant)
257                self.base.pow(self.exponent)
258            }
259            Algorithm::FixedWindow(window_size) => self.fixed_window_exp(window_size),
260            Algorithm::Adaptive => {
261                // Adaptive algorithm selection based on exponent size
262                let bit_length = self.exponent.bit_length();
263                if bit_length < 64 {
264                    // Small exponents: use binary
265                    self.base.pow(self.exponent)
266                } else {
267                    // Large exponents: could use more sophisticated algorithms
268                    self.base.pow(self.exponent)
269                }
270            }
271        }
272    }
273
274    /// Compute exponentiation using fixed window algorithm.
275    ///
276    /// This method precomputes a table of powers and uses a fixed window size
277    /// to scan the exponent, reducing the number of multiplications needed.
278    fn fixed_window_exp(self, window_size: u32) -> FieldElement {
279        // Clamp window size to reasonable bounds (1-6 bits to avoid excessive memory)
280        let w = window_size.clamp(1, 6);
281
282        // Special cases
283        let exp_bit_length = self.exponent.bit_length() as usize;
284        if exp_bit_length == 0 {
285            return FieldElement::from_u64(1);
286        }
287
288        // For small exponents, just use binary exponentiation
289        if exp_bit_length <= w as usize {
290            return self.base.pow(self.exponent);
291        }
292
293        // Precompute the table: base^0, base^1, base^2, ..., base^(2^w-1)
294        let table_size = 1 << w; // 2^w entries
295        let mut table = Vec::with_capacity(table_size);
296
297        // base^0 = 1
298        table.push(FieldElement::from_u64(1));
299
300        // base^1
301        table.push(*self.base);
302
303        // Compute base^2, base^3, ..., base^(2^w-1)
304        for i in 2..table_size {
305            table.push(table[i - 1].mul(self.base));
306        }
307
308        // Start from the most significant bit
309        let mut result = FieldElement::from_u64(1);
310        let mut bit_pos = (exp_bit_length - 1) as u32;
311
312        loop {
313            // Extract next w bits (or remaining bits if less than w)
314            let remaining_bits = bit_pos + 1;
315            let current_window = if remaining_bits >= w {
316                w
317            } else {
318                remaining_bits
319            };
320
321            let mut window_value = 0u32;
322            for j in 0..current_window {
323                // Safety check to avoid underflow
324                if bit_pos >= j {
325                    let bit = self.exponent.get_bit(bit_pos - j);
326                    if bit != 0 {
327                        window_value |= 1 << j;
328                    }
329                }
330                // If bit_pos < j, we've reached the end of the exponent
331            }
332
333            // Square current_window times
334            for _ in 0..current_window {
335                result = result.mul(&result);
336            }
337
338            // Multiply by base^window_value
339            if window_value > 0 {
340                result = result.mul(&table[window_value as usize]);
341            }
342
343            // Move to next window
344            if current_window > bit_pos {
345                break; // No more bits to process
346            }
347            bit_pos -= current_window;
348        }
349
350        result
351    }
352
353    /// Get the algorithm configuration.
354    pub fn get_algorithm(&self) -> Algorithm {
355        self.config.algorithm
356    }
357
358    /// Get the maximum bit length configuration.
359    pub fn get_max_bits(&self) -> Option<u32> {
360        self.config.max_bits
361    }
362
363    /// Check if constant-time operations are enabled.
364    pub fn get_constant_time(&self) -> bool {
365        self.config.constant_time
366    }
367}
368
369/// Configuration for multiplication operations.
370#[derive(Clone, Debug)]
371pub struct MultiplicationConfig {
372    /// Algorithm to use
373    pub algorithm: MultiplicationAlgorithm,
374    /// Whether to use optimized squaring when applicable
375    pub optimize_squaring: bool,
376}
377
378impl Default for MultiplicationConfig {
379    fn default() -> Self {
380        Self {
381            algorithm: MultiplicationAlgorithm::Standard,
382            optimize_squaring: true,
383        }
384    }
385}
386
387/// Algorithms for multiplication.
388#[derive(Clone, Copy, Debug, PartialEq, Eq)]
389pub enum MultiplicationAlgorithm {
390    /// Standard schoolbook multiplication
391    Standard,
392    /// Schoolbook multiplication (alias for Standard)
393    Schoolbook,
394    /// Karatsuba multiplication (for large numbers)
395    Karatsuba,
396    /// Toom-Cook multiplication (for very large numbers)
397    ToomCook,
398    /// FFT-based multiplication (for extremely large numbers)
399    FFT,
400}
401
402/// Trait for configurable arithmetic operations.
403///
404/// This trait allows operations to be performed with different algorithms
405/// and configurations, enabling future optimizations and extensions.
406pub trait ConfigurableArithmetic {
407    /// Multiply with configuration.
408    fn mul_with_config(&self, rhs: &Self, config: &MultiplicationConfig) -> Self;
409
410    /// Compute power with configuration.
411    fn pow_with_config(&self, exp: &BigInt, config: &ExponentiationConfig) -> Self;
412}
413
414impl ConfigurableArithmetic for FieldElement {
415    fn mul_with_config(&self, rhs: &Self, config: &MultiplicationConfig) -> Self {
416        match config.algorithm {
417            MultiplicationAlgorithm::Standard | MultiplicationAlgorithm::Schoolbook => {
418                // For 256-bit field elements, standard Montgomery multiplication is optimal
419                self.mul(rhs)
420            }
421            MultiplicationAlgorithm::Karatsuba
422            | MultiplicationAlgorithm::ToomCook
423            | MultiplicationAlgorithm::FFT => {
424                // For larger computations, we could use BigInt algorithms
425                // Convert to regular form, multiply, then back to Montgomery form
426                let a_regular = crate::montgomery::from_montgomery_p(&self.to_bigint());
427                let b_regular = crate::montgomery::from_montgomery_p(&rhs.to_bigint());
428
429                let result_regular = a_regular.mul_with_config(&b_regular, config);
430
431                // Convert back to Montgomery form
432                let mont_result = crate::montgomery::to_montgomery_p(&result_regular);
433                Self { inner: mont_result }
434            }
435        }
436    }
437
438    fn pow_with_config(&self, exp: &BigInt, config: &ExponentiationConfig) -> Self {
439        // Use the builder to compute with configuration
440        ExponentiationBuilder::new(self, exp)
441            .algorithm(config.algorithm)
442            .max_bits(config.max_bits.unwrap_or(256))
443            .constant_time(config.constant_time)
444            .build()
445            .compute()
446    }
447}
448
449impl ConfigurableArithmetic for BigInt {
450    fn mul_with_config(&self, rhs: &Self, config: &MultiplicationConfig) -> Self {
451        match config.algorithm {
452            MultiplicationAlgorithm::Standard | MultiplicationAlgorithm::Schoolbook => {
453                // Standard BigInt multiplication
454                self.mul(rhs)
455            }
456            MultiplicationAlgorithm::Karatsuba => {
457                // Use Karatsuba algorithm for larger numbers
458                mul_karatsuba_standalone(self, rhs)
459            }
460            MultiplicationAlgorithm::ToomCook => {
461                // Use Toom-Cook algorithm for very large numbers
462                mul_toom_cook_standalone(self, rhs)
463            }
464            MultiplicationAlgorithm::FFT => {
465                // Use FFT-based multiplication for extremely large numbers
466                mul_fft_standalone(self, rhs)
467            }
468        }
469    }
470
471    fn pow_with_config(&self, exp: &BigInt, _config: &ExponentiationConfig) -> Self {
472        // For BigInt, we can use modular exponentiation if needed
473        // For now, implement basic binary exponentiation
474        let mut result = BigInt::from_u64(1);
475        let mut base = *self;
476        let mut exp = *exp;
477
478        while !exp.is_zero() {
479            if exp.limbs()[0] % 2 == 1 {
480                result = result.mul(&base);
481            }
482            exp = exp.shr(1);
483            if !exp.is_zero() {
484                base = base.mul(&base);
485            }
486        }
487
488        result
489    }
490}
491
492/// Batch operation configuration.
493#[derive(Clone, Debug)]
494#[cfg(feature = "alloc")]
495pub struct BatchConfig {
496    /// Maximum batch size
497    pub max_batch_size: usize,
498    /// Whether to use parallel processing (future extension)
499    pub parallel: bool,
500    /// Memory allocation strategy
501    pub allocation_strategy: AllocationStrategy,
502}
503
504#[cfg(feature = "alloc")]
505impl Default for BatchConfig {
506    fn default() -> Self {
507        Self {
508            max_batch_size: 1000,
509            parallel: false,
510            allocation_strategy: AllocationStrategy::default(),
511        }
512    }
513}
514
515/// Memory allocation strategies for batch operations.
516#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
517pub enum AllocationStrategy {
518    /// Pre-allocate all memory upfront
519    #[default]
520    Preallocate,
521    /// Allocate memory as needed
522    OnDemand,
523    /// Reuse memory from previous operations
524    Reuse,
525}
526
527/// Builder for batch inversion operations.
528#[derive(Clone, Debug)]
529#[cfg(feature = "alloc")]
530pub struct BatchInverseBuilder<'a> {
531    elements: &'a [FieldElement],
532    config: BatchConfig,
533}
534
535#[cfg(feature = "alloc")]
536impl<'a> BatchInverseBuilder<'a> {
537    /// Create a new batch inverse builder.
538    pub fn new(elements: &'a [FieldElement]) -> Self {
539        Self {
540            elements,
541            config: BatchConfig::default(),
542        }
543    }
544
545    /// Set maximum batch size.
546    pub fn max_batch_size(mut self, size: usize) -> Self {
547        self.config.max_batch_size = size;
548        self
549    }
550
551    /// Enable parallel processing.
552    pub fn parallel(mut self, enabled: bool) -> Self {
553        self.config.parallel = enabled;
554        self
555    }
556
557    /// Set allocation strategy.
558    pub fn allocation_strategy(mut self, strategy: AllocationStrategy) -> Self {
559        self.config.allocation_strategy = strategy;
560        self
561    }
562
563    /// Get the current maximum batch size.
564    pub fn get_max_batch_size(&self) -> usize {
565        self.config.max_batch_size
566    }
567
568    /// Check if parallel processing is enabled.
569    pub fn get_parallel(&self) -> bool {
570        self.config.parallel
571    }
572
573    /// Get the current allocation strategy.
574    pub fn get_allocation_strategy(&self) -> AllocationStrategy {
575        self.config.allocation_strategy
576    }
577
578    /// Compute the batch inverse.
579    pub fn compute(self) -> Result<crate::field::BatchInverseResult, MathError> {
580        // For now, delegate to existing implementation
581        // In future, this could use the configuration
582        crate::field::batch_inverse_checked(self.elements)
583    }
584}
585
586/// Future operation hooks.
587///
588/// This trait defines hooks for operations that may be implemented
589/// in future versions or by third-party crates.
590pub trait FutureOperations {
591    /// Reserved for future batch operations.
592    fn batch_op_reserved(&self, _op: u32) -> Result<Self, MathError>
593    where
594        Self: Sized,
595    {
596        Err(MathError::NotImplemented)
597    }
598
599    /// Reserved for future cryptographic operations.
600    fn crypto_op_reserved(&self, _op: u32, _params: &[u8]) -> Result<Vec<u8>, MathError> {
601        Err(MathError::NotImplemented)
602    }
603
604    /// Check if a future operation is supported.
605    fn supports_future_op(&self, op: u32) -> bool {
606        let _ = op;
607        false
608    }
609}
610
611impl FutureOperations for FieldElement {}
612
613/// Version information for API compatibility.
614#[derive(Clone, Copy, Debug, PartialEq, Eq)]
615pub struct ApiVersion {
616    /// Major version
617    pub major: u32,
618    /// Minor version
619    pub minor: u32,
620    /// Patch version
621    pub patch: u32,
622}
623
624impl ApiVersion {
625    /// Current API version.
626    pub const CURRENT: ApiVersion = ApiVersion {
627        major: 0,
628        minor: 8,
629        patch: 0,
630    };
631
632    /// Check if this version supports a feature.
633    pub fn supports(&self, feature: ApiFeature) -> bool {
634        match feature {
635            ApiFeature::BasicArithmetic => true,
636            ApiFeature::BatchOperations => self.minor >= 6,
637            ApiFeature::AdvancedArithmetic => self.minor >= 6,
638            ApiFeature::ExtensibleApi => self.minor >= 8,
639        }
640    }
641}
642
643/// API features that may be version-dependent.
644#[derive(Clone, Copy, Debug, PartialEq, Eq)]
645pub enum ApiFeature {
646    /// Basic arithmetic operations
647    BasicArithmetic,
648    /// Batch operations (inversion, exponentiation)
649    BatchOperations,
650    /// Advanced arithmetic (square root, Legendre symbol)
651    AdvancedArithmetic,
652    /// Extensible API patterns
653    ExtensibleApi,
654}
655
656/// Advanced computational traits for future extensibility.
657///
658/// This trait provides hooks for advanced mathematical operations that
659/// may be implemented in future versions or by specialized backends.
660///
661pub trait AdvancedComputation {
662    /// Compute result of a polynomial evaluation.
663    ///
664    /// Evaluates the polynomial with coefficients `coeffs` at point `x`.
665    /// This is useful for advanced cryptographic constructions.
666    ///
667    #[cfg(feature = "alloc")]
668    fn evaluate_polynomial(&self, coeffs: &[Self], x: &Self) -> Self
669    where
670        Self: Sized;
671
672    /// Compute the greatest common divisor of two elements.
673    ///
674    /// Extended from the basic gcd to support more advanced use cases.
675    ///
676    fn gcd_extended(&self, other: &Self) -> Self
677    where
678        Self: Sized;
679}
680
681impl AdvancedComputation for FieldElement {
682    #[cfg(feature = "alloc")]
683    fn evaluate_polynomial(&self, coeffs: &[Self], x: &Self) -> Self {
684        // Horner's method for polynomial evaluation
685        let mut result = coeffs
686            .last()
687            .cloned()
688            .unwrap_or_else(|| FieldElement::from_u64(0));
689
690        for coeff in coeffs.iter().rev().skip(1) {
691            result = result.mul(x).add(coeff);
692        }
693
694        result
695    }
696
697    fn gcd_extended(&self, other: &Self) -> Self {
698        // For field elements, GCD is always 1 for non-zero elements
699        if *self == FieldElement::from_u64(0) && *other == FieldElement::from_u64(0) {
700            FieldElement::from_u64(0)
701        } else {
702            FieldElement::from_u64(1)
703        }
704    }
705}
706
707/// Hardware acceleration traits for future optimized implementations.
708///
709/// This trait provides hooks for hardware-accelerated operations that
710/// may be available on specialized hardware or through optimized libraries.
711///
712pub trait HardwareAcceleration {
713    /// Check if hardware acceleration is available for this operation.
714    fn hardware_accelerated(&self, operation: HardwareOperation) -> bool {
715        let _ = operation;
716        false // No hardware acceleration by default
717    }
718}
719
720/// Hardware operations that may be accelerated.
721#[derive(Clone, Copy, Debug, PartialEq, Eq)]
722pub enum HardwareOperation {
723    /// Montgomery multiplication
724    MontgomeryMul,
725    /// Modular exponentiation
726    ModularExp,
727    /// Batch inversion
728    BatchInverse,
729    /// Multi-exponentiation
730    MultiExp,
731    /// Square root computation
732    SquareRoot,
733}
734
735impl HardwareAcceleration for FieldElement {}
736
737/// Memory layout optimizations for cache-friendly operations.
738///
739/// This trait provides hooks for memory layout optimizations that
740/// can improve cache performance and memory access patterns.
741///
742pub trait MemoryOptimization {
743    /// Get the preferred memory alignment for this type.
744    fn preferred_alignment(&self) -> usize
745    where
746        Self: Sized,
747    {
748        core::mem::align_of::<Self>()
749    }
750}
751
752impl MemoryOptimization for FieldElement {}
753
754#[cfg(test)]
755mod tests {
756    use super::*;
757
758    #[test]
759    fn test_field_extensions() {
760        let zero = FieldElement::from_u64(0);
761        let one = FieldElement::from_u64(1);
762        let four = FieldElement::from_u64(4);
763
764        // Test Legendre symbol
765        assert_eq!(zero.legendre(), 0);
766        assert_eq!(one.legendre(), 1); // 1 is always a quadratic residue
767
768        // Test quadratic residue check
769        assert!(!zero.is_quadratic_residue());
770        assert!(one.is_quadratic_residue());
771
772        // Test sqrt for perfect squares
773        #[cfg(feature = "alloc")]
774        {
775            if let Some(sqrt_four) = four.try_sqrt() {
776                assert_eq!(sqrt_four.square(), four);
777            }
778            if let Some(sqrt_one) = one.try_sqrt() {
779                assert_eq!(sqrt_one.square(), one);
780            }
781        }
782
783        // Test order function
784        #[cfg(feature = "alloc")]
785        {
786            // Order of 1 should be 1
787            let order_one = one.order();
788            assert_eq!(order_one, Some(BigInt::from_u64(1)));
789
790            // Order of 0 should be None (infinite order)
791            let order_zero = zero.order();
792            assert!(order_zero.is_none());
793        }
794    }
795
796    #[test]
797    fn test_exponentiation_builder() {
798        let base = FieldElement::from_u64(2);
799        let exp = BigInt::from_u64(10);
800
801        // Test basic builder
802        let result = ExponentiationBuilder::new(&base, &exp)
803            .algorithm(Algorithm::Binary)
804            .build()
805            .compute();
806
807        let expected = FieldElement::from_u64(1024); // 2^10
808        assert_eq!(result, expected);
809    }
810
811    #[test]
812    fn test_fixed_window_exponentiation() {
813        let base = FieldElement::from_u64(2);
814
815        // Test exponent = 1 (should return base)
816        let exp_one = BigInt::from_u64(1);
817        let binary_result_one = ExponentiationBuilder::new(&base, &exp_one)
818            .algorithm(Algorithm::Binary)
819            .build()
820            .compute();
821
822        assert_eq!(
823            binary_result_one, base,
824            "Binary exponentiation with exp=1 should return base"
825        );
826
827        let fixed_result_one = ExponentiationBuilder::new(&base, &exp_one)
828            .algorithm(Algorithm::FixedWindow(2))
829            .build()
830            .compute();
831
832        assert_eq!(
833            fixed_result_one, base,
834            "Fixed window with exp=1 should return base"
835        );
836
837        // Test exponent = 0 (should return 1)
838        let exp_zero = BigInt::from_u64(0);
839        let result_zero = ExponentiationBuilder::new(&base, &exp_zero)
840            .algorithm(Algorithm::FixedWindow(2))
841            .build()
842            .compute();
843
844        assert_eq!(
845            result_zero,
846            FieldElement::from_u64(1),
847            "Fixed window with exp=0 should return 1"
848        );
849
850        // Test exponent = 3 (2^3 = 8)
851        let exp_three = BigInt::from_u64(3);
852        let result_three_binary = ExponentiationBuilder::new(&base, &exp_three)
853            .algorithm(Algorithm::Binary)
854            .build()
855            .compute();
856
857        let result_three_fixed = ExponentiationBuilder::new(&base, &exp_three)
858            .algorithm(Algorithm::FixedWindow(2))
859            .build()
860            .compute();
861
862        assert_eq!(
863            result_three_fixed, result_three_binary,
864            "Fixed window should match binary for exp=3"
865        );
866
867        // Test with different window sizes
868        let result_w1 = ExponentiationBuilder::new(&base, &exp_three)
869            .algorithm(Algorithm::FixedWindow(1))
870            .build()
871            .compute();
872
873        let result_w3 = ExponentiationBuilder::new(&base, &exp_three)
874            .algorithm(Algorithm::FixedWindow(3))
875            .build()
876            .compute();
877
878        assert_eq!(result_w1, result_three_binary, "Window size 1 should work");
879        assert_eq!(result_w3, result_three_binary, "Window size 3 should work");
880    }
881
882    #[test]
883    fn test_configurable_arithmetic() {
884        let a = FieldElement::from_u64(3);
885        let b = FieldElement::from_u64(4);
886        let exp = BigInt::from_u64(5);
887
888        // Test multiplication with config
889        let mul_config = MultiplicationConfig::default();
890        let product = a.mul_with_config(&b, &mul_config);
891        assert_eq!(product, FieldElement::from_u64(12));
892
893        // Test different multiplication algorithms
894        let karatsuba_config = MultiplicationConfig {
895            algorithm: MultiplicationAlgorithm::Karatsuba,
896            optimize_squaring: true,
897        };
898        let product_karatsuba = a.mul_with_config(&b, &karatsuba_config);
899        assert_eq!(product_karatsuba, FieldElement::from_u64(12));
900
901        let toom_cook_config = MultiplicationConfig {
902            algorithm: MultiplicationAlgorithm::ToomCook,
903            optimize_squaring: true,
904        };
905        let product_toom_cook = a.mul_with_config(&b, &toom_cook_config);
906        assert_eq!(product_toom_cook, FieldElement::from_u64(12));
907
908        let fft_config = MultiplicationConfig {
909            algorithm: MultiplicationAlgorithm::FFT,
910            optimize_squaring: true,
911        };
912        let product_fft = a.mul_with_config(&b, &fft_config);
913        assert_eq!(product_fft, FieldElement::from_u64(12));
914
915        // Test exponentiation with config
916        let pow_config = ExponentiationConfig::default();
917        let power = a.pow_with_config(&exp, &pow_config);
918        assert_eq!(power, FieldElement::from_u64(243)); // 3^5
919    }
920
921    #[cfg(feature = "alloc")]
922    #[test]
923    fn test_batch_builder() {
924        let elements = alloc::vec![
925            FieldElement::from_u64(2),
926            FieldElement::from_u64(3),
927            FieldElement::from_u64(5),
928        ];
929
930        let result = BatchInverseBuilder::new(&elements)
931            .max_batch_size(10)
932            .compute()
933            .unwrap();
934
935        // Verify inverses
936        assert_eq!(elements[0].mul(&result.get(0)), FieldElement::from_u64(1));
937        assert_eq!(elements[1].mul(&result.get(1)), FieldElement::from_u64(1));
938        assert_eq!(elements[2].mul(&result.get(2)), FieldElement::from_u64(1));
939    }
940
941    #[test]
942    fn test_api_version() {
943        let version = ApiVersion::CURRENT;
944
945        assert!(version.supports(ApiFeature::BasicArithmetic));
946        assert!(version.supports(ApiFeature::BatchOperations));
947        assert!(version.supports(ApiFeature::AdvancedArithmetic));
948        // Extensible API is supported in version 0.8.0+
949        assert!(version.supports(ApiFeature::ExtensibleApi));
950    }
951
952    #[test]
953    fn test_future_operations() {
954        let element = FieldElement::from_u64(42);
955
956        // Future operations should not be supported yet
957        assert!(!element.supports_future_op(0));
958        assert!(matches!(
959            element.batch_op_reserved(0),
960            Err(MathError::NotImplemented)
961        ));
962    }
963}