Skip to main content

big_number/
big_number.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[cfg(feature = "alloc")]
4extern crate alloc;
5
6#[cfg(feature = "alloc")]
7use alloc::{string::String, vec::Vec};
8use core::{
9    fmt,
10    ops::{Add, Div, Mul, Neg, Rem, Sub},
11};
12
13pub const MAX_LIMBS: usize = 64;
14
15const fn max_limbs<const BITS: usize, const LIMBS: usize>() -> [u64; LIMBS] {
16    let mut limbs = [u64::MAX; LIMBS];
17    let rem = BITS % 64;
18    if rem != 0 {
19        limbs[LIMBS - 1] = (1u64 << rem) - 1;
20    }
21    limbs
22}
23
24#[derive(Clone, Copy, PartialEq, Eq)]
25pub struct Uint<const BITS: usize, const LIMBS: usize> {
26    pub limbs: [u64; LIMBS],
27}
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq)]
30pub struct Int<const BITS: usize, const LIMBS: usize>(Uint<BITS, LIMBS>);
31
32#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub enum Error {
34    InvalidRadix,
35    InvalidDigit,
36    EmptyString,
37    Overflow,
38}
39
40#[inline]
41pub const fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) {
42    let sum = (a as u128) + (b as u128) + (carry as u128);
43    (sum as u64, (sum >> 64) as u64)
44}
45
46#[inline]
47pub const fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) {
48    let diff = (1u128 << 64) + (a as u128) - (b as u128) - (borrow as u128);
49    (diff as u64, 1u64.wrapping_sub((diff >> 64) as u64))
50}
51
52#[inline]
53pub const fn mac(acc: u64, a: u64, b: u64, carry: u64) -> (u64, u64) {
54    let value = (acc as u128) + (a as u128) * (b as u128) + (carry as u128);
55    (value as u64, (value >> 64) as u64)
56}
57
58fn mul_limbs(out: &mut [u64], a: &[u64], a_len: usize, b: &[u64], b_len: usize) {
59    for i in 0..a_len {
60        let mut carry = 0u64;
61        for j in 0..b_len {
62            let (word, next_carry) = mac(out[i + j], a[i], b[j], carry);
63            out[i + j] = word;
64            carry = next_carry;
65        }
66        let mut k = i + b_len;
67        while carry != 0 {
68            let (word, next_carry) = adc(out[k], 0, carry);
69            out[k] = word;
70            carry = next_carry;
71            k += 1;
72        }
73    }
74}
75
76#[inline]
77const fn ct_select_u64(a: u64, b: u64, choice: bool) -> u64 {
78    let mask = 0u64.wrapping_sub(choice as u64);
79    b ^ ((a ^ b) & mask)
80}
81
82#[inline]
83const fn digit_to_char(digit: u64, upper: bool) -> char {
84    match digit {
85        0..=9 => (b'0' + digit as u8) as char,
86        _ if upper => (b'A' + (digit as u8 - 10)) as char,
87        _ => (b'a' + (digit as u8 - 10)) as char,
88    }
89}
90
91#[inline]
92fn char_to_digit(byte: u8) -> Option<u32> {
93    match byte {
94        b'0'..=b'9' => Some((byte - b'0') as u32),
95        b'a'..=b'z' => Some((byte - b'a' + 10) as u32),
96        b'A'..=b'Z' => Some((byte - b'A' + 10) as u32),
97        _ => None,
98    }
99}
100
101const fn uint_from_u128<const BITS: usize, const LIMBS: usize>(value: u128) -> Uint<BITS, LIMBS> {
102    let mut limbs = [0u64; LIMBS];
103    if LIMBS > 0 {
104        limbs[0] = value as u64;
105    }
106    if LIMBS > 1 {
107        limbs[1] = (value >> 64) as u64;
108    }
109    Uint {
110        limbs,
111    }
112}
113
114fn u128_to_word(value: u128) -> u64 {
115    u64::try_from(value).expect("primitive operand exceeds u64")
116}
117
118fn i128_abs_to_word(value: i128) -> (u64, bool) {
119    (u128_to_word(value.unsigned_abs()), value.is_negative())
120}
121
122impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
123    const _LIMBS_CHECK: () = assert!(LIMBS == (BITS + 63) / 64, "LIMBS must equal ceil(BITS/64)");
124
125    pub const ZERO: Self = Self {
126        limbs: [0u64; LIMBS],
127    };
128    pub const ONE: Self = Self::from_u64(1);
129    pub const MAX: Self = Self {
130        limbs: max_limbs::<BITS, LIMBS>(),
131    };
132
133    #[inline]
134    pub const fn from_limbs(limbs: [u64; LIMBS]) -> Self {
135        Self {
136            limbs,
137        }
138    }
139
140    #[inline]
141    pub const fn from_u64(v: u64) -> Self {
142        let mut limbs = [0u64; LIMBS];
143        if LIMBS > 0 {
144            limbs[0] = v;
145        }
146        Self {
147            limbs,
148        }
149    }
150
151    #[inline]
152    pub fn from_be_slice(bytes: &[u8]) -> Self {
153        assert_eq!(bytes.len(), BITS / 8);
154        let mut limbs = [0u64; LIMBS];
155        let mut i = 0;
156        while i < LIMBS {
157            let start = bytes.len() - ((i + 1) * 8);
158            let mut limb = [0u8; 8];
159            limb.copy_from_slice(&bytes[start..start + 8]);
160            limbs[i] = u64::from_be_bytes(limb);
161            i += 1;
162        }
163        Self {
164            limbs,
165        }
166    }
167
168    #[inline]
169    pub fn from_le_slice(bytes: &[u8]) -> Self {
170        assert_eq!(bytes.len(), BITS / 8);
171        let mut limbs = [0u64; LIMBS];
172        let mut i = 0;
173        while i < LIMBS {
174            let start = i * 8;
175            let mut limb = [0u8; 8];
176            limb.copy_from_slice(&bytes[start..start + 8]);
177            limbs[i] = u64::from_le_bytes(limb);
178            i += 1;
179        }
180        Self {
181            limbs,
182        }
183    }
184
185    #[cfg(feature = "alloc")]
186    #[inline]
187    pub fn to_be_bytes(&self) -> Vec<u8> {
188        let mut out = Vec::with_capacity(BITS / 8);
189        let mut i = LIMBS;
190        while i > 0 {
191            i -= 1;
192            out.extend_from_slice(&self.limbs[i].to_be_bytes());
193        }
194        out
195    }
196
197    #[cfg(feature = "alloc")]
198    #[inline]
199    pub fn to_le_bytes(&self) -> Vec<u8> {
200        let mut out = Vec::with_capacity(BITS / 8);
201        let mut i = 0;
202        while i < LIMBS {
203            out.extend_from_slice(&self.limbs[i].to_le_bytes());
204            i += 1;
205        }
206        out
207    }
208
209    #[inline]
210    pub fn to_be_bytes_fixed<const N: usize>(&self) -> [u8; N] {
211        assert_eq!(N, BITS / 8);
212        let mut out = [0u8; N];
213        let mut i = 0;
214        while i < LIMBS {
215            let start = N - ((i + 1) * 8);
216            out[start..start + 8].copy_from_slice(&self.limbs[i].to_be_bytes());
217            i += 1;
218        }
219        out
220    }
221
222    #[inline]
223    pub fn to_le_bytes_fixed<const N: usize>(&self) -> [u8; N] {
224        assert_eq!(N, BITS / 8);
225        let mut out = [0u8; N];
226        let mut i = 0;
227        while i < LIMBS {
228            let start = i * 8;
229            out[start..start + 8].copy_from_slice(&self.limbs[i].to_le_bytes());
230            i += 1;
231        }
232        out
233    }
234
235    #[inline]
236    pub fn bit(&self, index: usize) -> bool {
237        if index >= BITS {
238            return false;
239        }
240        ((self.limbs[index / 64] >> (index % 64)) & 1) == 1
241    }
242
243    #[inline]
244    pub fn is_zero(&self) -> bool {
245        let mut acc = 0u64;
246        let mut i = 0;
247        while i < LIMBS {
248            acc |= self.limbs[i];
249            i += 1;
250        }
251        acc == 0
252    }
253
254    #[inline]
255    pub fn is_odd(&self) -> bool {
256        (self.limbs[0] & 1) == 1
257    }
258
259    #[inline]
260    pub fn ct_ge(&self, rhs: &Self) -> bool {
261        let (_, borrow) = self.sub_raw(rhs);
262        borrow == 0
263    }
264
265    #[inline]
266    pub fn ct_eq(&self, rhs: &Self) -> bool {
267        let mut diff = 0u64;
268        let mut i = 0;
269        while i < LIMBS {
270            diff |= self.limbs[i] ^ rhs.limbs[i];
271            i += 1;
272        }
273        diff == 0
274    }
275
276    #[inline]
277    pub fn ct_select(a: &Self, b: &Self, choice: bool) -> Self {
278        let mut limbs = [0u64; LIMBS];
279        let mut i = 0;
280        while i < LIMBS {
281            limbs[i] = ct_select_u64(a.limbs[i], b.limbs[i], choice);
282            i += 1;
283        }
284        Self {
285            limbs,
286        }
287    }
288
289    #[inline]
290    pub fn add_raw(&self, rhs: &Self) -> (Self, u64) {
291        let mut out = [0u64; LIMBS];
292        let mut carry = 0u64;
293        let mut i = 0;
294        while i < LIMBS {
295            let (word, next_carry) = adc(self.limbs[i], rhs.limbs[i], carry);
296            out[i] = word;
297            carry = next_carry;
298            i += 1;
299        }
300        (
301            Self {
302                limbs: out,
303            },
304            carry,
305        )
306    }
307
308    #[inline]
309    pub fn sub_raw(&self, rhs: &Self) -> (Self, u64) {
310        let mut out = [0u64; LIMBS];
311        let mut borrow = 0u64;
312        let mut i = 0;
313        while i < LIMBS {
314            let (word, next_borrow) = sbb(self.limbs[i], rhs.limbs[i], borrow);
315            out[i] = word;
316            borrow = next_borrow;
317            i += 1;
318        }
319        (
320            Self {
321                limbs: out,
322            },
323            borrow,
324        )
325    }
326
327    #[inline]
328    pub fn add_mod(&self, rhs: &Self, modulus: &Self) -> Self {
329        let (sum, carry) = self.add_raw(rhs);
330        let (reduced, borrow) = sum.sub_raw(modulus);
331        // Use bitwise OR to avoid short-circuit branching on secret carry/borrow bits.
332        // Reduce when carry==1 (overflow) OR borrow==0 (sum >= modulus).
333        Self::ct_select(&reduced, &sum, (carry | (borrow ^ 1)) != 0)
334    }
335
336    #[inline]
337    pub fn sub_mod(&self, rhs: &Self, modulus: &Self) -> Self {
338        let (diff, borrow) = self.sub_raw(rhs);
339        let (corrected, _) = diff.add_raw(modulus);
340        Self::ct_select(&corrected, &diff, borrow == 1)
341    }
342
343    #[inline]
344    pub fn double_mod(&self, modulus: &Self) -> Self {
345        self.add_mod(self, modulus)
346    }
347
348    fn mul_wide_internal(&self, rhs: &Self) -> [u64; MAX_LIMBS] {
349        assert!(LIMBS * 2 <= MAX_LIMBS);
350        let mut out = [0u64; MAX_LIMBS];
351        let mut i = 0;
352        while i < LIMBS {
353            let mut carry = 0u64;
354            let mut j = 0;
355            while j < LIMBS {
356                let (word, next_carry) = mac(out[i + j], self.limbs[i], rhs.limbs[j], carry);
357                out[i + j] = word;
358                carry = next_carry;
359                j += 1;
360            }
361            let mut k = i + LIMBS;
362            while k < MAX_LIMBS {
363                let (word, next_carry) = adc(out[k], 0, carry);
364                out[k] = word;
365                carry = next_carry;
366                k += 1;
367            }
368            i += 1;
369        }
370        out
371    }
372
373    fn reduce_wide_internal(product: &[u64; MAX_LIMBS], modulus: &Self) -> Self {
374        let total_bits = LIMBS * 128;
375        let mut rem = Self::ZERO;
376        let mut bit_index = total_bits;
377        while bit_index > 0 {
378            bit_index -= 1;
379            let limb_idx = bit_index / 64;
380            let bit_pos = bit_index % 64;
381            let bit = ((product[limb_idx] >> bit_pos) & 1) as u64;
382
383            let mut shifted = [0u64; LIMBS];
384            let mut carry = bit;
385            let mut i = 0;
386            while i < LIMBS {
387                let next = rem.limbs[i] >> 63;
388                shifted[i] = (rem.limbs[i] << 1) | carry;
389                carry = next;
390                i += 1;
391            }
392            let shifted_rem = Self {
393                limbs: shifted,
394            };
395            let (reduced, borrow) = shifted_rem.sub_raw(modulus);
396            // Use bitwise OR to avoid short-circuit branching on secret carry/borrow bits.
397            rem = Self::ct_select(&reduced, &shifted_rem, (carry | (borrow ^ 1)) != 0);
398        }
399        rem
400    }
401
402    #[inline]
403    pub fn mul_mod(&self, rhs: &Self, modulus: &Self) -> Self {
404        let product = self.mul_wide_internal(rhs);
405        Self::reduce_wide_internal(&product, modulus)
406    }
407
408    /// Barrett reduction of a 2*LIMBS-wide product modulo `modulus`.
409    ///
410    /// `mu` must equal `floor(2^(2*LIMBS*64) / modulus)` and have `LIMBS+1` limbs.
411    pub fn reduce_wide_barrett<const MU_LIMBS: usize>(
412        product: &[u64; MAX_LIMBS],
413        modulus: &Self,
414        mu: &[u64; MU_LIMBS],
415    ) -> Self {
416        assert!(MU_LIMBS == LIMBS + 1);
417
418        let k = LIMBS;
419        let k1 = k + 1;
420        let k_minus_1 = k - 1;
421
422        let mut q1 = [0u64; MAX_LIMBS];
423        q1[..k1].copy_from_slice(&product[k_minus_1..k_minus_1 + k1]);
424
425        let mut q2 = [0u64; MAX_LIMBS];
426        mul_limbs(&mut q2, &q1, k1, mu, k1);
427
428        let mut q3 = [0u64; MAX_LIMBS];
429        q3[..k1].copy_from_slice(&q2[k1..k1 + k1]);
430
431        let mut r1 = [0u64; MAX_LIMBS];
432        r1[..k1].copy_from_slice(&product[..k1]);
433
434        let mut q3m = [0u64; MAX_LIMBS];
435        mul_limbs(&mut q3m, &q3[..k1], k1, &modulus.limbs, k);
436        let mut r2 = [0u64; MAX_LIMBS];
437        r2[..k1].copy_from_slice(&q3m[..k1]);
438
439        let mut r = [0u64; MAX_LIMBS];
440        let mut borrow = 0u64;
441        let mut i = 0;
442        while i < k1 {
443            let (word, next_borrow) = sbb(r1[i], r2[i], borrow);
444            r[i] = word;
445            borrow = next_borrow;
446            i += 1;
447        }
448
449        let mut limbs = [0u64; LIMBS];
450        limbs.copy_from_slice(&r[..LIMBS]);
451        let mut result = Self {
452            limbs,
453        };
454
455        let (d1, b1) = result.sub_raw(modulus);
456        result = Self::ct_select(&d1, &result, b1 == 0);
457        let (d2, b2) = result.sub_raw(modulus);
458        result = Self::ct_select(&d2, &result, b2 == 0);
459
460        result
461    }
462
463    /// Modular multiplication using Barrett reduction.
464    ///
465    /// `mu` must equal `floor(2^(2*LIMBS*64) / modulus)` and have `LIMBS+1` limbs.
466    pub fn mul_mod_barrett<const MU_LIMBS: usize>(&self, rhs: &Self, modulus: &Self, mu: &[u64; MU_LIMBS]) -> Self {
467        let product = self.mul_wide_internal(rhs);
468        Self::reduce_wide_barrett(&product, modulus, mu)
469    }
470
471    #[inline]
472    pub fn add_word(&self, word: u64) -> (Self, u64) {
473        let mut out = self.limbs;
474        let (first, mut carry) = adc(out[0], word, 0);
475        out[0] = first;
476        let mut i = 1;
477        while i < LIMBS {
478            let (next, next_carry) = adc(out[i], 0, carry);
479            out[i] = next;
480            carry = next_carry;
481            i += 1;
482        }
483        (
484            Self {
485                limbs: out,
486            },
487            carry,
488        )
489    }
490
491    #[inline]
492    pub fn sub_word(&self, word: u64) -> (Self, u64) {
493        let mut out = self.limbs;
494        let (first, mut borrow) = sbb(out[0], word, 0);
495        out[0] = first;
496        let mut i = 1;
497        while i < LIMBS {
498            let (next, next_borrow) = sbb(out[i], 0, borrow);
499            out[i] = next;
500            borrow = next_borrow;
501            i += 1;
502        }
503        (
504            Self {
505                limbs: out,
506            },
507            borrow,
508        )
509    }
510
511    #[inline]
512    pub fn mul_word(&self, word: u64) -> (Self, u64) {
513        let mut out = [0u64; LIMBS];
514        let mut carry = 0u64;
515        let mut i = 0;
516        while i < LIMBS {
517            let (next, next_carry) = mac(0, self.limbs[i], word, carry);
518            out[i] = next;
519            carry = next_carry;
520            i += 1;
521        }
522        (
523            Self {
524                limbs: out,
525            },
526            carry,
527        )
528    }
529
530    #[inline]
531    pub fn div_rem_word(&self, word: u64) -> (Self, u64) {
532        assert!(word != 0, "division by zero");
533        let mut out = [0u64; LIMBS];
534        let mut rem = 0u64;
535        let mut i = LIMBS;
536        while i > 0 {
537            i -= 1;
538            let dividend = ((rem as u128) << 64) | self.limbs[i] as u128;
539            out[i] = (dividend / word as u128) as u64;
540            rem = (dividend % word as u128) as u64;
541        }
542        (
543            Self {
544                limbs: out,
545            },
546            rem,
547        )
548    }
549
550    pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, Error> {
551        if !(2..=36).contains(&radix) {
552            return Err(Error::InvalidRadix);
553        }
554        if src.is_empty() {
555            return Err(Error::EmptyString);
556        }
557
558        let mut out = Self::ZERO;
559        for byte in src.bytes() {
560            let digit = char_to_digit(byte).ok_or(Error::InvalidDigit)?;
561            if digit >= radix {
562                return Err(Error::InvalidDigit);
563            }
564            let (mul, high) = out.mul_word(radix as u64);
565            if high != 0 {
566                return Err(Error::Overflow);
567            }
568            let (next, carry) = mul.add_word(digit as u64);
569            if carry != 0 {
570                return Err(Error::Overflow);
571            }
572            out = next;
573        }
574        Ok(out)
575    }
576
577    #[cfg(feature = "alloc")]
578    pub fn to_string_radix(&self, radix: u32) -> String {
579        assert!((2..=36).contains(&radix), "invalid radix");
580        if self.is_zero() {
581            return String::from("0");
582        }
583
584        let mut value = *self;
585        let mut digits = Vec::new();
586        while !value.is_zero() {
587            let (quotient, remainder) = value.div_rem_word(radix as u64);
588            digits.push(digit_to_char(remainder, false));
589            value = quotient;
590        }
591        digits.into_iter().rev().collect()
592    }
593}
594
595#[cfg(feature = "alloc")]
596impl<const BITS: usize, const LIMBS: usize> fmt::Display for Uint<BITS, LIMBS> {
597    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
598        write!(f, "{}", self.to_string_radix(10))
599    }
600}
601
602impl<const BITS: usize, const LIMBS: usize> fmt::LowerHex for Uint<BITS, LIMBS> {
603    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
604        if f.alternate() {
605            f.write_str("0x")?;
606        }
607        let mut started = false;
608        let mut i = LIMBS;
609        while i > 0 {
610            i -= 1;
611            let limb = self.limbs[i];
612            if started {
613                write!(f, "{limb:016x}")?;
614            } else if limb != 0 {
615                write!(f, "{limb:x}")?;
616                started = true;
617            }
618        }
619        if !started {
620            f.write_str("0")?;
621        }
622        Ok(())
623    }
624}
625
626impl<const BITS: usize, const LIMBS: usize> fmt::UpperHex for Uint<BITS, LIMBS> {
627    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
628        if f.alternate() {
629            f.write_str("0x")?;
630        }
631        let mut started = false;
632        let mut i = LIMBS;
633        while i > 0 {
634            i -= 1;
635            let limb = self.limbs[i];
636            if started {
637                write!(f, "{limb:016X}")?;
638            } else if limb != 0 {
639                write!(f, "{limb:X}")?;
640                started = true;
641            }
642        }
643        if !started {
644            f.write_str("0")?;
645        }
646        Ok(())
647    }
648}
649
650impl<const BITS: usize, const LIMBS: usize> fmt::Debug for Uint<BITS, LIMBS> {
651    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
652        write!(f, "Uint(0x{self:x})")
653    }
654}
655
656impl<const BITS: usize, const LIMBS: usize> Int<BITS, LIMBS> {
657    const _LIMBS_CHECK: () = assert!(LIMBS == (BITS + 63) / 64, "LIMBS must equal ceil(BITS/64)");
658
659    pub const ZERO: Self = Self(Uint::ZERO);
660    pub const ONE: Self = Self(Uint::ONE);
661    pub const MINUS_ONE: Self = Self(Uint::MAX);
662
663    #[inline]
664    const fn from_uint_bits(bits: Uint<BITS, LIMBS>) -> Self {
665        Self(bits)
666    }
667
668    #[inline]
669    fn from_u128(value: u128) -> Self {
670        Self(uint_from_u128(value))
671    }
672
673    #[inline]
674    fn from_i128(value: i128) -> Self {
675        if value.is_negative() {
676            let magnitude = uint_from_u128::<BITS, LIMBS>(value.unsigned_abs());
677            Self(Self::ZERO.0.sub_raw(&magnitude).0)
678        } else {
679            Self(uint_from_u128(value as u128))
680        }
681    }
682
683    #[inline]
684    pub fn is_negative(&self) -> bool {
685        (self.0.limbs[LIMBS - 1] >> 63) == 1
686    }
687
688    #[inline]
689    pub fn abs(&self) -> Uint<BITS, LIMBS> {
690        if self.is_negative() {
691            Self::ZERO.0.sub_raw(&self.0).0
692        } else {
693            self.0
694        }
695    }
696}
697
698impl<const BITS: usize, const LIMBS: usize> Add for Uint<BITS, LIMBS> {
699    type Output = Self;
700
701    fn add(self, rhs: Self) -> Self::Output {
702        self.add_raw(&rhs).0
703    }
704}
705
706impl<const BITS: usize, const LIMBS: usize> Sub for Uint<BITS, LIMBS> {
707    type Output = Self;
708
709    fn sub(self, rhs: Self) -> Self::Output {
710        self.sub_raw(&rhs).0
711    }
712}
713
714impl<const BITS: usize, const LIMBS: usize> Mul for Uint<BITS, LIMBS> {
715    type Output = Self;
716
717    fn mul(self, rhs: Self) -> Self::Output {
718        let product = self.mul_wide_internal(&rhs);
719        let mut limbs = [0u64; LIMBS];
720        let mut i = 0;
721        while i < LIMBS {
722            limbs[i] = product[i];
723            i += 1;
724        }
725        Self {
726            limbs,
727        }
728    }
729}
730
731impl<const BITS: usize, const LIMBS: usize> Add for Int<BITS, LIMBS> {
732    type Output = Self;
733
734    fn add(self, rhs: Self) -> Self::Output {
735        Self::from_uint_bits(self.0.add_raw(&rhs.0).0)
736    }
737}
738
739impl<const BITS: usize, const LIMBS: usize> Sub for Int<BITS, LIMBS> {
740    type Output = Self;
741
742    fn sub(self, rhs: Self) -> Self::Output {
743        Self::from_uint_bits(self.0.sub_raw(&rhs.0).0)
744    }
745}
746
747impl<const BITS: usize, const LIMBS: usize> Neg for Int<BITS, LIMBS> {
748    type Output = Self;
749
750    fn neg(self) -> Self::Output {
751        Self::from_uint_bits(Int::ZERO.0.sub_raw(&self.0).0)
752    }
753}
754
755macro_rules! impl_uint_ops_unsigned {
756    ($($ty:ty),* $(,)?) => {
757        $(
758            impl<const BITS: usize, const LIMBS: usize> Add<$ty> for Uint<BITS, LIMBS> {
759                type Output = Self;
760                fn add(self, rhs: $ty) -> Self::Output {
761                    self.add_word(u128_to_word(rhs as u128)).0
762                }
763            }
764
765            impl<const BITS: usize, const LIMBS: usize> Sub<$ty> for Uint<BITS, LIMBS> {
766                type Output = Self;
767                fn sub(self, rhs: $ty) -> Self::Output {
768                    self.sub_word(u128_to_word(rhs as u128)).0
769                }
770            }
771
772            impl<const BITS: usize, const LIMBS: usize> Mul<$ty> for Uint<BITS, LIMBS> {
773                type Output = Self;
774                fn mul(self, rhs: $ty) -> Self::Output {
775                    self.mul_word(u128_to_word(rhs as u128)).0
776                }
777            }
778
779            impl<const BITS: usize, const LIMBS: usize> Div<$ty> for Uint<BITS, LIMBS> {
780                type Output = Self;
781                fn div(self, rhs: $ty) -> Self::Output {
782                    self.div_rem_word(u128_to_word(rhs as u128)).0
783                }
784            }
785
786            impl<const BITS: usize, const LIMBS: usize> Rem<$ty> for Uint<BITS, LIMBS> {
787                type Output = u64;
788                fn rem(self, rhs: $ty) -> Self::Output {
789                    self.div_rem_word(u128_to_word(rhs as u128)).1
790                }
791            }
792        )*
793    };
794}
795
796macro_rules! impl_uint_ops_signed {
797    ($($ty:ty),* $(,)?) => {
798        $(
799            impl<const BITS: usize, const LIMBS: usize> Add<$ty> for Uint<BITS, LIMBS> {
800                type Output = Self;
801                fn add(self, rhs: $ty) -> Self::Output {
802                    let (word, negative) = i128_abs_to_word(rhs as i128);
803                    if negative {
804                        self.sub_word(word).0
805                    } else {
806                        self.add_word(word).0
807                    }
808                }
809            }
810
811            impl<const BITS: usize, const LIMBS: usize> Sub<$ty> for Uint<BITS, LIMBS> {
812                type Output = Self;
813                fn sub(self, rhs: $ty) -> Self::Output {
814                    let (word, negative) = i128_abs_to_word(rhs as i128);
815                    if negative {
816                        self.add_word(word).0
817                    } else {
818                        self.sub_word(word).0
819                    }
820                }
821            }
822
823            impl<const BITS: usize, const LIMBS: usize> Mul<$ty> for Uint<BITS, LIMBS> {
824                type Output = Self;
825                fn mul(self, rhs: $ty) -> Self::Output {
826                    self.mul_word(i128_abs_to_word(rhs as i128).0).0
827                }
828            }
829
830            impl<const BITS: usize, const LIMBS: usize> Div<$ty> for Uint<BITS, LIMBS> {
831                type Output = Self;
832                fn div(self, rhs: $ty) -> Self::Output {
833                    self.div_rem_word(i128_abs_to_word(rhs as i128).0).0
834                }
835            }
836
837            impl<const BITS: usize, const LIMBS: usize> Rem<$ty> for Uint<BITS, LIMBS> {
838                type Output = u64;
839                fn rem(self, rhs: $ty) -> Self::Output {
840                    self.div_rem_word(i128_abs_to_word(rhs as i128).0).1
841                }
842            }
843        )*
844    };
845}
846
847macro_rules! impl_int_ops_unsigned {
848    ($($ty:ty),* $(,)?) => {
849        $(
850            impl<const BITS: usize, const LIMBS: usize> Add<$ty> for Int<BITS, LIMBS> {
851                type Output = Self;
852                fn add(self, rhs: $ty) -> Self::Output {
853                    self + Self::from_u128(rhs as u128)
854                }
855            }
856
857            impl<const BITS: usize, const LIMBS: usize> Sub<$ty> for Int<BITS, LIMBS> {
858                type Output = Self;
859                fn sub(self, rhs: $ty) -> Self::Output {
860                    self - Self::from_u128(rhs as u128)
861                }
862            }
863
864            impl<const BITS: usize, const LIMBS: usize> Mul<$ty> for Int<BITS, LIMBS> {
865                type Output = Self;
866                fn mul(self, rhs: $ty) -> Self::Output {
867                    let (product, _) = self.abs().mul_word(u128_to_word(rhs as u128));
868                    let bits = if self.is_negative() {
869                        Uint::ZERO.sub_raw(&product).0
870                    } else {
871                        product
872                    };
873                    Self::from_uint_bits(bits)
874                }
875            }
876
877            impl<const BITS: usize, const LIMBS: usize> Div<$ty> for Int<BITS, LIMBS> {
878                type Output = Self;
879                fn div(self, rhs: $ty) -> Self::Output {
880                    let (quotient, _) = self.abs().div_rem_word(u128_to_word(rhs as u128));
881                    let bits = if self.is_negative() {
882                        Uint::ZERO.sub_raw(&quotient).0
883                    } else {
884                        quotient
885                    };
886                    Self::from_uint_bits(bits)
887                }
888            }
889
890            impl<const BITS: usize, const LIMBS: usize> Rem<$ty> for Int<BITS, LIMBS> {
891                type Output = Self;
892                fn rem(self, rhs: $ty) -> Self::Output {
893                    let (_, remainder) = self.abs().div_rem_word(u128_to_word(rhs as u128));
894                    let bits = Uint::from_u64(remainder);
895                    let bits = if self.is_negative() {
896                        Uint::ZERO.sub_raw(&bits).0
897                    } else {
898                        bits
899                    };
900                    Self::from_uint_bits(bits)
901                }
902            }
903        )*
904    };
905}
906
907macro_rules! impl_int_ops_signed {
908    ($($ty:ty),* $(,)?) => {
909        $(
910            impl<const BITS: usize, const LIMBS: usize> Add<$ty> for Int<BITS, LIMBS> {
911                type Output = Self;
912                fn add(self, rhs: $ty) -> Self::Output {
913                    self + Self::from_i128(rhs as i128)
914                }
915            }
916
917            impl<const BITS: usize, const LIMBS: usize> Sub<$ty> for Int<BITS, LIMBS> {
918                type Output = Self;
919                fn sub(self, rhs: $ty) -> Self::Output {
920                    self - Self::from_i128(rhs as i128)
921                }
922            }
923
924            impl<const BITS: usize, const LIMBS: usize> Mul<$ty> for Int<BITS, LIMBS> {
925                type Output = Self;
926                fn mul(self, rhs: $ty) -> Self::Output {
927                    let (word, negative) = i128_abs_to_word(rhs as i128);
928                    let (product, _) = self.abs().mul_word(word);
929                    let make_negative = self.is_negative() ^ negative;
930                    let bits = if make_negative {
931                        Uint::ZERO.sub_raw(&product).0
932                    } else {
933                        product
934                    };
935                    Self::from_uint_bits(bits)
936                }
937            }
938
939            impl<const BITS: usize, const LIMBS: usize> Div<$ty> for Int<BITS, LIMBS> {
940                type Output = Self;
941                fn div(self, rhs: $ty) -> Self::Output {
942                    let (word, negative) = i128_abs_to_word(rhs as i128);
943                    let (quotient, _) = self.abs().div_rem_word(word);
944                    let make_negative = self.is_negative() ^ negative;
945                    let bits = if make_negative {
946                        Uint::ZERO.sub_raw(&quotient).0
947                    } else {
948                        quotient
949                    };
950                    Self::from_uint_bits(bits)
951                }
952            }
953
954            impl<const BITS: usize, const LIMBS: usize> Rem<$ty> for Int<BITS, LIMBS> {
955                type Output = Self;
956                fn rem(self, rhs: $ty) -> Self::Output {
957                    let (word, _) = i128_abs_to_word(rhs as i128);
958                    let (_, remainder) = self.abs().div_rem_word(word);
959                    let bits = Uint::from_u64(remainder);
960                    let bits = if self.is_negative() {
961                        Uint::ZERO.sub_raw(&bits).0
962                    } else {
963                        bits
964                    };
965                    Self::from_uint_bits(bits)
966                }
967            }
968        )*
969    };
970}
971
972impl_uint_ops_unsigned!(u8, u16, u32, u64, u128);
973impl_uint_ops_signed!(i8, i16, i32, i64, i128);
974impl_int_ops_unsigned!(u8, u16, u32, u64, u128);
975impl_int_ops_signed!(i8, i16, i32, i64, i128);
976
977#[cfg(test)]
978mod tests {
979    use super::*;
980    type U256 = Uint<256, 4>;
981    type U128 = Uint<128, 2>;
982    type I128 = Int<128, 2>;
983
984    const P256_MODULUS: U256 = U256::from_limbs([
985        0xffff_ffff_ffff_ffff,
986        0x0000_0000_ffff_ffff,
987        0x0000_0000_0000_0000,
988        0xffff_ffff_0000_0001,
989    ]);
990    const P256_ORDER: U256 = U256::from_limbs([
991        0xf3b9_cac2_fc63_2551,
992        0xbce6_faad_a717_9e84,
993        0xffff_ffff_ffff_ffff,
994        0xffff_ffff_0000_0000,
995    ]);
996    const P256_P_MINUS_TWO: U256 = U256::from_limbs([
997        0xffff_ffff_ffff_fffd,
998        0x0000_0000_ffff_ffff,
999        0x0000_0000_0000_0000,
1000        0xffff_ffff_0000_0001,
1001    ]);
1002    const P256_P_PLUS_ONE_OVER_FOUR: U256 = U256::from_limbs([
1003        0x0000_0000_0000_0000,
1004        0x0000_0000_4000_0000,
1005        0x4000_0000_0000_0000,
1006        0x3fff_ffff_c000_0000,
1007    ]);
1008    const ED25519_P: U256 = U256::from_limbs([
1009        0xffff_ffff_ffff_ffed,
1010        0xffff_ffff_ffff_ffff,
1011        0xffff_ffff_ffff_ffff,
1012        0x7fff_ffff_ffff_ffff,
1013    ]);
1014
1015    fn decode_hex<const N: usize>(input: &str) -> [u8; N] {
1016        assert_eq!(input.len(), N * 2);
1017        let mut out = [0u8; N];
1018        let bytes = input.as_bytes();
1019        let mut i = 0;
1020        while i < N {
1021            let hi = char_to_digit(bytes[i * 2]).unwrap() as u8;
1022            let lo = char_to_digit(bytes[i * 2 + 1]).unwrap() as u8;
1023            out[i] = (hi << 4) | lo;
1024            i += 1;
1025        }
1026        out
1027    }
1028
1029    #[test]
1030    fn raw_arithmetic_reports_carry_and_borrow() {
1031        let (sum, carry) = U128::MAX.add_raw(&U128::ONE);
1032        assert_eq!(sum, U128::ZERO);
1033        assert_eq!(carry, 1);
1034
1035        let (diff, borrow) = U128::ZERO.sub_raw(&U128::ONE);
1036        assert_eq!(diff, U128::MAX);
1037        assert_eq!(borrow, 1);
1038
1039        let (low, high) = U128::MAX.mul_word(2);
1040        assert_eq!(low, U128::from_limbs([0xffff_ffff_ffff_fffe, 0xffff_ffff_ffff_ffff]));
1041        assert_eq!(high, 1);
1042    }
1043
1044    #[test]
1045    fn modular_arithmetic_matches_known_values() {
1046        assert_eq!(P256_P_MINUS_TWO.add_mod(&U256::from_u64(2), &P256_MODULUS), U256::ZERO);
1047        assert_eq!(
1048            P256_MODULUS.sub_mod(&U256::from_u64(1), &P256_MODULUS),
1049            P256_MODULUS - U256::ONE
1050        );
1051        assert_eq!(P256_P_MINUS_TWO.double_mod(&P256_MODULUS), P256_MODULUS - U256::from_u64(4));
1052        assert_eq!(P256_P_PLUS_ONE_OVER_FOUR.mul_mod(&U256::from_u64(4), &P256_MODULUS), U256::ONE);
1053        assert_eq!(P256_ORDER.add_mod(&U256::ONE, &P256_ORDER), U256::ONE);
1054    }
1055
1056    #[test]
1057    fn string_round_trips_for_common_radices() {
1058        let values = [
1059            U256::ZERO,
1060            U256::ONE,
1061            U256::MAX,
1062            U256::from_be_slice(&decode_hex::<32>(
1063                "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
1064            )),
1065        ];
1066
1067        for value in values {
1068            for radix in [2, 10, 16] {
1069                let encoded = value.to_string_radix(radix);
1070                let decoded = U256::from_str_radix(&encoded, radix).unwrap();
1071                assert_eq!(decoded, value);
1072            }
1073        }
1074    }
1075
1076    #[test]
1077    fn operator_overloads_work_with_primitives() {
1078        let value = U128::from_u64(10);
1079        assert_eq!(value + 5u64, U128::from_u64(15));
1080        assert_eq!(value - (-5i32), U128::from_u64(15));
1081        assert_eq!(value * -3i32, U128::from_u64(30));
1082        assert_eq!(value / -3i32, U128::from_u64(3));
1083        assert_eq!(value % -3i32, 1);
1084
1085        let signed = I128::from_i128(-10);
1086        assert_eq!(signed + 3u32, I128::from_i128(-7));
1087        assert_eq!(signed - (-5i32), I128::from_i128(-5));
1088        assert_eq!(signed * -2i32, I128::from_i128(20));
1089        assert_eq!(signed / -4i32, I128::from_i128(2));
1090        assert_eq!(signed % 4u32, I128::from_i128(-2));
1091    }
1092
1093    #[test]
1094    fn constant_time_helpers_select_and_compare() {
1095        let a = U256::from_u64(7);
1096        let b = U256::from_u64(11);
1097        assert_eq!(U256::ct_select(&a, &b, true), a);
1098        assert_eq!(U256::ct_select(&a, &b, false), b);
1099        assert!(a.ct_eq(&a));
1100        assert!(!a.ct_eq(&b));
1101        assert!(b.ct_ge(&a));
1102        assert!(!a.ct_ge(&b));
1103    }
1104
1105    #[test]
1106    fn from_str_radix_rejects_invalid_inputs() {
1107        assert_eq!(U128::from_str_radix("", 10), Err(Error::EmptyString));
1108        assert_eq!(U128::from_str_radix("10", 1), Err(Error::InvalidRadix));
1109        assert_eq!(U128::from_str_radix("2", 2), Err(Error::InvalidDigit));
1110        assert_eq!(U128::from_str_radix("zz", 10), Err(Error::InvalidDigit));
1111        assert_eq!(
1112            U128::from_str_radix("340282366920938463463374607431768211456", 10),
1113            Err(Error::Overflow)
1114        );
1115    }
1116
1117    #[test]
1118    fn byte_round_trips_match_p256_constants() {
1119        let modulus_hex = "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff";
1120        let order_hex = "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551";
1121
1122        let modulus_bytes = decode_hex::<32>(modulus_hex);
1123        let order_bytes = decode_hex::<32>(order_hex);
1124
1125        let modulus = U256::from_be_slice(&modulus_bytes);
1126        let order = U256::from_be_slice(&order_bytes);
1127
1128        assert_eq!(modulus, P256_MODULUS);
1129        assert_eq!(order, P256_ORDER);
1130        assert_eq!(modulus.to_be_bytes_fixed::<32>(), modulus_bytes);
1131        assert_eq!(order.to_be_bytes_fixed::<32>(), order_bytes);
1132        assert_eq!(format!("{modulus:x}"), modulus_hex);
1133        assert_eq!(format!("{order:X}"), order_hex.to_uppercase());
1134    }
1135
1136    #[test]
1137    fn little_endian_round_trip_works() {
1138        let value = U256::from_be_slice(&decode_hex::<32>(
1139            "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
1140        ));
1141        let le = value.to_le_bytes_fixed::<32>();
1142        assert_eq!(U256::from_le_slice(&le), value);
1143    }
1144
1145    #[test]
1146    fn modular_addition_vectors() {
1147        struct Test {
1148            a: U256,
1149            b: U256,
1150            m: U256,
1151            expected: U256,
1152        }
1153        let tests = [
1154            Test {
1155                a: U256::ZERO,
1156                b: U256::ZERO,
1157                m: P256_MODULUS,
1158                expected: U256::ZERO,
1159            },
1160            Test {
1161                a: U256::ZERO,
1162                b: U256::ONE,
1163                m: P256_MODULUS,
1164                expected: U256::ONE,
1165            },
1166            Test {
1167                a: U256::ONE,
1168                b: U256::ONE,
1169                m: P256_MODULUS,
1170                expected: U256::from_u64(2),
1171            },
1172            Test {
1173                a: P256_MODULUS - U256::ONE,
1174                b: U256::ONE,
1175                m: P256_MODULUS,
1176                expected: U256::ZERO,
1177            },
1178            Test {
1179                a: P256_MODULUS - U256::ONE,
1180                b: U256::from_u64(2),
1181                m: P256_MODULUS,
1182                expected: U256::ONE,
1183            },
1184            Test {
1185                a: U256::ZERO,
1186                b: U256::ZERO,
1187                m: P256_ORDER,
1188                expected: U256::ZERO,
1189            },
1190            Test {
1191                a: U256::ZERO,
1192                b: U256::ONE,
1193                m: P256_ORDER,
1194                expected: U256::ONE,
1195            },
1196            Test {
1197                a: U256::ONE,
1198                b: U256::ONE,
1199                m: P256_ORDER,
1200                expected: U256::from_u64(2),
1201            },
1202            Test {
1203                a: U256::MAX,
1204                b: U256::ONE,
1205                m: P256_ORDER,
1206                expected: U256::from_limbs([
1207                    0x0c46_353d_039c_daaf,
1208                    0x4319_0552_58e8_617b,
1209                    0x0000_0000_0000_0000,
1210                    0x0000_0000_ffff_ffff,
1211                ]),
1212            },
1213            Test {
1214                a: P256_ORDER - U256::ONE,
1215                b: U256::ONE,
1216                m: P256_ORDER,
1217                expected: U256::ZERO,
1218            },
1219            Test {
1220                a: P256_ORDER - U256::ONE,
1221                b: U256::from_u64(2),
1222                m: P256_ORDER,
1223                expected: U256::ONE,
1224            },
1225            Test {
1226                a: U256::ZERO,
1227                b: U256::ZERO,
1228                m: ED25519_P,
1229                expected: U256::ZERO,
1230            },
1231            Test {
1232                a: U256::ZERO,
1233                b: U256::ONE,
1234                m: ED25519_P,
1235                expected: U256::ONE,
1236            },
1237            Test {
1238                a: U256::ONE,
1239                b: U256::ONE,
1240                m: ED25519_P,
1241                expected: U256::from_u64(2),
1242            },
1243            Test {
1244                a: U256::from_limbs([
1245                    0xffff_ffff_ffff_ffff,
1246                    0x0000_0000_0000_0000,
1247                    0x0000_0000_0000_0000,
1248                    0x0000_0000_0000_0000,
1249                ]),
1250                b: U256::ONE,
1251                m: P256_MODULUS,
1252                expected: U256::from_limbs([
1253                    0x0000_0000_0000_0000,
1254                    0x0000_0000_0000_0001,
1255                    0x0000_0000_0000_0000,
1256                    0x0000_0000_0000_0000,
1257                ]),
1258            },
1259            Test {
1260                a: U256::from_limbs([
1261                    0xffff_ffff_ffff_ffff,
1262                    0x0000_0000_0000_0000,
1263                    0x0000_0000_0000_0000,
1264                    0x0000_0000_0000_0000,
1265                ]),
1266                b: U256::ONE,
1267                m: P256_ORDER,
1268                expected: U256::from_limbs([
1269                    0x0000_0000_0000_0000,
1270                    0x0000_0000_0000_0001,
1271                    0x0000_0000_0000_0000,
1272                    0x0000_0000_0000_0000,
1273                ]),
1274            },
1275            Test {
1276                a: U256::from_limbs([
1277                    0xffff_ffff_ffff_ffff,
1278                    0x0000_0000_0000_0000,
1279                    0x0000_0000_0000_0000,
1280                    0x0000_0000_0000_0000,
1281                ]),
1282                b: U256::ONE,
1283                m: ED25519_P,
1284                expected: U256::from_limbs([
1285                    0x0000_0000_0000_0000,
1286                    0x0000_0000_0000_0001,
1287                    0x0000_0000_0000_0000,
1288                    0x0000_0000_0000_0000,
1289                ]),
1290            },
1291            Test {
1292                a: ED25519_P - U256::ONE,
1293                b: ED25519_P - U256::ONE,
1294                m: ED25519_P,
1295                expected: (ED25519_P - U256::ONE).double_mod(&ED25519_P),
1296            },
1297        ];
1298        for t in &tests {
1299            assert_eq!(t.a.add_mod(&t.b, &t.m), t.expected, "add_mod({:x}, {:x}, {:x})", t.a, t.b, t.m);
1300        }
1301    }
1302
1303    #[test]
1304    fn modular_subtraction_vectors() {
1305        struct Test {
1306            a: U256,
1307            b: U256,
1308            m: U256,
1309            expected: U256,
1310        }
1311        let tests = [
1312            Test {
1313                a: U256::ZERO,
1314                b: U256::ZERO,
1315                m: P256_MODULUS,
1316                expected: U256::ZERO,
1317            },
1318            Test {
1319                a: U256::ONE,
1320                b: U256::ZERO,
1321                m: P256_MODULUS,
1322                expected: U256::ONE,
1323            },
1324            Test {
1325                a: U256::ZERO,
1326                b: U256::ONE,
1327                m: P256_MODULUS,
1328                expected: P256_MODULUS - U256::ONE,
1329            },
1330            Test {
1331                a: P256_MODULUS - U256::ONE,
1332                b: U256::ONE,
1333                m: P256_MODULUS,
1334                expected: P256_MODULUS - U256::from_u64(2),
1335            },
1336            Test {
1337                a: U256::ONE,
1338                b: P256_MODULUS - U256::ONE,
1339                m: P256_MODULUS,
1340                expected: U256::from_u64(2),
1341            },
1342            Test {
1343                a: U256::ZERO,
1344                b: U256::ZERO,
1345                m: P256_ORDER,
1346                expected: U256::ZERO,
1347            },
1348            Test {
1349                a: U256::ONE,
1350                b: U256::ZERO,
1351                m: P256_ORDER,
1352                expected: U256::ONE,
1353            },
1354            Test {
1355                a: U256::ZERO,
1356                b: U256::ONE,
1357                m: P256_ORDER,
1358                expected: P256_ORDER - U256::ONE,
1359            },
1360            Test {
1361                a: P256_ORDER - U256::ONE,
1362                b: U256::ONE,
1363                m: P256_ORDER,
1364                expected: P256_ORDER - U256::from_u64(2),
1365            },
1366            Test {
1367                a: U256::ONE,
1368                b: P256_ORDER - U256::ONE,
1369                m: P256_ORDER,
1370                expected: U256::from_u64(2),
1371            },
1372            Test {
1373                a: U256::ZERO,
1374                b: U256::ZERO,
1375                m: ED25519_P,
1376                expected: U256::ZERO,
1377            },
1378            Test {
1379                a: U256::ONE,
1380                b: U256::ZERO,
1381                m: ED25519_P,
1382                expected: U256::ONE,
1383            },
1384            Test {
1385                a: U256::ZERO,
1386                b: U256::ONE,
1387                m: ED25519_P,
1388                expected: ED25519_P - U256::ONE,
1389            },
1390            Test {
1391                a: ED25519_P - U256::ONE,
1392                b: U256::ONE,
1393                m: ED25519_P,
1394                expected: ED25519_P - U256::from_u64(2),
1395            },
1396            Test {
1397                a: U256::ONE,
1398                b: ED25519_P - U256::ONE,
1399                m: ED25519_P,
1400                expected: U256::from_u64(2),
1401            },
1402        ];
1403        for t in &tests {
1404            assert_eq!(t.a.sub_mod(&t.b, &t.m), t.expected, "sub_mod({:x}, {:x}, {:x})", t.a, t.b, t.m);
1405        }
1406    }
1407
1408    #[test]
1409    fn modular_multiplication_vectors() {
1410        struct Test {
1411            a: U256,
1412            b: U256,
1413            m: U256,
1414            expected: U256,
1415        }
1416        let tests = [
1417            Test {
1418                a: U256::ZERO,
1419                b: U256::ZERO,
1420                m: P256_MODULUS,
1421                expected: U256::ZERO,
1422            },
1423            Test {
1424                a: U256::ZERO,
1425                b: U256::ONE,
1426                m: P256_MODULUS,
1427                expected: U256::ZERO,
1428            },
1429            Test {
1430                a: U256::ONE,
1431                b: U256::ZERO,
1432                m: P256_MODULUS,
1433                expected: U256::ZERO,
1434            },
1435            Test {
1436                a: U256::ONE,
1437                b: U256::ONE,
1438                m: P256_MODULUS,
1439                expected: U256::ONE,
1440            },
1441            Test {
1442                a: U256::from_u64(2),
1443                b: U256::from_u64(3),
1444                m: P256_MODULUS,
1445                expected: U256::from_u64(6),
1446            },
1447            Test {
1448                a: U256::MAX,
1449                b: U256::ONE,
1450                m: P256_MODULUS,
1451                expected: U256::from_limbs([
1452                    0x0000_0000_0000_0000,
1453                    0xffff_ffff_0000_0000,
1454                    0xffff_ffff_ffff_ffff,
1455                    0x0000_0000_ffff_fffe,
1456                ]),
1457            },
1458            Test {
1459                a: P256_MODULUS - U256::ONE,
1460                b: U256::ONE,
1461                m: P256_MODULUS,
1462                expected: P256_MODULUS - U256::ONE,
1463            },
1464            Test {
1465                a: P256_MODULUS - U256::ONE,
1466                b: P256_MODULUS - U256::ONE,
1467                m: P256_MODULUS,
1468                expected: U256::ONE,
1469            },
1470            Test {
1471                a: P256_MODULUS + U256::ONE,
1472                b: P256_MODULUS + U256::ONE,
1473                m: P256_MODULUS,
1474                expected: U256::ONE,
1475            },
1476            Test {
1477                a: U256::ZERO,
1478                b: U256::ZERO,
1479                m: P256_ORDER,
1480                expected: U256::ZERO,
1481            },
1482            Test {
1483                a: U256::ZERO,
1484                b: U256::ONE,
1485                m: P256_ORDER,
1486                expected: U256::ZERO,
1487            },
1488            Test {
1489                a: U256::ONE,
1490                b: U256::ZERO,
1491                m: P256_ORDER,
1492                expected: U256::ZERO,
1493            },
1494            Test {
1495                a: U256::ONE,
1496                b: U256::ONE,
1497                m: P256_ORDER,
1498                expected: U256::ONE,
1499            },
1500            Test {
1501                a: U256::from_u64(2),
1502                b: U256::from_u64(3),
1503                m: P256_ORDER,
1504                expected: U256::from_u64(6),
1505            },
1506            Test {
1507                a: P256_ORDER - U256::ONE,
1508                b: U256::ONE,
1509                m: P256_ORDER,
1510                expected: P256_ORDER - U256::ONE,
1511            },
1512            Test {
1513                a: P256_ORDER - U256::ONE,
1514                b: P256_ORDER - U256::ONE,
1515                m: P256_ORDER,
1516                expected: U256::ONE,
1517            },
1518            Test {
1519                a: P256_ORDER + U256::ONE,
1520                b: P256_ORDER + U256::ONE,
1521                m: P256_ORDER,
1522                expected: U256::ONE,
1523            },
1524            Test {
1525                a: U256::ZERO,
1526                b: U256::ZERO,
1527                m: ED25519_P,
1528                expected: U256::ZERO,
1529            },
1530            Test {
1531                a: U256::ZERO,
1532                b: U256::ONE,
1533                m: ED25519_P,
1534                expected: U256::ZERO,
1535            },
1536            Test {
1537                a: U256::ONE,
1538                b: U256::ZERO,
1539                m: ED25519_P,
1540                expected: U256::ZERO,
1541            },
1542            Test {
1543                a: U256::ONE,
1544                b: U256::ONE,
1545                m: ED25519_P,
1546                expected: U256::ONE,
1547            },
1548            Test {
1549                a: U256::from_u64(2),
1550                b: U256::from_u64(3),
1551                m: ED25519_P,
1552                expected: U256::from_u64(6),
1553            },
1554            Test {
1555                a: ED25519_P - U256::ONE,
1556                b: U256::ONE,
1557                m: ED25519_P,
1558                expected: ED25519_P - U256::ONE,
1559            },
1560            Test {
1561                a: ED25519_P - U256::ONE,
1562                b: ED25519_P - U256::ONE,
1563                m: ED25519_P,
1564                expected: U256::ONE,
1565            },
1566            Test {
1567                a: ED25519_P + U256::ONE,
1568                b: ED25519_P + U256::ONE,
1569                m: ED25519_P,
1570                expected: U256::ONE,
1571            },
1572            Test {
1573                a: U256::from_limbs([
1574                    0xffff_ffff_ffff_ffff,
1575                    0x0000_0000_0000_0000,
1576                    0x0000_0000_0000_0000,
1577                    0x0000_0000_0000_0000,
1578                ]),
1579                b: U256::from_limbs([
1580                    0xffff_ffff_ffff_ffff,
1581                    0x0000_0000_0000_0000,
1582                    0x0000_0000_0000_0000,
1583                    0x0000_0000_0000_0000,
1584                ]),
1585                m: P256_MODULUS,
1586                expected: U256::from_limbs([
1587                    0x0000_0000_0000_0001,
1588                    0xffff_ffff_ffff_fffe,
1589                    0x0000_0000_0000_0000,
1590                    0x0000_0000_0000_0000,
1591                ]),
1592            },
1593        ];
1594        for t in &tests {
1595            assert_eq!(t.a.mul_mod(&t.b, &t.m), t.expected, "mul_mod({:x}, {:x}, {:x})", t.a, t.b, t.m);
1596        }
1597    }
1598
1599    #[test]
1600    fn raw_addition_vectors() {
1601        struct Test {
1602            a: U256,
1603            b: U256,
1604            expected_sum: U256,
1605            expected_carry: u64,
1606        }
1607        let tests = [
1608            Test {
1609                a: U256::ZERO,
1610                b: U256::ZERO,
1611                expected_sum: U256::ZERO,
1612                expected_carry: 0,
1613            },
1614            Test {
1615                a: U256::ZERO,
1616                b: U256::ONE,
1617                expected_sum: U256::ONE,
1618                expected_carry: 0,
1619            },
1620            Test {
1621                a: U256::ONE,
1622                b: U256::ONE,
1623                expected_sum: U256::from_u64(2),
1624                expected_carry: 0,
1625            },
1626            Test {
1627                a: U256::MAX,
1628                b: U256::ZERO,
1629                expected_sum: U256::MAX,
1630                expected_carry: 0,
1631            },
1632            Test {
1633                a: U256::MAX,
1634                b: U256::ONE,
1635                expected_sum: U256::ZERO,
1636                expected_carry: 1,
1637            },
1638            Test {
1639                a: U256::MAX,
1640                b: U256::MAX,
1641                expected_sum: U256::MAX - U256::ONE,
1642                expected_carry: 1,
1643            },
1644            Test {
1645                a: U256::MAX - U256::ONE,
1646                b: U256::ONE,
1647                expected_sum: U256::MAX,
1648                expected_carry: 0,
1649            },
1650            Test {
1651                a: U256::ONE,
1652                b: U256::MAX,
1653                expected_sum: U256::ZERO,
1654                expected_carry: 1,
1655            },
1656            Test {
1657                a: U256::from_limbs([
1658                    0xffff_ffff_ffff_ffff,
1659                    0x0000_0000_0000_0000,
1660                    0x0000_0000_0000_0000,
1661                    0x0000_0000_0000_0000,
1662                ]),
1663                b: U256::ONE,
1664                expected_sum: U256::from_limbs([
1665                    0x0000_0000_0000_0000,
1666                    0x0000_0000_0000_0001,
1667                    0x0000_0000_0000_0000,
1668                    0x0000_0000_0000_0000,
1669                ]),
1670                expected_carry: 0,
1671            },
1672            Test {
1673                a: U256::from_limbs([
1674                    0xffff_ffff_ffff_ffff,
1675                    0xffff_ffff_ffff_ffff,
1676                    0x0000_0000_0000_0000,
1677                    0x0000_0000_0000_0000,
1678                ]),
1679                b: U256::ONE,
1680                expected_sum: U256::from_limbs([
1681                    0x0000_0000_0000_0000,
1682                    0x0000_0000_0000_0000,
1683                    0x0000_0000_0000_0001,
1684                    0x0000_0000_0000_0000,
1685                ]),
1686                expected_carry: 0,
1687            },
1688        ];
1689        for t in &tests {
1690            let (sum, carry) = t.a.add_raw(&t.b);
1691            assert_eq!(sum, t.expected_sum, "add_raw({:x}, {:x}).sum", t.a, t.b);
1692            assert_eq!(carry, t.expected_carry, "add_raw({:x}, {:x}).carry", t.a, t.b);
1693        }
1694    }
1695
1696    #[test]
1697    fn raw_subtraction_vectors() {
1698        struct Test {
1699            a: U256,
1700            b: U256,
1701            expected_diff: U256,
1702            expected_borrow: u64,
1703        }
1704        let tests = [
1705            Test {
1706                a: U256::ZERO,
1707                b: U256::ZERO,
1708                expected_diff: U256::ZERO,
1709                expected_borrow: 0,
1710            },
1711            Test {
1712                a: U256::ONE,
1713                b: U256::ZERO,
1714                expected_diff: U256::ONE,
1715                expected_borrow: 0,
1716            },
1717            Test {
1718                a: U256::ONE,
1719                b: U256::ONE,
1720                expected_diff: U256::ZERO,
1721                expected_borrow: 0,
1722            },
1723            Test {
1724                a: U256::ZERO,
1725                b: U256::ONE,
1726                expected_diff: U256::MAX,
1727                expected_borrow: 1,
1728            },
1729            Test {
1730                a: U256::MAX,
1731                b: U256::MAX,
1732                expected_diff: U256::ZERO,
1733                expected_borrow: 0,
1734            },
1735            Test {
1736                a: U256::MAX,
1737                b: U256::ZERO,
1738                expected_diff: U256::MAX,
1739                expected_borrow: 0,
1740            },
1741            Test {
1742                a: U256::MAX,
1743                b: U256::MAX - U256::ONE,
1744                expected_diff: U256::ONE,
1745                expected_borrow: 0,
1746            },
1747            Test {
1748                a: U256::ONE,
1749                b: U256::MAX,
1750                expected_diff: U256::from_u64(2),
1751                expected_borrow: 1,
1752            },
1753        ];
1754        for t in &tests {
1755            let (diff, borrow) = t.a.sub_raw(&t.b);
1756            assert_eq!(diff, t.expected_diff, "sub_raw({:x}, {:x}).diff", t.a, t.b);
1757            assert_eq!(borrow, t.expected_borrow, "sub_raw({:x}, {:x}).borrow", t.a, t.b);
1758        }
1759    }
1760
1761    #[test]
1762    fn string_roundtrip_vectors() {
1763        struct Test {
1764            value: U256,
1765            radix: u32,
1766            expected: &'static str,
1767        }
1768        let tests = [
1769            Test {
1770                value: U256::ZERO,
1771                radix: 2,
1772                expected: "0",
1773            },
1774            Test {
1775                value: U256::ZERO,
1776                radix: 10,
1777                expected: "0",
1778            },
1779            Test {
1780                value: U256::ZERO,
1781                radix: 16,
1782                expected: "0",
1783            },
1784            Test {
1785                value: U256::ONE,
1786                radix: 2,
1787                expected: "1",
1788            },
1789            Test {
1790                value: U256::ONE,
1791                radix: 10,
1792                expected: "1",
1793            },
1794            Test {
1795                value: U256::ONE,
1796                radix: 16,
1797                expected: "1",
1798            },
1799            Test {
1800                value: U256::MAX,
1801                radix: 10,
1802                expected: "115792089237316195423570985008687907853269984665640564039457584007913129639935",
1803            },
1804            Test {
1805                value: U256::MAX,
1806                radix: 16,
1807                expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
1808            },
1809            Test {
1810                value: P256_MODULUS,
1811                radix: 10,
1812                expected: "115792089210356248762697446949407573530086143415290314195533631308867097853951",
1813            },
1814            Test {
1815                value: P256_MODULUS,
1816                radix: 16,
1817                expected: "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
1818            },
1819            Test {
1820                value: P256_ORDER,
1821                radix: 10,
1822                expected: "115792089210356248762697446949407573529996955224135760342422259061068512044369",
1823            },
1824            Test {
1825                value: P256_ORDER,
1826                radix: 16,
1827                expected: "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
1828            },
1829            Test {
1830                value: ED25519_P,
1831                radix: 10,
1832                expected: "57896044618658097711785492504343953926634992332820282019728792003956564819949",
1833            },
1834            Test {
1835                value: ED25519_P,
1836                radix: 16,
1837                expected: "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
1838            },
1839        ];
1840        for t in &tests {
1841            let encoded = t.value.to_string_radix(t.radix);
1842            assert_eq!(encoded, t.expected, "to_string_radix({:x}, {})", t.value, t.radix);
1843            let decoded = U256::from_str_radix(t.expected, t.radix).unwrap();
1844            assert_eq!(decoded, t.value, "from_str_radix round-trip");
1845        }
1846    }
1847
1848    #[test]
1849    fn mul_mod_edge_cases() {
1850        assert_eq!(P256_P_PLUS_ONE_OVER_FOUR.mul_mod(&U256::from_u64(4), &P256_MODULUS), U256::ONE);
1851
1852        let (a, _) = U256::MAX.mul_word(2);
1853        assert_eq!(a.add_mod(&U256::ZERO, &P256_MODULUS), U256::MAX.double_mod(&P256_MODULUS));
1854    }
1855
1856    // P-256 generator point coordinates (NIST SP 800-186 / RFC 6979).
1857    // Test vectors generated with Python: `hex((Gx * Gy) % p256_p)` etc.
1858    const P256_GX: U256 = U256::from_be_slice_const(
1859        0x6b17d1f2, 0xe12c4247, 0xf8bce6e5, 0x63a440f2, 0x77037d81, 0x2deb33a0, 0xf4a13945, 0xd898c296,
1860    );
1861    const P256_GY: U256 = U256::from_be_slice_const(
1862        0x4fe342e2, 0xfe1a7f9b, 0x8ee7eb4a, 0x7c0f9e16, 0x2bce3357, 0x6b315ece, 0xcbb64068, 0x37bf51f5,
1863    );
1864
1865    impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
1866        // Helper to build a 256-bit constant from eight 32-bit big-endian words.
1867        // Only valid for BITS=256, LIMBS=4; used only in test helpers.
1868        const fn from_be_slice_const(w7: u32, w6: u32, w5: u32, w4: u32, w3: u32, w2: u32, w1: u32, w0: u32) -> Self {
1869            let limb3 = ((w7 as u64) << 32) | (w6 as u64);
1870            let limb2 = ((w5 as u64) << 32) | (w4 as u64);
1871            let limb1 = ((w3 as u64) << 32) | (w2 as u64);
1872            let limb0 = ((w1 as u64) << 32) | (w0 as u64);
1873            let limbs = [0u64; LIMBS];
1874            if LIMBS > 0 {
1875                let mut l = [0u64; LIMBS];
1876                l[0] = limb0;
1877                l[1] = limb1;
1878                l[2] = limb2;
1879                l[3] = limb3;
1880                return Self {
1881                    limbs: l,
1882                };
1883            }
1884            Self {
1885                limbs,
1886            }
1887        }
1888    }
1889
1890    #[test]
1891    fn p256_mul_mod_with_generator_coordinates() {
1892        // Vectors verified with Python's arbitrary-precision arithmetic.
1893        let gx_gy_mod_p = U256::from_be_slice(&decode_hex::<32>(
1894            "823cd15f6dd3c71933565064513a6b2bd183e554c6a08622f713ebbbface98be",
1895        ));
1896        let gx_sq_mod_p = U256::from_be_slice(&decode_hex::<32>(
1897            "98f6b84d29bef2b281819a5e0e3690d833b699495d694dd1002ae56c426b3f8c",
1898        ));
1899        let gy_sq_mod_p = U256::from_be_slice(&decode_hex::<32>(
1900            "55df5d5850f47bad82149139979369fe498a9022a412b5e0bedd2cfc21c3ed91",
1901        ));
1902
1903        assert_eq!(P256_GX.mul_mod(&P256_GY, &P256_MODULUS), gx_gy_mod_p, "Gx*Gy mod p");
1904        // Commutativity
1905        assert_eq!(
1906            P256_GY.mul_mod(&P256_GX, &P256_MODULUS),
1907            gx_gy_mod_p,
1908            "Gy*Gx mod p (commutativity)"
1909        );
1910        assert_eq!(P256_GX.mul_mod(&P256_GX, &P256_MODULUS), gx_sq_mod_p, "Gx^2 mod p");
1911        assert_eq!(P256_GY.mul_mod(&P256_GY, &P256_MODULUS), gy_sq_mod_p, "Gy^2 mod p");
1912    }
1913
1914    #[test]
1915    fn p256_add_sub_mod_with_generator_coordinates() {
1916        // Gx + Gy mod p256_p  (Python: hex((Gx + Gy) % p))
1917        let gx_plus_gy = U256::from_be_slice(&decode_hex::<32>(
1918            "bafb14d5df46c1e387a4d22fdfb3df08a2d1b0d8991c926fc05779ae1058148b",
1919        ));
1920        // Gx - Gy mod p256_p  (Python: hex((Gx - Gy) % p))
1921        let gx_minus_gy = U256::from_be_slice(&decode_hex::<32>(
1922            "1b348f0fe311c2ac69d4fb9ae794a2dc4b354a29c2b9d4d228eaf8dda0d970a1",
1923        ));
1924        // Gy - Gx mod p256_p
1925        let gy_minus_gx = U256::from_be_slice(&decode_hex::<32>(
1926            "e4cb70ef1cee3d54962b0465186b5d23b4cab5d73d462b2dd71507225f268f5e",
1927        ));
1928
1929        assert_eq!(P256_GX.add_mod(&P256_GY, &P256_MODULUS), gx_plus_gy);
1930        assert_eq!(P256_GX.sub_mod(&P256_GY, &P256_MODULUS), gx_minus_gy);
1931        assert_eq!(P256_GY.sub_mod(&P256_GX, &P256_MODULUS), gy_minus_gx);
1932        // (a-b) + (b-a) = 0 mod p
1933        assert_eq!(gx_minus_gy.add_mod(&gy_minus_gx, &P256_MODULUS), U256::ZERO);
1934    }
1935
1936    #[test]
1937    fn bit_access() {
1938        // Gx = 0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
1939        // Bit 0: the LSB of limb[0] = 0x...96 → bit 0 = 0
1940        assert!(!P256_GX.bit(0), "bit 0 of Gx");
1941        assert!(P256_GX.bit(1), "bit 1 of Gx");
1942        assert!(P256_GX.bit(2), "bit 2 of Gx");
1943        assert!(P256_GX.bit(63), "bit 63 of Gx");
1944        assert!(!P256_GX.bit(64), "bit 64 of Gx");
1945        assert!(!P256_GX.bit(65), "bit 65 of Gx");
1946        assert!(!P256_GX.bit(127), "bit 127 of Gx");
1947        assert!(!P256_GX.bit(128), "bit 128 of Gx");
1948        assert!(P256_GX.bit(192), "bit 192 of Gx");
1949        assert!(!P256_GX.bit(255), "bit 255 of Gx");
1950        // Out-of-range bit is false
1951        assert!(!P256_GX.bit(256), "bit 256 (out of range) of Gx");
1952
1953        // p256_p: all-ones in low 64 bits → bit 0 is 1
1954        assert!(P256_MODULUS.bit(0), "bit 0 of p256_p");
1955        assert!(P256_MODULUS.bit(63), "bit 63 of p256_p");
1956        assert!(P256_MODULUS.bit(64), "bit 64 of p256_p");
1957        assert!(!P256_MODULUS.bit(96), "bit 96 of p256_p");
1958        assert!(P256_MODULUS.bit(255), "bit 255 of p256_p");
1959
1960        assert!(!U256::ZERO.bit(0));
1961        assert!(!U256::ZERO.bit(255));
1962        assert!(U256::ONE.bit(0));
1963        assert!(!U256::ONE.bit(1));
1964        assert!(U256::MAX.bit(0));
1965        assert!(U256::MAX.bit(255));
1966    }
1967
1968    #[test]
1969    fn is_odd_flag() {
1970        assert!(!U256::ZERO.is_odd(), "0 is even");
1971        assert!(U256::ONE.is_odd(), "1 is odd");
1972        assert!(!U256::from_u64(2).is_odd(), "2 is even");
1973        assert!(U256::from_u64(3).is_odd(), "3 is odd");
1974        assert!(P256_MODULUS.is_odd(), "p256_p is odd");
1975        assert!(P256_ORDER.is_odd(), "p256_n is odd");
1976        assert!(!P256_GX.is_odd(), "Gx is even");
1977        assert!(P256_GY.is_odd(), "Gy is odd");
1978        assert!(U256::MAX.is_odd(), "MAX is odd");
1979    }
1980
1981    #[test]
1982    fn ct_ge_comprehensive() {
1983        let zero = U256::ZERO;
1984        let one = U256::ONE;
1985        let max = U256::MAX;
1986
1987        // Equal values
1988        assert!(zero.ct_ge(&zero), "0 >= 0");
1989        assert!(one.ct_ge(&one), "1 >= 1");
1990        assert!(max.ct_ge(&max), "MAX >= MAX");
1991        assert!(P256_MODULUS.ct_ge(&P256_MODULUS), "p >= p");
1992
1993        // Strict greater
1994        assert!(one.ct_ge(&zero), "1 >= 0");
1995        assert!(max.ct_ge(&zero), "MAX >= 0");
1996        assert!(max.ct_ge(&one), "MAX >= 1");
1997        assert!(P256_GX.ct_ge(&zero), "Gx >= 0");
1998
1999        // Strict less
2000        assert!(!zero.ct_ge(&one), "NOT 0 >= 1");
2001        assert!(!zero.ct_ge(&max), "NOT 0 >= MAX");
2002        assert!(!one.ct_ge(&max), "NOT 1 >= MAX");
2003        assert!(!P256_GX.ct_ge(&max), "NOT Gx >= MAX");
2004
2005        // Adjacent values
2006        assert!((P256_MODULUS - U256::ONE).ct_ge(&(P256_MODULUS - U256::from_u64(2))));
2007        assert!(!P256_MODULUS.sub_mod(&U256::ONE, &P256_MODULUS).ct_ge(&P256_MODULUS));
2008    }
2009
2010    #[test]
2011    fn div_rem_word_vectors() {
2012        // Vectors generated with Python: p256_p / divisor
2013        // p256_p = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff
2014        struct Test {
2015            dividend: U256,
2016            divisor: u64,
2017            expected_quotient: U256,
2018            expected_rem: u64,
2019        }
2020        let tests = [
2021            Test {
2022                dividend: P256_MODULUS,
2023                divisor: 1,
2024                expected_quotient: P256_MODULUS,
2025                expected_rem: 0,
2026            },
2027            Test {
2028                dividend: P256_MODULUS,
2029                divisor: 2,
2030                expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2031                    "7fffffff800000008000000000000000000000007fffffffffffffffffffffff",
2032                )),
2033                expected_rem: 1,
2034            },
2035            Test {
2036                dividend: P256_MODULUS,
2037                divisor: 10,
2038                expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2039                    "1999999980000000199999999999999999999999b33333333333333333333333",
2040                )),
2041                expected_rem: 1,
2042            },
2043            Test {
2044                dividend: P256_MODULUS,
2045                divisor: 16,
2046                expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2047                    "0ffffffff00000001000000000000000000000000fffffffffffffffffffffff",
2048                )),
2049                expected_rem: 0xf,
2050            },
2051            Test {
2052                dividend: P256_MODULUS,
2053                divisor: 0xffff_ffff,
2054                expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2055                    "0000000100000000000000010000000100000001000000020000000200000002",
2056                )),
2057                expected_rem: 1,
2058            },
2059            Test {
2060                dividend: P256_MODULUS,
2061                divisor: 0x1_0000_0000,
2062                expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2063                    "00000000ffffffff00000001000000000000000000000000ffffffffffffffff",
2064                )),
2065                expected_rem: 0xffff_ffff,
2066            },
2067            Test {
2068                dividend: U256::ZERO,
2069                divisor: 7,
2070                expected_quotient: U256::ZERO,
2071                expected_rem: 0,
2072            },
2073            Test {
2074                dividend: U256::ONE,
2075                divisor: 7,
2076                expected_quotient: U256::ZERO,
2077                expected_rem: 1,
2078            },
2079            Test {
2080                dividend: U256::from_u64(100),
2081                divisor: 7,
2082                expected_quotient: U256::from_u64(14),
2083                expected_rem: 2,
2084            },
2085        ];
2086        for t in &tests {
2087            let (q, r) = t.dividend.div_rem_word(t.divisor);
2088            assert_eq!(q, t.expected_quotient, "div_rem_word({:x}, {}).quotient", t.dividend, t.divisor);
2089            assert_eq!(r, t.expected_rem, "div_rem_word({:x}, {}).rem", t.dividend, t.divisor);
2090        }
2091    }
2092
2093    #[test]
2094    fn add_word_vectors() {
2095        // Vectors: Python hex(Gx + k) for small k
2096        let gx = P256_GX;
2097        let gx_plus_1 = U256::from_be_slice(&decode_hex::<32>(
2098            "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c297",
2099        ));
2100        let gx_minus_1 = U256::from_be_slice(&decode_hex::<32>(
2101            "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c295",
2102        ));
2103
2104        let (sum, carry) = gx.add_word(1);
2105        assert_eq!(sum, gx_plus_1, "Gx + 1");
2106        assert_eq!(carry, 0);
2107
2108        let (diff, borrow) = gx.sub_word(1);
2109        assert_eq!(diff, gx_minus_1, "Gx - 1");
2110        assert_eq!(borrow, 0);
2111
2112        // Adding to MAX wraps
2113        let (sum_max, carry_max) = U256::MAX.add_word(1);
2114        assert_eq!(sum_max, U256::ZERO);
2115        assert_eq!(carry_max, 1);
2116
2117        // Subtracting from ZERO borrows
2118        let (diff_zero, borrow_zero) = U256::ZERO.sub_word(1);
2119        assert_eq!(diff_zero, U256::MAX);
2120        assert_eq!(borrow_zero, 1);
2121
2122        // Word that carries across limb boundary: 2^64 - 1 + 1
2123        let val = U256::from_u64(u64::MAX);
2124        let (sum2, carry2) = val.add_word(1);
2125        assert_eq!(sum2, U256::from_limbs([0, 1, 0, 0]));
2126        assert_eq!(carry2, 0);
2127    }
2128
2129    #[test]
2130    fn mul_word_vectors() {
2131        // Gx * 2 = 2*Gx (no overflow since Gx < 2^255)
2132        // Python: hex(Gx * 2)
2133        let gx_times_2 = U256::from_be_slice(&decode_hex::<32>(
2134            "d62fa3e5c258848ff179cdcac74881e4ee06fb025bd66741e942728bb131852c",
2135        ));
2136        let (prod, carry) = P256_GX.mul_word(2);
2137        assert_eq!(prod, gx_times_2, "Gx * 2");
2138        assert_eq!(carry, 0, "Gx * 2 carry");
2139
2140        // MAX * 2 = 2^256 - 2: low 256 bits = all-ones XOR 1, overflow carry = 1
2141        let (prod_max, carry_max) = U256::MAX.mul_word(2);
2142        assert_eq!(prod_max, U256::from_limbs([u64::MAX - 1, u64::MAX, u64::MAX, u64::MAX]));
2143        assert_eq!(carry_max, 1);
2144
2145        // ONE * 0 = 0
2146        let (zero_prod, zero_carry) = U256::ONE.mul_word(0);
2147        assert_eq!(zero_prod, U256::ZERO);
2148        assert_eq!(zero_carry, 0);
2149
2150        // from_u64(10) * from_u64(10) (single-word)
2151        let (p, c) = U128::from_u64(u64::MAX).mul_word(u64::MAX);
2152        // u64::MAX * u64::MAX = 2^128 - 2^65 + 1 = (2^64-1)^2
2153        // low 64 bits = 1, high 64 bits = u64::MAX - 1
2154        assert_eq!(p, U128::from_limbs([1, u64::MAX - 1]));
2155        assert_eq!(c, 0);
2156    }
2157
2158    #[test]
2159    fn fibonacci_number_round_trip() {
2160        // Fib(100) = 354224848179261915075
2161        // hex: 0x1333db76a7c594bfc3
2162        // Verified with Python: `a, b = 0, 1; [a, b = b, a+b for _ in range(100)]; print(a)`
2163        let fib100_dec = "354224848179261915075";
2164        let fib100_hex = "1333db76a7c594bfc3";
2165
2166        let from_dec = U128::from_str_radix(fib100_dec, 10).unwrap();
2167        let from_hex = U128::from_str_radix(fib100_hex, 16).unwrap();
2168
2169        assert_eq!(from_dec, from_hex, "Fib(100) from decimal == from hex");
2170        assert_eq!(from_dec.to_string_radix(10), fib100_dec);
2171        assert_eq!(from_dec.to_string_radix(16), fib100_hex);
2172
2173        // Fib(100) in binary
2174        let fib100_bin = from_dec.to_string_radix(2);
2175        let from_bin = U128::from_str_radix(&fib100_bin, 2).unwrap();
2176        assert_eq!(from_bin, from_dec);
2177
2178        // Octal round-trip
2179        let fib100_oct = from_dec.to_string_radix(8);
2180        let from_oct = U128::from_str_radix(&fib100_oct, 8).unwrap();
2181        assert_eq!(from_oct, from_dec);
2182    }
2183
2184    #[test]
2185    fn display_and_debug_formatting() {
2186        // Display uses decimal
2187        assert_eq!(format!("{}", U256::ZERO), "0");
2188        assert_eq!(format!("{}", U256::ONE), "1");
2189        assert_eq!(
2190            format!("{}", U256::MAX),
2191            "115792089237316195423570985008687907853269984665640564039457584007913129639935"
2192        );
2193        assert_eq!(
2194            format!("{}", P256_MODULUS),
2195            "115792089210356248762697446949407573530086143415290314195533631308867097853951"
2196        );
2197
2198        // LowerHex
2199        assert_eq!(format!("{:x}", U256::ZERO), "0");
2200        assert_eq!(format!("{:x}", U256::ONE), "1");
2201        assert_eq!(
2202            format!("{:x}", U256::MAX),
2203            "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
2204        );
2205        assert_eq!(format!("{:#x}", U256::from_u64(255)), "0xff");
2206
2207        // UpperHex
2208        assert_eq!(format!("{:X}", U256::ZERO), "0");
2209        assert_eq!(
2210            format!("{:X}", P256_MODULUS),
2211            "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"
2212        );
2213        assert_eq!(format!("{:#X}", U256::from_u64(255)), "0xFF");
2214
2215        // Debug
2216        assert_eq!(format!("{:?}", U256::ZERO), "Uint(0x0)");
2217        assert_eq!(format!("{:?}", U256::ONE), "Uint(0x1)");
2218        assert_eq!(
2219            format!("{:?}", P256_MODULUS),
2220            "Uint(0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff)"
2221        );
2222    }
2223
2224    #[test]
2225    fn to_be_le_bytes_vec() {
2226        // Verify Vec<u8> output matches fixed-size output
2227        let values = [U256::ZERO, U256::ONE, U256::MAX, P256_MODULUS, P256_GX, P256_GY];
2228        for v in &values {
2229            let be_vec = v.to_be_bytes();
2230            let be_fixed = v.to_be_bytes_fixed::<32>();
2231            assert_eq!(be_vec.as_slice(), be_fixed.as_slice(), "BE bytes of {:x}", v);
2232
2233            let le_vec = v.to_le_bytes();
2234            let le_fixed = v.to_le_bytes_fixed::<32>();
2235            assert_eq!(le_vec.as_slice(), le_fixed.as_slice(), "LE bytes of {:x}", v);
2236
2237            // Round-trip through be
2238            let rt_be = U256::from_be_slice(&be_vec);
2239            assert_eq!(rt_be, *v, "BE round-trip of {:x}", v);
2240
2241            // Round-trip through le
2242            let rt_le = U256::from_le_slice(&le_vec);
2243            assert_eq!(rt_le, *v, "LE round-trip of {:x}", v);
2244        }
2245    }
2246
2247    #[test]
2248    fn max_for_non_64_multiple_bits() {
2249        // Uint<130, 3>: LIMBS=3, top limb should have only bits 0-1 set.
2250        // MAX = 2^130 - 1:
2251        //   limb[0] = 2^64 - 1
2252        //   limb[1] = 2^64 - 1
2253        //   limb[2] = 0b11 = 3  (only 2 bits, since 130 % 64 = 2)
2254        type U130 = Uint<130, 3>;
2255        let max = U130::MAX;
2256        assert_eq!(max.limbs[0], u64::MAX, "U130::MAX limb[0]");
2257        assert_eq!(max.limbs[1], u64::MAX, "U130::MAX limb[1]");
2258        assert_eq!(max.limbs[2], 0b11, "U130::MAX limb[2] should have only 2 bits set");
2259
2260        // Uint<192, 3>: 192 = 3*64, all limbs should be u64::MAX
2261        type U192 = Uint<192, 3>;
2262        let max192 = U192::MAX;
2263        assert_eq!(max192.limbs[0], u64::MAX, "U192::MAX limb[0]");
2264        assert_eq!(max192.limbs[1], u64::MAX, "U192::MAX limb[1]");
2265        assert_eq!(max192.limbs[2], u64::MAX, "U192::MAX limb[2]");
2266
2267        // Uint<65, 2>: top limb should have only 1 bit set
2268        type U65 = Uint<65, 2>;
2269        let max65 = U65::MAX;
2270        assert_eq!(max65.limbs[0], u64::MAX, "U65::MAX limb[0]");
2271        assert_eq!(max65.limbs[1], 1, "U65::MAX limb[1] should be 1 (bit 64 only)");
2272    }
2273
2274    #[test]
2275    fn mul_mod_associativity_and_identity() {
2276        // (a * b) * c == a * (b * c) mod p
2277        let a = P256_GX;
2278        let b = P256_GY;
2279        let c = P256_MODULUS - U256::ONE;
2280        let m = P256_MODULUS;
2281
2282        let ab = a.mul_mod(&b, &m);
2283        let bc = b.mul_mod(&c, &m);
2284
2285        assert_eq!(ab.mul_mod(&c, &m), a.mul_mod(&bc, &m), "associativity");
2286
2287        // Identity: a * 1 = a
2288        assert_eq!(a.mul_mod(&U256::ONE, &m), a, "a * 1 = a");
2289        assert_eq!(U256::ONE.mul_mod(&a, &m), a, "1 * a = a");
2290
2291        // Zero: a * 0 = 0
2292        assert_eq!(a.mul_mod(&U256::ZERO, &m), U256::ZERO, "a * 0 = 0");
2293        assert_eq!(U256::ZERO.mul_mod(&a, &m), U256::ZERO, "0 * a = 0");
2294
2295        // Distributivity: (a + b) * c == a*c + b*c mod p
2296        let ab_sum = a.add_mod(&b, &m);
2297        let lhs = ab_sum.mul_mod(&c, &m);
2298        let rhs = a.mul_mod(&c, &m).add_mod(&b.mul_mod(&c, &m), &m);
2299        assert_eq!(lhs, rhs, "distributivity");
2300    }
2301}