1#![cfg_attr(not(feature = "std"), no_std)]
39
40#[cfg(feature = "alloc")]
41extern crate alloc;
42
43#[cfg(feature = "alloc")]
44use alloc::{string::String, vec::Vec};
45use core::{
46 fmt,
47 ops::{Add, Div, Mul, Neg, Rem, Sub},
48};
49
50pub const MAX_LIMBS: usize = 260;
56
57pub const MAX_BARRETT_LIMBS: usize = MAX_LIMBS / 2 - 1;
60
61const fn max_limbs<const BITS: usize, const LIMBS: usize>() -> [u64; LIMBS] {
62 let mut limbs = [u64::MAX; LIMBS];
63 let rem = BITS % 64;
64 if rem != 0 {
65 limbs[LIMBS - 1] = (1u64 << rem) - 1;
66 }
67 limbs
68}
69
70#[derive(Clone, Copy, PartialEq, Eq)]
77#[cfg_attr(feature = "zeroize", derive(zeroize::Zeroize))]
78pub struct Uint<const BITS: usize, const LIMBS: usize> {
79 pub limbs: [u64; LIMBS],
80}
81
82#[derive(Clone, Copy, Debug, PartialEq, Eq)]
89pub struct Int<const BITS: usize, const LIMBS: usize>(Uint<BITS, LIMBS>);
90
91#[derive(Clone, Copy, Debug, PartialEq, Eq)]
93pub enum Error {
94 InvalidRadix,
96 InvalidDigit,
98 EmptyString,
100 Overflow,
102}
103
104#[inline]
105pub const fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) {
106 let sum = (a as u128) + (b as u128) + (carry as u128);
107 (sum as u64, (sum >> 64) as u64)
108}
109
110#[inline]
111pub const fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) {
112 let diff = (1u128 << 64) + (a as u128) - (b as u128) - (borrow as u128);
113 (diff as u64, 1u64.wrapping_sub((diff >> 64) as u64))
114}
115
116#[inline]
117pub const fn mac(acc: u64, a: u64, b: u64, carry: u64) -> (u64, u64) {
118 let value = (acc as u128) + (a as u128) * (b as u128) + (carry as u128);
119 (value as u64, (value >> 64) as u64)
120}
121
122fn mul_limbs(out: &mut [u64], a: &[u64], a_len: usize, b: &[u64], b_len: usize) {
129 for i in 0..a_len {
130 let mut carry = 0u64;
131 for j in 0..b_len {
132 let (word, next_carry) = mac(out[i + j], a[i], b[j], carry);
133 out[i + j] = word;
134 carry = next_carry;
135 }
136 let mut k = i + b_len;
137 while carry != 0 && k < out.len() {
138 let (word, next_carry) = adc(out[k], 0, carry);
139 out[k] = word;
140 carry = next_carry;
141 k += 1;
142 }
143 }
144}
145
146#[inline]
147const fn ct_select_u64(a: u64, b: u64, choice: bool) -> u64 {
148 let mask = 0u64.wrapping_sub(choice as u64);
149 b ^ ((a ^ b) & mask)
150}
151
152#[cfg(feature = "alloc")]
153#[inline]
154const fn digit_to_char(digit: u64, upper: bool) -> char {
155 match digit {
156 0..=9 => (b'0' + digit as u8) as char,
157 _ if upper => (b'A' + (digit as u8 - 10)) as char,
158 _ => (b'a' + (digit as u8 - 10)) as char,
159 }
160}
161
162#[inline]
163fn char_to_digit(byte: u8) -> Option<u32> {
164 match byte {
165 b'0'..=b'9' => Some((byte - b'0') as u32),
166 b'a'..=b'z' => Some((byte - b'a' + 10) as u32),
167 b'A'..=b'Z' => Some((byte - b'A' + 10) as u32),
168 _ => None,
169 }
170}
171
172const fn uint_from_u128<const BITS: usize, const LIMBS: usize>(value: u128) -> Uint<BITS, LIMBS> {
173 let mut limbs = [0u64; LIMBS];
174 if LIMBS > 0 {
175 limbs[0] = value as u64;
176 }
177 if LIMBS > 1 {
178 limbs[1] = (value >> 64) as u64;
179 }
180 Uint {
181 limbs,
182 }
183}
184
185fn u128_to_word(value: u128) -> u64 {
186 u64::try_from(value).expect("primitive operand exceeds u64")
187}
188
189fn i128_abs_to_word(value: i128) -> (u64, bool) {
190 (u128_to_word(value.unsigned_abs()), value.is_negative())
191}
192
193#[inline]
196fn zeroize_limbs(limbs: &mut [u64]) {
197 #[cfg(feature = "zeroize")]
198 zeroize::Zeroize::zeroize(limbs);
199 #[cfg(not(feature = "zeroize"))]
200 let _ = limbs;
201}
202
203impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
204 const _LIMBS_CHECK: () = assert!(LIMBS == BITS.div_ceil(64), "LIMBS must equal ceil(BITS/64)");
205
206 pub const ZERO: Self = Self {
207 limbs: [0u64; LIMBS],
208 };
209 pub const ONE: Self = Self::from_u64(1);
210 pub const MAX: Self = Self {
211 limbs: max_limbs::<BITS, LIMBS>(),
212 };
213
214 #[inline]
221 pub const fn from_limbs(limbs: [u64; LIMBS]) -> Self {
222 Self {
223 limbs,
224 }
225 }
226
227 #[inline]
229 pub const fn from_u64(v: u64) -> Self {
230 let mut limbs = [0u64; LIMBS];
231 if LIMBS > 0 {
232 limbs[0] = v;
233 }
234 Self {
235 limbs,
236 }
237 }
238
239 #[inline]
241 const fn truncate_to_bits(mut self) -> Self {
242 let rem = BITS % 64;
243 if rem != 0 {
244 self.limbs[LIMBS - 1] &= (1u64 << rem) - 1;
245 }
246 self
247 }
248
249 #[inline]
259 pub fn from_be_slice(bytes: &[u8]) -> Self {
260 assert_eq!(bytes.len(), LIMBS * 8, "expected LIMBS * 8 big-endian bytes");
261 let mut limbs = [0u64; LIMBS];
262 let mut i = 0;
263 while i < LIMBS {
264 let start = (LIMBS - 1 - i) * 8;
265 let mut limb = [0u8; 8];
266 limb.copy_from_slice(&bytes[start..start + 8]);
267 limbs[i] = u64::from_be_bytes(limb);
268 i += 1;
269 }
270 Self {
271 limbs,
272 }
273 .truncate_to_bits()
274 }
275
276 #[inline]
286 pub fn from_le_slice(bytes: &[u8]) -> Self {
287 assert_eq!(bytes.len(), LIMBS * 8, "expected LIMBS * 8 little-endian bytes");
288 let mut limbs = [0u64; LIMBS];
289 let mut i = 0;
290 while i < LIMBS {
291 let start = i * 8;
292 let mut limb = [0u8; 8];
293 limb.copy_from_slice(&bytes[start..start + 8]);
294 limbs[i] = u64::from_le_bytes(limb);
295 i += 1;
296 }
297 Self {
298 limbs,
299 }
300 .truncate_to_bits()
301 }
302
303 #[cfg(feature = "alloc")]
308 #[inline]
309 pub fn to_be_bytes(&self) -> Vec<u8> {
310 let mut out = Vec::with_capacity(LIMBS * 8);
311 let mut i = LIMBS;
312 while i > 0 {
313 i -= 1;
314 out.extend_from_slice(&self.limbs[i].to_be_bytes());
315 }
316 out
317 }
318
319 #[cfg(feature = "alloc")]
324 #[inline]
325 pub fn to_le_bytes(&self) -> Vec<u8> {
326 let mut out = Vec::with_capacity(LIMBS * 8);
327 let mut i = 0;
328 while i < LIMBS {
329 out.extend_from_slice(&self.limbs[i].to_le_bytes());
330 i += 1;
331 }
332 out
333 }
334
335 #[inline]
341 pub fn to_be_bytes_fixed<const N: usize>(&self) -> [u8; N] {
342 assert_eq!(N, LIMBS * 8, "expected an array of LIMBS * 8 big-endian bytes");
343 let mut out = [0u8; N];
344 let mut i = 0;
345 while i < LIMBS {
346 let start = N - ((i + 1) * 8);
347 out[start..start + 8].copy_from_slice(&self.limbs[i].to_be_bytes());
348 i += 1;
349 }
350 out
351 }
352
353 #[inline]
359 pub fn to_le_bytes_fixed<const N: usize>(&self) -> [u8; N] {
360 assert_eq!(N, LIMBS * 8, "expected an array of LIMBS * 8 little-endian bytes");
361 let mut out = [0u8; N];
362 let mut i = 0;
363 while i < LIMBS {
364 let start = i * 8;
365 out[start..start + 8].copy_from_slice(&self.limbs[i].to_le_bytes());
366 i += 1;
367 }
368 out
369 }
370
371 #[inline]
375 pub fn bit(&self, index: usize) -> bool {
376 if index >= BITS {
377 return false;
378 }
379 ((self.limbs[index / 64] >> (index % 64)) & 1) == 1
380 }
381
382 #[inline]
384 pub fn is_zero(&self) -> bool {
385 let mut acc = 0u64;
386 let mut i = 0;
387 while i < LIMBS {
388 acc |= self.limbs[i];
389 i += 1;
390 }
391 acc == 0
392 }
393
394 pub fn bit_len(&self) -> usize {
396 let mut i = LIMBS;
397 while i > 0 {
398 i -= 1;
399 if self.limbs[i] != 0 {
400 return i * 64 + 64 - self.limbs[i].leading_zeros() as usize;
401 }
402 }
403 0
404 }
405
406 #[inline]
408 pub fn is_odd(&self) -> bool {
409 (self.limbs[0] & 1) == 1
410 }
411
412 #[inline]
416 pub fn ct_ge(&self, rhs: &Self) -> bool {
417 let (_, borrow) = self.sub_raw(rhs);
418 borrow == 0
419 }
420
421 #[inline]
423 pub fn ct_eq(&self, rhs: &Self) -> bool {
424 let mut diff = 0u64;
425 let mut i = 0;
426 while i < LIMBS {
427 diff |= self.limbs[i] ^ rhs.limbs[i];
428 i += 1;
429 }
430 diff == 0
431 }
432
433 #[inline]
435 pub fn ct_select(a: &Self, b: &Self, choice: bool) -> Self {
436 let mut limbs = [0u64; LIMBS];
437 let mut i = 0;
438 while i < LIMBS {
439 limbs[i] = ct_select_u64(a.limbs[i], b.limbs[i], choice);
440 i += 1;
441 }
442 Self {
443 limbs,
444 }
445 }
446
447 #[inline]
449 pub fn add_raw(&self, rhs: &Self) -> (Self, u64) {
450 let mut out = [0u64; LIMBS];
451 let mut carry = 0u64;
452 let mut i = 0;
453 while i < LIMBS {
454 let (word, next_carry) = adc(self.limbs[i], rhs.limbs[i], carry);
455 out[i] = word;
456 carry = next_carry;
457 i += 1;
458 }
459 (
460 Self {
461 limbs: out,
462 },
463 carry,
464 )
465 }
466
467 #[inline]
470 pub fn sub_raw(&self, rhs: &Self) -> (Self, u64) {
471 let mut out = [0u64; LIMBS];
472 let mut borrow = 0u64;
473 let mut i = 0;
474 while i < LIMBS {
475 let (word, next_borrow) = sbb(self.limbs[i], rhs.limbs[i], borrow);
476 out[i] = word;
477 borrow = next_borrow;
478 i += 1;
479 }
480 (
481 Self {
482 limbs: out,
483 },
484 borrow,
485 )
486 }
487
488 #[inline]
492 pub fn add_mod(&self, rhs: &Self, modulus: &Self) -> Self {
493 let (sum, carry) = self.add_raw(rhs);
494 let (reduced, borrow) = sum.sub_raw(modulus);
495 Self::ct_select(&reduced, &sum, (carry | (borrow ^ 1)) != 0)
498 }
499
500 #[inline]
505 pub fn sub_mod(&self, rhs: &Self, modulus: &Self) -> Self {
506 let (diff, borrow) = self.sub_raw(rhs);
507 let (corrected, _) = diff.add_raw(modulus);
508 Self::ct_select(&corrected, &diff, borrow == 1)
509 }
510
511 #[inline]
515 pub fn double_mod(&self, modulus: &Self) -> Self {
516 self.add_mod(self, modulus)
517 }
518
519 fn mul_wide_internal(&self, rhs: &Self) -> [u64; MAX_LIMBS] {
520 assert!(LIMBS * 2 <= MAX_LIMBS);
521 let mut out = [0u64; MAX_LIMBS];
522 let mut i = 0;
523 while i < LIMBS {
524 let mut carry = 0u64;
525 let mut j = 0;
526 while j < LIMBS {
527 let (word, next_carry) = mac(out[i + j], self.limbs[i], rhs.limbs[j], carry);
528 out[i + j] = word;
529 carry = next_carry;
530 j += 1;
531 }
532 let mut k = i + LIMBS;
533 while carry != 0 && k < MAX_LIMBS {
534 let (word, next_carry) = adc(out[k], 0, carry);
535 out[k] = word;
536 carry = next_carry;
537 k += 1;
538 }
539 i += 1;
540 }
541 out
542 }
543
544 fn reduce_wide_internal(product: &[u64; MAX_LIMBS], modulus: &Self) -> Self {
545 let total_bits = LIMBS * 128;
546 let mut rem = Self::ZERO;
547 let mut bit_index = total_bits;
548 while bit_index > 0 {
549 bit_index -= 1;
550 let limb_idx = bit_index / 64;
551 let bit_pos = bit_index % 64;
552 let bit = ((product[limb_idx] >> bit_pos) & 1) as u64;
553
554 let mut shifted = [0u64; LIMBS];
555 let mut carry = bit;
556 let mut i = 0;
557 while i < LIMBS {
558 let next = rem.limbs[i] >> 63;
559 shifted[i] = (rem.limbs[i] << 1) | carry;
560 carry = next;
561 i += 1;
562 }
563 let shifted_rem = Self {
564 limbs: shifted,
565 };
566 let (reduced, borrow) = shifted_rem.sub_raw(modulus);
567 rem = Self::ct_select(&reduced, &shifted_rem, (carry | (borrow ^ 1)) != 0);
569 }
570 rem
571 }
572
573 #[inline]
580 pub fn mul_mod(&self, rhs: &Self, modulus: &Self) -> Self {
581 let mut product = self.mul_wide_internal(rhs);
582 let result = Self::reduce_wide_internal(&product, modulus);
583 zeroize_limbs(&mut product[..]);
584 result
585 }
586
587 fn mul_wide_eff<const W: usize>(&self, rhs: &Self, eff_limbs: usize) -> [u64; W] {
595 assert!(2 * eff_limbs <= W, "working width W is too small");
596 let mut out = [0u64; W];
597 mul_limbs(&mut out, &self.limbs, eff_limbs, &rhs.limbs, eff_limbs);
598 out
599 }
600
601 pub fn compute_mu_for_barrett(&self) -> [u64; MAX_LIMBS] {
612 let eff_limbs = self.bit_len().div_ceil(64);
613 self.compute_mu_for_barrett_eff(eff_limbs)
614 }
615
616 fn compute_mu_for_barrett_eff(&self, eff_limbs: usize) -> [u64; MAX_LIMBS] {
617 const {
618 assert!(LIMBS + 1 <= MAX_LIMBS);
619 }
620 assert!(eff_limbs >= 1 && eff_limbs <= LIMBS, "modulus must be nonzero");
621
622 let total_bits = eff_limbs * 128;
623 let mut mu = [0u64; MAX_LIMBS];
624 let mut rem = Self::ZERO;
625
626 for bit_pos in (0..=total_bits).rev() {
627 let mut shifted_limbs = [0u64; LIMBS];
628 let mut carry = 0u64;
629 for i in 0..LIMBS {
630 let next = rem.limbs[i] >> 63;
631 shifted_limbs[i] = (rem.limbs[i] << 1) | carry;
632 carry = next;
633 }
634
635 let bit = if bit_pos == total_bits { 1u64 } else { 0u64 };
636 let mut with = shifted_limbs;
637 with[0] |= bit;
638
639 let shifted = Self {
640 limbs: with,
641 };
642 let (reduced, borrow) = shifted.sub_raw(self);
643 rem = Self::ct_select(&reduced, &shifted, (carry | (borrow ^ 1)) != 0);
646 if carry | (borrow ^ 1) != 0 {
648 let qi = bit_pos / 64;
649 let qbit = bit_pos % 64;
650 if qi < eff_limbs + 1 {
651 mu[qi] |= 1 << qbit;
652 }
653 }
654 }
655
656 mu
657 }
658
659 pub fn modpow_barrett(&self, exp: &Self, modulus: &Self, mu: &[u64]) -> Self {
673 self.modpow_barrett_w::<MAX_LIMBS>(exp, modulus, mu)
674 }
675
676 pub fn modpow_barrett_eff(&self, exp: &Self, modulus: &Self, mu: &[u64], eff_limbs: usize) -> Self {
682 self.modpow_barrett_impl::<MAX_LIMBS>(exp, modulus, mu, eff_limbs)
683 }
684
685 pub fn modpow_barrett_w<const W: usize>(&self, exp: &Self, modulus: &Self, mu: &[u64]) -> Self {
693 let eff_limbs = modulus.bit_len().div_ceil(64);
694 self.modpow_barrett_impl::<W>(exp, modulus, mu, eff_limbs)
695 }
696
697 fn modpow_barrett_impl<const W: usize>(&self, exp: &Self, modulus: &Self, mu: &[u64], eff_limbs: usize) -> Self {
698 assert!(eff_limbs >= 1 && eff_limbs <= MAX_BARRETT_LIMBS, "eff_limbs out of range");
699 assert!(2 * (eff_limbs + 1) <= W, "working width W is too small for the modulus");
700 let mut base = self.mul_mod_barrett_impl::<W>(&Self::ONE, modulus, mu, eff_limbs);
701 let mut result = Self::ONE;
702 let bits = exp.bit_len();
703 let mut i = 0;
704 while i < bits {
705 if exp.bit(i) {
706 result = result.mul_mod_barrett_impl::<W>(&base, modulus, mu, eff_limbs);
707 }
708 i += 1;
709 if i < bits {
711 base = base.mul_mod_barrett_impl::<W>(&base, modulus, mu, eff_limbs);
712 }
713 }
714 zeroize_limbs(&mut base.limbs);
715 result
716 }
717
718 pub fn mul_mod_barrett(&self, rhs: &Self, modulus: &Self, mu: &[u64]) -> Self {
729 self.mul_mod_barrett_w::<MAX_LIMBS>(rhs, modulus, mu)
730 }
731
732 pub fn mul_mod_barrett_eff(&self, rhs: &Self, modulus: &Self, mu: &[u64], eff_limbs: usize) -> Self {
737 self.mul_mod_barrett_impl::<MAX_LIMBS>(rhs, modulus, mu, eff_limbs)
738 }
739
740 pub fn mul_mod_barrett_w<const W: usize>(&self, rhs: &Self, modulus: &Self, mu: &[u64]) -> Self {
749 let eff_limbs = modulus.bit_len().div_ceil(64);
750 self.mul_mod_barrett_impl::<W>(rhs, modulus, mu, eff_limbs)
751 }
752
753 fn mul_mod_barrett_impl<const W: usize>(&self, rhs: &Self, modulus: &Self, mu: &[u64], eff_limbs: usize) -> Self {
754 assert!(eff_limbs >= 1 && eff_limbs <= MAX_BARRETT_LIMBS, "eff_limbs out of range");
755 assert!(2 * (eff_limbs + 1) <= W, "working width W is too small for the modulus");
756 debug_assert!(
757 self.bit_len() <= eff_limbs * 64 && rhs.bit_len() <= eff_limbs * 64,
758 "Barrett operands must be reduced below 2^(eff_limbs * 64)"
759 );
760 let mut product = self.mul_wide_eff::<W>(rhs, eff_limbs);
761 let result = Self::reduce_wide_barrett_eff_impl::<W>(&product, modulus, mu, eff_limbs);
762 zeroize_limbs(&mut product[..]);
763 result
764 }
765
766 pub fn reduce_wide_barrett_eff(product: &[u64; MAX_LIMBS], modulus: &Self, mu: &[u64], eff_limbs: usize) -> Self {
780 Self::reduce_wide_barrett_eff_impl::<MAX_LIMBS>(&product[..], modulus, mu, eff_limbs)
781 }
782
783 fn reduce_wide_barrett_eff_impl<const W: usize>(
784 product: &[u64],
785 modulus: &Self,
786 mu: &[u64],
787 eff_limbs: usize,
788 ) -> Self {
789 assert!(eff_limbs >= 1 && eff_limbs <= LIMBS, "eff_limbs out of range");
790 assert!(
791 eff_limbs <= MAX_BARRETT_LIMBS,
792 "Barrett reduction supports at most MAX_BARRETT_LIMBS effective limbs"
793 );
794 assert!(2 * (eff_limbs + 1) <= W, "working width W is too small for the modulus");
795 assert!(product.len() >= 2 * eff_limbs, "product slice is too short");
796 assert!(mu.len() >= eff_limbs + 1, "mu is too short for the effective limb count");
797
798 let k = eff_limbs;
799 let k1 = k + 1;
800 let k_minus_1 = k.saturating_sub(1);
801
802 let mut q1 = [0u64; W];
803 q1[..k1].copy_from_slice(&product[k_minus_1..k_minus_1 + k1]);
804
805 let mut q2 = [0u64; W];
806 mul_limbs(&mut q2, &q1, k1, mu, k1);
807
808 let mut q3 = [0u64; W];
809 q3[..k1].copy_from_slice(&q2[k1..k1 + k1]);
810
811 let mut r1 = [0u64; W];
812 r1[..k1].copy_from_slice(&product[..k1]);
813
814 let mut q3m = [0u64; W];
815 mul_limbs(&mut q3m, &q3[..k1], k1, &modulus.limbs, k);
816 let mut r2 = [0u64; W];
817 r2[..k1].copy_from_slice(&q3m[..k1]);
818
819 let mut r = [0u64; W];
820 let mut borrow = 0u64;
821 let mut i = 0;
822 while i < k1 {
823 let (word, next_borrow) = sbb(r1[i], r2[i], borrow);
824 r[i] = word;
825 borrow = next_borrow;
826 i += 1;
827 }
828
829 for _ in 0..2 {
834 let mut r_try = r;
835 let mut borrow = 0u64;
836 let mut j = 0;
837 while j < k1 {
838 let mod_limb = if j < LIMBS { modulus.limbs[j] } else { 0u64 };
839 let (word, next_borrow) = sbb(r_try[j], mod_limb, borrow);
840 r_try[j] = word;
841 borrow = next_borrow;
842 j += 1;
843 }
844 let choose = borrow == 0;
845 let mut j = 0;
846 while j < k1 {
847 r[j] = ct_select_u64(r_try[j], r[j], choose);
848 j += 1;
849 }
850 }
851
852 let mut limbs = [0u64; LIMBS];
853 limbs[..k].copy_from_slice(&r[..k]);
854 let result = Self {
855 limbs,
856 };
857 zeroize_limbs(&mut q1);
858 zeroize_limbs(&mut q2);
859 zeroize_limbs(&mut q3);
860 zeroize_limbs(&mut r1);
861 zeroize_limbs(&mut q3m);
862 zeroize_limbs(&mut r2);
863 zeroize_limbs(&mut r);
864 result
865 }
866
867 pub fn modpow(&self, exp: &Self, modulus: &Self) -> Self {
881 let mut base = self.mul_mod(&Self::ONE, modulus);
882 let mut result = Self::ONE;
883 let bits = exp.bit_len();
884 let mut i = 0;
885 while i < bits {
886 if exp.bit(i) {
887 result = result.mul_mod(&base, modulus);
888 }
889 i += 1;
890 if i < bits {
892 base = base.mul_mod(&base, modulus);
893 }
894 }
895 zeroize_limbs(&mut base.limbs);
896 result
897 }
898
899 pub fn reduce_wide_barrett(product: &[u64; MAX_LIMBS], modulus: &Self, mu: &[u64]) -> Self {
911 let eff_limbs = modulus.bit_len().div_ceil(64);
912 Self::reduce_wide_barrett_eff(product, modulus, mu, eff_limbs)
913 }
914
915 #[inline]
917 pub fn add_word(&self, word: u64) -> (Self, u64) {
918 let mut out = self.limbs;
919 let (first, mut carry) = adc(out[0], word, 0);
920 out[0] = first;
921 let mut i = 1;
922 while i < LIMBS {
923 let (next, next_carry) = adc(out[i], 0, carry);
924 out[i] = next;
925 carry = next_carry;
926 i += 1;
927 }
928 (
929 Self {
930 limbs: out,
931 },
932 carry,
933 )
934 }
935
936 #[inline]
938 pub fn sub_word(&self, word: u64) -> (Self, u64) {
939 let mut out = self.limbs;
940 let (first, mut borrow) = sbb(out[0], word, 0);
941 out[0] = first;
942 let mut i = 1;
943 while i < LIMBS {
944 let (next, next_borrow) = sbb(out[i], 0, borrow);
945 out[i] = next;
946 borrow = next_borrow;
947 i += 1;
948 }
949 (
950 Self {
951 limbs: out,
952 },
953 borrow,
954 )
955 }
956
957 #[inline]
960 pub fn mul_word(&self, word: u64) -> (Self, u64) {
961 let mut out = [0u64; LIMBS];
962 let mut carry = 0u64;
963 let mut i = 0;
964 while i < LIMBS {
965 let (next, next_carry) = mac(0, self.limbs[i], word, carry);
966 out[i] = next;
967 carry = next_carry;
968 i += 1;
969 }
970 (
971 Self {
972 limbs: out,
973 },
974 carry,
975 )
976 }
977
978 #[inline]
984 pub fn div_rem_word(&self, word: u64) -> (Self, u64) {
985 assert!(word != 0, "division by zero");
986 let mut out = [0u64; LIMBS];
987 let mut rem = 0u64;
988 let mut i = LIMBS;
989 while i > 0 {
990 i -= 1;
991 let dividend = ((rem as u128) << 64) | self.limbs[i] as u128;
992 out[i] = (dividend / word as u128) as u64;
993 rem = (dividend % word as u128) as u64;
994 }
995 (
996 Self {
997 limbs: out,
998 },
999 rem,
1000 )
1001 }
1002
1003 #[inline]
1008 fn add_word_at(&self, index: usize, word: u64) -> (Self, u64) {
1009 let mut out = self.limbs;
1010 let mut carry = word;
1011 let mut i = index;
1012 while i < LIMBS && carry != 0 {
1013 let (next, next_carry) = adc(out[i], carry, 0);
1014 out[i] = next;
1015 carry = next_carry;
1016 i += 1;
1017 }
1018 (
1019 Self {
1020 limbs: out,
1021 },
1022 carry,
1023 )
1024 }
1025
1026 #[inline]
1029 fn sub_word_at(&self, index: usize, word: u64) -> (Self, u64) {
1030 let mut out = self.limbs;
1031 let mut borrow = word;
1032 let mut i = index;
1033 while i < LIMBS && borrow != 0 {
1034 let (next, next_borrow) = sbb(out[i], borrow, 0);
1035 out[i] = next;
1036 borrow = next_borrow;
1037 i += 1;
1038 }
1039 (
1040 Self {
1041 limbs: out,
1042 },
1043 borrow,
1044 )
1045 }
1046
1047 #[inline]
1049 pub fn add_u128(&self, value: u128) -> Self {
1050 let (lo, hi) = (value as u64, (value >> 64) as u64);
1051 self.add_word(lo).0.add_word_at(1, hi).0
1052 }
1053
1054 #[inline]
1056 pub fn sub_u128(&self, value: u128) -> Self {
1057 let (lo, hi) = (value as u64, (value >> 64) as u64);
1058 self.sub_word(lo).0.sub_word_at(1, hi).0
1059 }
1060
1061 #[inline]
1063 pub fn mul_u128(&self, value: u128) -> Self {
1064 let (lo, hi) = (value as u64, (value >> 64) as u64);
1065 if hi == 0 {
1066 return self.mul_word(lo).0;
1067 }
1068 let (low, _) = self.mul_word(lo);
1069 let (high, _) = self.mul_word(hi);
1070 let mut out = low.limbs;
1072 let mut carry = 0u64;
1073 let mut j = 1;
1074 while j < LIMBS {
1075 let (sum, next_carry) = adc(out[j], high.limbs[j - 1], carry);
1076 out[j] = sum;
1077 carry = next_carry;
1078 j += 1;
1079 }
1080 Self {
1081 limbs: out,
1082 }
1083 }
1084
1085 pub fn div_rem_u128(&self, divisor: u128) -> (Self, u128) {
1091 assert!(divisor != 0, "division by zero");
1092 if divisor <= u64::MAX as u128 {
1093 let (q, r) = self.div_rem_word(divisor as u64);
1094 return (q, r as u128);
1095 }
1096 if LIMBS < 2 {
1099 return (Self::ZERO, self.limbs[0] as u128);
1100 }
1101 let d = {
1102 let mut limbs = [0u64; LIMBS];
1103 limbs[0] = divisor as u64;
1104 limbs[1] = (divisor >> 64) as u64;
1105 Self {
1106 limbs,
1107 }
1108 };
1109
1110 let mut quotient = Self::ZERO;
1111 let mut rem = Self::ZERO;
1112 let mut i = self.bit_len();
1113 while i > 0 {
1114 i -= 1;
1115 let mut carry = self.bit(i) as u64;
1117 let mut j = 0;
1118 while j < LIMBS {
1119 let next = rem.limbs[j] >> 63;
1120 rem.limbs[j] = (rem.limbs[j] << 1) | carry;
1121 carry = next;
1122 j += 1;
1123 }
1124 let (sub, borrow) = rem.sub_raw(&d);
1127 if carry != 0 || borrow == 0 {
1128 rem = sub;
1129 quotient.limbs[i / 64] |= 1u64 << (i % 64);
1130 }
1131 }
1132 let remainder = rem.limbs[0] as u128 | ((rem.limbs[1] as u128) << 64);
1133 (quotient, remainder)
1134 }
1135
1136 pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, Error> {
1161 if !(2..=36).contains(&radix) {
1162 return Err(Error::InvalidRadix);
1163 }
1164 if src.is_empty() {
1165 return Err(Error::EmptyString);
1166 }
1167
1168 let bytes = src.as_bytes();
1172 let start = bytes.iter().position(|&b| b != b'0').unwrap_or(bytes.len());
1173 if start == bytes.len() {
1174 return Ok(Self::ZERO);
1175 }
1176 let significant = &bytes[start..];
1177
1178 let bits_per_digit = (63 - (radix as u64).leading_zeros()) as usize;
1182 if significant.len() > BITS / bits_per_digit + 1 {
1183 return Err(Error::Overflow);
1184 }
1185
1186 let mut out = Self::ZERO;
1187 for &byte in significant {
1188 let digit = char_to_digit(byte).ok_or(Error::InvalidDigit)?;
1189 if digit >= radix {
1190 return Err(Error::InvalidDigit);
1191 }
1192 let (mul, high) = out.mul_word(radix as u64);
1193 if high != 0 {
1194 return Err(Error::Overflow);
1195 }
1196 let (next, carry) = mul.add_word(digit as u64);
1197 if carry != 0 {
1198 return Err(Error::Overflow);
1199 }
1200 out = next;
1201 }
1202 if out.bit_len() > BITS {
1205 return Err(Error::Overflow);
1206 }
1207 Ok(out)
1208 }
1209
1210 #[cfg(feature = "alloc")]
1218 pub fn to_string_radix(&self, radix: u32) -> String {
1219 assert!((2..=36).contains(&radix), "invalid radix");
1220 if self.is_zero() {
1221 return String::from("0");
1222 }
1223
1224 let bits_per_digit = (63 - (radix as u64).leading_zeros()) as usize;
1226 let capacity = self.bit_len() / bits_per_digit + 1;
1227 let mut digits: Vec<u8> = Vec::with_capacity(capacity);
1228 let mut value = *self;
1229 while !value.is_zero() {
1230 let (quotient, remainder) = value.div_rem_word(radix as u64);
1231 digits.push(digit_to_char(remainder, false) as u8);
1232 value = quotient;
1233 }
1234 digits.reverse();
1235 String::from_utf8(digits).expect("digits are ASCII")
1237 }
1238}
1239
1240#[cfg(feature = "alloc")]
1241impl<const BITS: usize, const LIMBS: usize> fmt::Display for Uint<BITS, LIMBS> {
1242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1243 f.write_str(&self.to_string_radix(10))
1244 }
1245}
1246
1247impl<const BITS: usize, const LIMBS: usize> fmt::LowerHex for Uint<BITS, LIMBS> {
1248 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1249 if f.alternate() {
1250 f.write_str("0x")?;
1251 }
1252 let mut started = false;
1253 let mut i = LIMBS;
1254 while i > 0 {
1255 i -= 1;
1256 let limb = self.limbs[i];
1257 if started {
1258 write!(f, "{limb:016x}")?;
1259 } else if limb != 0 {
1260 write!(f, "{limb:x}")?;
1261 started = true;
1262 }
1263 }
1264 if !started {
1265 f.write_str("0")?;
1266 }
1267 Ok(())
1268 }
1269}
1270
1271impl<const BITS: usize, const LIMBS: usize> fmt::UpperHex for Uint<BITS, LIMBS> {
1272 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1273 if f.alternate() {
1274 f.write_str("0x")?;
1275 }
1276 let mut started = false;
1277 let mut i = LIMBS;
1278 while i > 0 {
1279 i -= 1;
1280 let limb = self.limbs[i];
1281 if started {
1282 write!(f, "{limb:016X}")?;
1283 } else if limb != 0 {
1284 write!(f, "{limb:X}")?;
1285 started = true;
1286 }
1287 }
1288 if !started {
1289 f.write_str("0")?;
1290 }
1291 Ok(())
1292 }
1293}
1294
1295impl<const BITS: usize, const LIMBS: usize> fmt::Debug for Uint<BITS, LIMBS> {
1296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1297 write!(f, "Uint(0x{self:x})")
1298 }
1299}
1300
1301impl<const BITS: usize, const LIMBS: usize> Int<BITS, LIMBS> {
1302 const _LIMBS_CHECK: () = assert!(LIMBS == BITS.div_ceil(64), "LIMBS must equal ceil(BITS/64)");
1303
1304 pub const ZERO: Self = Self(Uint::ZERO);
1305 pub const ONE: Self = Self(Uint::ONE);
1306 pub const MINUS_ONE: Self = Self(Uint::MAX);
1307
1308 #[inline]
1309 const fn from_uint_bits(bits: Uint<BITS, LIMBS>) -> Self {
1310 Self(bits)
1311 }
1312
1313 #[inline]
1314 fn from_u128(value: u128) -> Self {
1315 Self(uint_from_u128(value))
1316 }
1317
1318 #[inline]
1319 fn from_i128(value: i128) -> Self {
1320 if value.is_negative() {
1321 let magnitude = uint_from_u128::<BITS, LIMBS>(value.unsigned_abs());
1322 Self(Self::ZERO.0.sub_raw(&magnitude).0)
1323 } else {
1324 Self(uint_from_u128(value as u128))
1325 }
1326 }
1327
1328 #[inline]
1330 pub fn is_negative(&self) -> bool {
1331 self.0.bit(BITS - 1)
1332 }
1333
1334 #[inline]
1336 pub fn abs(&self) -> Uint<BITS, LIMBS> {
1337 if self.is_negative() {
1338 Self::ZERO.0.sub_raw(&self.0).0
1339 } else {
1340 self.0
1341 }
1342 }
1343}
1344
1345impl<const BITS: usize, const LIMBS: usize> Add for Uint<BITS, LIMBS> {
1346 type Output = Self;
1347
1348 fn add(self, rhs: Self) -> Self::Output {
1349 self.add_raw(&rhs).0
1350 }
1351}
1352
1353impl<const BITS: usize, const LIMBS: usize> Sub for Uint<BITS, LIMBS> {
1354 type Output = Self;
1355
1356 fn sub(self, rhs: Self) -> Self::Output {
1357 self.sub_raw(&rhs).0
1358 }
1359}
1360
1361impl<const BITS: usize, const LIMBS: usize> Mul for Uint<BITS, LIMBS> {
1362 type Output = Self;
1363
1364 fn mul(self, rhs: Self) -> Self::Output {
1365 let mut product = self.mul_wide_internal(&rhs);
1366 let mut limbs = [0u64; LIMBS];
1367 let mut i = 0;
1368 while i < LIMBS {
1369 limbs[i] = product[i];
1370 i += 1;
1371 }
1372 zeroize_limbs(&mut product[..]);
1373 Self {
1374 limbs,
1375 }
1376 }
1377}
1378
1379impl<const BITS: usize, const LIMBS: usize> Add for Int<BITS, LIMBS> {
1380 type Output = Self;
1381
1382 fn add(self, rhs: Self) -> Self::Output {
1383 Self::from_uint_bits(self.0.add_raw(&rhs.0).0)
1384 }
1385}
1386
1387impl<const BITS: usize, const LIMBS: usize> Sub for Int<BITS, LIMBS> {
1388 type Output = Self;
1389
1390 fn sub(self, rhs: Self) -> Self::Output {
1391 Self::from_uint_bits(self.0.sub_raw(&rhs.0).0)
1392 }
1393}
1394
1395impl<const BITS: usize, const LIMBS: usize> Neg for Int<BITS, LIMBS> {
1396 type Output = Self;
1397
1398 fn neg(self) -> Self::Output {
1399 Self::from_uint_bits(Int::ZERO.0.sub_raw(&self.0).0)
1400 }
1401}
1402
1403macro_rules! impl_uint_ops_unsigned {
1404 ($($ty:ty),* $(,)?) => {
1405 $(
1406 impl<const BITS: usize, const LIMBS: usize> Add<$ty> for Uint<BITS, LIMBS> {
1407 type Output = Self;
1408 fn add(self, rhs: $ty) -> Self::Output {
1409 self.add_word(u128_to_word(rhs as u128)).0
1410 }
1411 }
1412
1413 impl<const BITS: usize, const LIMBS: usize> Sub<$ty> for Uint<BITS, LIMBS> {
1414 type Output = Self;
1415 fn sub(self, rhs: $ty) -> Self::Output {
1416 self.sub_word(u128_to_word(rhs as u128)).0
1417 }
1418 }
1419
1420 impl<const BITS: usize, const LIMBS: usize> Mul<$ty> for Uint<BITS, LIMBS> {
1421 type Output = Self;
1422 fn mul(self, rhs: $ty) -> Self::Output {
1423 self.mul_word(u128_to_word(rhs as u128)).0
1424 }
1425 }
1426
1427 impl<const BITS: usize, const LIMBS: usize> Div<$ty> for Uint<BITS, LIMBS> {
1428 type Output = Self;
1429 fn div(self, rhs: $ty) -> Self::Output {
1430 self.div_rem_word(u128_to_word(rhs as u128)).0
1431 }
1432 }
1433
1434 impl<const BITS: usize, const LIMBS: usize> Rem<$ty> for Uint<BITS, LIMBS> {
1435 type Output = u64;
1436 fn rem(self, rhs: $ty) -> Self::Output {
1437 self.div_rem_word(u128_to_word(rhs as u128)).1
1438 }
1439 }
1440 )*
1441 };
1442}
1443
1444macro_rules! impl_uint_ops_signed {
1445 ($($ty:ty),* $(,)?) => {
1446 $(
1447 impl<const BITS: usize, const LIMBS: usize> Add<$ty> for Uint<BITS, LIMBS> {
1448 type Output = Self;
1449 fn add(self, rhs: $ty) -> Self::Output {
1450 let (word, negative) = i128_abs_to_word(rhs as i128);
1451 if negative {
1452 self.sub_word(word).0
1453 } else {
1454 self.add_word(word).0
1455 }
1456 }
1457 }
1458
1459 impl<const BITS: usize, const LIMBS: usize> Sub<$ty> for Uint<BITS, LIMBS> {
1460 type Output = Self;
1461 fn sub(self, rhs: $ty) -> Self::Output {
1462 let (word, negative) = i128_abs_to_word(rhs as i128);
1463 if negative {
1464 self.add_word(word).0
1465 } else {
1466 self.sub_word(word).0
1467 }
1468 }
1469 }
1470
1471 impl<const BITS: usize, const LIMBS: usize> Mul<$ty> for Uint<BITS, LIMBS> {
1472 type Output = Self;
1473 fn mul(self, rhs: $ty) -> Self::Output {
1474 self.mul_word(i128_abs_to_word(rhs as i128).0).0
1475 }
1476 }
1477
1478 impl<const BITS: usize, const LIMBS: usize> Div<$ty> for Uint<BITS, LIMBS> {
1479 type Output = Self;
1480 fn div(self, rhs: $ty) -> Self::Output {
1481 self.div_rem_word(i128_abs_to_word(rhs as i128).0).0
1482 }
1483 }
1484
1485 impl<const BITS: usize, const LIMBS: usize> Rem<$ty> for Uint<BITS, LIMBS> {
1486 type Output = u64;
1487 fn rem(self, rhs: $ty) -> Self::Output {
1488 self.div_rem_word(i128_abs_to_word(rhs as i128).0).1
1489 }
1490 }
1491 )*
1492 };
1493}
1494
1495macro_rules! impl_int_ops_unsigned {
1496 ($($ty:ty),* $(,)?) => {
1497 $(
1498 impl<const BITS: usize, const LIMBS: usize> Add<$ty> for Int<BITS, LIMBS> {
1499 type Output = Self;
1500 fn add(self, rhs: $ty) -> Self::Output {
1501 self + Self::from_u128(rhs as u128)
1502 }
1503 }
1504
1505 impl<const BITS: usize, const LIMBS: usize> Sub<$ty> for Int<BITS, LIMBS> {
1506 type Output = Self;
1507 fn sub(self, rhs: $ty) -> Self::Output {
1508 self - Self::from_u128(rhs as u128)
1509 }
1510 }
1511
1512 impl<const BITS: usize, const LIMBS: usize> Mul<$ty> for Int<BITS, LIMBS> {
1513 type Output = Self;
1514 fn mul(self, rhs: $ty) -> Self::Output {
1515 let (product, _) = self.abs().mul_word(u128_to_word(rhs as u128));
1516 let bits = if self.is_negative() {
1517 Uint::ZERO.sub_raw(&product).0
1518 } else {
1519 product
1520 };
1521 Self::from_uint_bits(bits)
1522 }
1523 }
1524
1525 impl<const BITS: usize, const LIMBS: usize> Div<$ty> for Int<BITS, LIMBS> {
1526 type Output = Self;
1527 fn div(self, rhs: $ty) -> Self::Output {
1528 let (quotient, _) = self.abs().div_rem_word(u128_to_word(rhs as u128));
1529 let bits = if self.is_negative() {
1530 Uint::ZERO.sub_raw("ient).0
1531 } else {
1532 quotient
1533 };
1534 Self::from_uint_bits(bits)
1535 }
1536 }
1537
1538 impl<const BITS: usize, const LIMBS: usize> Rem<$ty> for Int<BITS, LIMBS> {
1539 type Output = Self;
1540 fn rem(self, rhs: $ty) -> Self::Output {
1541 let (_, remainder) = self.abs().div_rem_word(u128_to_word(rhs as u128));
1542 let bits = Uint::from_u64(remainder);
1543 let bits = if self.is_negative() {
1544 Uint::ZERO.sub_raw(&bits).0
1545 } else {
1546 bits
1547 };
1548 Self::from_uint_bits(bits)
1549 }
1550 }
1551 )*
1552 };
1553}
1554
1555macro_rules! impl_int_ops_signed {
1556 ($($ty:ty),* $(,)?) => {
1557 $(
1558 impl<const BITS: usize, const LIMBS: usize> Add<$ty> for Int<BITS, LIMBS> {
1559 type Output = Self;
1560 fn add(self, rhs: $ty) -> Self::Output {
1561 self + Self::from_i128(rhs as i128)
1562 }
1563 }
1564
1565 impl<const BITS: usize, const LIMBS: usize> Sub<$ty> for Int<BITS, LIMBS> {
1566 type Output = Self;
1567 fn sub(self, rhs: $ty) -> Self::Output {
1568 self - Self::from_i128(rhs as i128)
1569 }
1570 }
1571
1572 impl<const BITS: usize, const LIMBS: usize> Mul<$ty> for Int<BITS, LIMBS> {
1573 type Output = Self;
1574 fn mul(self, rhs: $ty) -> Self::Output {
1575 let (word, negative) = i128_abs_to_word(rhs as i128);
1576 let (product, _) = self.abs().mul_word(word);
1577 let make_negative = self.is_negative() != negative;
1578 let bits = if make_negative {
1579 Uint::ZERO.sub_raw(&product).0
1580 } else {
1581 product
1582 };
1583 Self::from_uint_bits(bits)
1584 }
1585 }
1586
1587 impl<const BITS: usize, const LIMBS: usize> Div<$ty> for Int<BITS, LIMBS> {
1588 type Output = Self;
1589 fn div(self, rhs: $ty) -> Self::Output {
1590 let (word, negative) = i128_abs_to_word(rhs as i128);
1591 let (quotient, _) = self.abs().div_rem_word(word);
1592 let make_negative = self.is_negative() != negative;
1593 let bits = if make_negative {
1594 Uint::ZERO.sub_raw("ient).0
1595 } else {
1596 quotient
1597 };
1598 Self::from_uint_bits(bits)
1599 }
1600 }
1601
1602 impl<const BITS: usize, const LIMBS: usize> Rem<$ty> for Int<BITS, LIMBS> {
1603 type Output = Self;
1604 fn rem(self, rhs: $ty) -> Self::Output {
1605 let (word, _) = i128_abs_to_word(rhs as i128);
1606 let (_, remainder) = self.abs().div_rem_word(word);
1607 let bits = Uint::from_u64(remainder);
1608 let bits = if self.is_negative() {
1609 Uint::ZERO.sub_raw(&bits).0
1610 } else {
1611 bits
1612 };
1613 Self::from_uint_bits(bits)
1614 }
1615 }
1616 )*
1617 };
1618}
1619
1620impl_uint_ops_unsigned!(u8, u16, u32, u64);
1621impl_uint_ops_signed!(i8, i16, i32, i64);
1622impl_int_ops_unsigned!(u8, u16, u32, u64);
1623impl_int_ops_signed!(i8, i16, i32, i64);
1624
1625impl<const BITS: usize, const LIMBS: usize> Add<u128> for Uint<BITS, LIMBS> {
1629 type Output = Self;
1630 fn add(self, rhs: u128) -> Self::Output {
1631 self.add_u128(rhs)
1632 }
1633}
1634
1635impl<const BITS: usize, const LIMBS: usize> Sub<u128> for Uint<BITS, LIMBS> {
1636 type Output = Self;
1637 fn sub(self, rhs: u128) -> Self::Output {
1638 self.sub_u128(rhs)
1639 }
1640}
1641
1642impl<const BITS: usize, const LIMBS: usize> Mul<u128> for Uint<BITS, LIMBS> {
1643 type Output = Self;
1644 fn mul(self, rhs: u128) -> Self::Output {
1645 self.mul_u128(rhs)
1646 }
1647}
1648
1649impl<const BITS: usize, const LIMBS: usize> Div<u128> for Uint<BITS, LIMBS> {
1650 type Output = Self;
1651 fn div(self, rhs: u128) -> Self::Output {
1652 self.div_rem_u128(rhs).0
1653 }
1654}
1655
1656impl<const BITS: usize, const LIMBS: usize> Rem<u128> for Uint<BITS, LIMBS> {
1657 type Output = u128;
1658 fn rem(self, rhs: u128) -> Self::Output {
1659 self.div_rem_u128(rhs).1
1660 }
1661}
1662
1663impl<const BITS: usize, const LIMBS: usize> Add<i128> for Uint<BITS, LIMBS> {
1664 type Output = Self;
1665 fn add(self, rhs: i128) -> Self::Output {
1666 if rhs < 0 {
1667 self.sub_u128(rhs.unsigned_abs())
1668 } else {
1669 self.add_u128(rhs as u128)
1670 }
1671 }
1672}
1673
1674impl<const BITS: usize, const LIMBS: usize> Sub<i128> for Uint<BITS, LIMBS> {
1675 type Output = Self;
1676 fn sub(self, rhs: i128) -> Self::Output {
1677 if rhs < 0 {
1678 self.add_u128(rhs.unsigned_abs())
1679 } else {
1680 self.sub_u128(rhs as u128)
1681 }
1682 }
1683}
1684
1685impl<const BITS: usize, const LIMBS: usize> Mul<i128> for Uint<BITS, LIMBS> {
1686 type Output = Self;
1687 fn mul(self, rhs: i128) -> Self::Output {
1688 self.mul_u128(rhs.unsigned_abs())
1689 }
1690}
1691
1692impl<const BITS: usize, const LIMBS: usize> Div<i128> for Uint<BITS, LIMBS> {
1693 type Output = Self;
1694 fn div(self, rhs: i128) -> Self::Output {
1695 self.div_rem_u128(rhs.unsigned_abs()).0
1696 }
1697}
1698
1699impl<const BITS: usize, const LIMBS: usize> Rem<i128> for Uint<BITS, LIMBS> {
1700 type Output = u128;
1701 fn rem(self, rhs: i128) -> Self::Output {
1702 self.div_rem_u128(rhs.unsigned_abs()).1
1703 }
1704}
1705
1706impl<const BITS: usize, const LIMBS: usize> Add<u128> for Int<BITS, LIMBS> {
1707 type Output = Self;
1708 fn add(self, rhs: u128) -> Self::Output {
1709 self + Self::from_u128(rhs)
1710 }
1711}
1712
1713impl<const BITS: usize, const LIMBS: usize> Sub<u128> for Int<BITS, LIMBS> {
1714 type Output = Self;
1715 fn sub(self, rhs: u128) -> Self::Output {
1716 self - Self::from_u128(rhs)
1717 }
1718}
1719
1720impl<const BITS: usize, const LIMBS: usize> Mul<u128> for Int<BITS, LIMBS> {
1721 type Output = Self;
1722 fn mul(self, rhs: u128) -> Self::Output {
1723 let product = self.abs().mul_u128(rhs);
1724 let bits = if self.is_negative() {
1725 Uint::ZERO.sub_raw(&product).0
1726 } else {
1727 product
1728 };
1729 Self::from_uint_bits(bits)
1730 }
1731}
1732
1733impl<const BITS: usize, const LIMBS: usize> Div<u128> for Int<BITS, LIMBS> {
1734 type Output = Self;
1735 fn div(self, rhs: u128) -> Self::Output {
1736 let (quotient, _) = self.abs().div_rem_u128(rhs);
1737 let bits = if self.is_negative() {
1738 Uint::ZERO.sub_raw("ient).0
1739 } else {
1740 quotient
1741 };
1742 Self::from_uint_bits(bits)
1743 }
1744}
1745
1746impl<const BITS: usize, const LIMBS: usize> Rem<u128> for Int<BITS, LIMBS> {
1747 type Output = Self;
1748 fn rem(self, rhs: u128) -> Self::Output {
1749 let (_, remainder) = self.abs().div_rem_u128(rhs);
1750 let bits = uint_from_u128::<BITS, LIMBS>(remainder);
1751 let bits = if self.is_negative() {
1752 Uint::ZERO.sub_raw(&bits).0
1753 } else {
1754 bits
1755 };
1756 Self::from_uint_bits(bits)
1757 }
1758}
1759
1760impl<const BITS: usize, const LIMBS: usize> Add<i128> for Int<BITS, LIMBS> {
1761 type Output = Self;
1762 fn add(self, rhs: i128) -> Self::Output {
1763 self + Self::from_i128(rhs)
1764 }
1765}
1766
1767impl<const BITS: usize, const LIMBS: usize> Sub<i128> for Int<BITS, LIMBS> {
1768 type Output = Self;
1769 fn sub(self, rhs: i128) -> Self::Output {
1770 self - Self::from_i128(rhs)
1771 }
1772}
1773
1774impl<const BITS: usize, const LIMBS: usize> Mul<i128> for Int<BITS, LIMBS> {
1775 type Output = Self;
1776 fn mul(self, rhs: i128) -> Self::Output {
1777 let product = self.abs().mul_u128(rhs.unsigned_abs());
1778 let make_negative = self.is_negative() != rhs.is_negative();
1779 let bits = if make_negative {
1780 Uint::ZERO.sub_raw(&product).0
1781 } else {
1782 product
1783 };
1784 Self::from_uint_bits(bits)
1785 }
1786}
1787
1788impl<const BITS: usize, const LIMBS: usize> Div<i128> for Int<BITS, LIMBS> {
1789 type Output = Self;
1790 fn div(self, rhs: i128) -> Self::Output {
1791 let (quotient, _) = self.abs().div_rem_u128(rhs.unsigned_abs());
1792 let make_negative = self.is_negative() != rhs.is_negative();
1793 let bits = if make_negative {
1794 Uint::ZERO.sub_raw("ient).0
1795 } else {
1796 quotient
1797 };
1798 Self::from_uint_bits(bits)
1799 }
1800}
1801
1802impl<const BITS: usize, const LIMBS: usize> Rem<i128> for Int<BITS, LIMBS> {
1803 type Output = Self;
1804 fn rem(self, rhs: i128) -> Self::Output {
1805 let (_, remainder) = self.abs().div_rem_u128(rhs.unsigned_abs());
1806 let bits = uint_from_u128::<BITS, LIMBS>(remainder);
1807 let bits = if self.is_negative() {
1808 Uint::ZERO.sub_raw(&bits).0
1809 } else {
1810 bits
1811 };
1812 Self::from_uint_bits(bits)
1813 }
1814}
1815
1816#[cfg(test)]
1817mod tests {
1818 use super::*;
1819 type U256 = Uint<256, 4>;
1820 type U128 = Uint<128, 2>;
1821 type I128 = Int<128, 2>;
1822
1823 const P256_MODULUS: U256 = U256::from_limbs([
1824 0xffff_ffff_ffff_ffff,
1825 0x0000_0000_ffff_ffff,
1826 0x0000_0000_0000_0000,
1827 0xffff_ffff_0000_0001,
1828 ]);
1829 const P256_ORDER: U256 = U256::from_limbs([
1830 0xf3b9_cac2_fc63_2551,
1831 0xbce6_faad_a717_9e84,
1832 0xffff_ffff_ffff_ffff,
1833 0xffff_ffff_0000_0000,
1834 ]);
1835 const P256_P_MINUS_TWO: U256 = U256::from_limbs([
1836 0xffff_ffff_ffff_fffd,
1837 0x0000_0000_ffff_ffff,
1838 0x0000_0000_0000_0000,
1839 0xffff_ffff_0000_0001,
1840 ]);
1841 const P256_P_PLUS_ONE_OVER_FOUR: U256 = U256::from_limbs([
1842 0x0000_0000_0000_0000,
1843 0x0000_0000_4000_0000,
1844 0x4000_0000_0000_0000,
1845 0x3fff_ffff_c000_0000,
1846 ]);
1847 const ED25519_P: U256 = U256::from_limbs([
1848 0xffff_ffff_ffff_ffed,
1849 0xffff_ffff_ffff_ffff,
1850 0xffff_ffff_ffff_ffff,
1851 0x7fff_ffff_ffff_ffff,
1852 ]);
1853
1854 fn decode_hex<const N: usize>(input: &str) -> [u8; N] {
1855 assert_eq!(input.len(), N * 2);
1856 let mut out = [0u8; N];
1857 let bytes = input.as_bytes();
1858 let mut i = 0;
1859 while i < N {
1860 let hi = char_to_digit(bytes[i * 2]).unwrap() as u8;
1861 let lo = char_to_digit(bytes[i * 2 + 1]).unwrap() as u8;
1862 out[i] = (hi << 4) | lo;
1863 i += 1;
1864 }
1865 out
1866 }
1867
1868 #[test]
1869 fn raw_arithmetic_reports_carry_and_borrow() {
1870 let (sum, carry) = U128::MAX.add_raw(&U128::ONE);
1871 assert_eq!(sum, U128::ZERO);
1872 assert_eq!(carry, 1);
1873
1874 let (diff, borrow) = U128::ZERO.sub_raw(&U128::ONE);
1875 assert_eq!(diff, U128::MAX);
1876 assert_eq!(borrow, 1);
1877
1878 let (low, high) = U128::MAX.mul_word(2);
1879 assert_eq!(low, U128::from_limbs([0xffff_ffff_ffff_fffe, 0xffff_ffff_ffff_ffff]));
1880 assert_eq!(high, 1);
1881 }
1882
1883 #[test]
1884 fn modular_arithmetic_matches_known_values() {
1885 assert_eq!(P256_P_MINUS_TWO.add_mod(&U256::from_u64(2), &P256_MODULUS), U256::ZERO);
1886 assert_eq!(
1887 P256_MODULUS.sub_mod(&U256::from_u64(1), &P256_MODULUS),
1888 P256_MODULUS - U256::ONE
1889 );
1890 assert_eq!(P256_P_MINUS_TWO.double_mod(&P256_MODULUS), P256_MODULUS - U256::from_u64(4));
1891 assert_eq!(P256_P_PLUS_ONE_OVER_FOUR.mul_mod(&U256::from_u64(4), &P256_MODULUS), U256::ONE);
1892 assert_eq!(P256_ORDER.add_mod(&U256::ONE, &P256_ORDER), U256::ONE);
1893 }
1894
1895 #[test]
1896 fn string_round_trips_for_common_radices() {
1897 let values = [
1898 U256::ZERO,
1899 U256::ONE,
1900 U256::MAX,
1901 U256::from_be_slice(&decode_hex::<32>(
1902 "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
1903 )),
1904 ];
1905
1906 for value in values {
1907 for radix in [2, 10, 16] {
1908 let encoded = value.to_string_radix(radix);
1909 let decoded = U256::from_str_radix(&encoded, radix).unwrap();
1910 assert_eq!(decoded, value);
1911 }
1912 }
1913 }
1914
1915 #[test]
1916 fn operator_overloads_work_with_primitives() {
1917 let value = U128::from_u64(10);
1918 assert_eq!(value + 5u64, U128::from_u64(15));
1919 assert_eq!(value - (-5i32), U128::from_u64(15));
1920 assert_eq!(value * -3i32, U128::from_u64(30));
1921 assert_eq!(value / -3i32, U128::from_u64(3));
1922 assert_eq!(value % -3i32, 1);
1923
1924 let signed = I128::from_i128(-10);
1925 assert_eq!(signed + 3u32, I128::from_i128(-7));
1926 assert_eq!(signed - (-5i32), I128::from_i128(-5));
1927 assert_eq!(signed * -2i32, I128::from_i128(20));
1928 assert_eq!(signed / -4i32, I128::from_i128(2));
1929 assert_eq!(signed % 4u32, I128::from_i128(-2));
1930 }
1931
1932 #[cfg(feature = "zeroize")]
1933 #[test]
1934 fn zeroize_clears_limb_buffers() {
1935 let mut buffer = [0xA5u64; 8];
1936 zeroize_limbs(&mut buffer);
1937 assert_eq!(buffer, [0u64; 8]);
1938
1939 let mut value = U256::MAX;
1940 zeroize::Zeroize::zeroize(&mut value);
1941 assert!(value.is_zero());
1942 }
1943
1944 #[test]
1945 fn constant_time_helpers_select_and_compare() {
1946 let a = U256::from_u64(7);
1947 let b = U256::from_u64(11);
1948 assert_eq!(U256::ct_select(&a, &b, true), a);
1949 assert_eq!(U256::ct_select(&a, &b, false), b);
1950 assert!(a.ct_eq(&a));
1951 assert!(!a.ct_eq(&b));
1952 assert!(b.ct_ge(&a));
1953 assert!(!a.ct_ge(&b));
1954 }
1955
1956 #[test]
1957 fn from_str_radix_rejects_invalid_inputs() {
1958 assert_eq!(U128::from_str_radix("", 10), Err(Error::EmptyString));
1959 assert_eq!(U128::from_str_radix("10", 1), Err(Error::InvalidRadix));
1960 assert_eq!(U128::from_str_radix("2", 2), Err(Error::InvalidDigit));
1961 assert_eq!(U128::from_str_radix("zz", 10), Err(Error::InvalidDigit));
1962 assert_eq!(
1963 U128::from_str_radix("340282366920938463463374607431768211456", 10),
1964 Err(Error::Overflow)
1965 );
1966 }
1967
1968 #[test]
1969 fn byte_round_trips_match_p256_constants() {
1970 let modulus_hex = "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff";
1971 let order_hex = "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551";
1972
1973 let modulus_bytes = decode_hex::<32>(modulus_hex);
1974 let order_bytes = decode_hex::<32>(order_hex);
1975
1976 let modulus = U256::from_be_slice(&modulus_bytes);
1977 let order = U256::from_be_slice(&order_bytes);
1978
1979 assert_eq!(modulus, P256_MODULUS);
1980 assert_eq!(order, P256_ORDER);
1981 assert_eq!(modulus.to_be_bytes_fixed::<32>(), modulus_bytes);
1982 assert_eq!(order.to_be_bytes_fixed::<32>(), order_bytes);
1983 assert_eq!(format!("{modulus:x}"), modulus_hex);
1984 assert_eq!(format!("{order:X}"), order_hex.to_uppercase());
1985 }
1986
1987 #[test]
1988 fn little_endian_round_trip_works() {
1989 let value = U256::from_be_slice(&decode_hex::<32>(
1990 "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5",
1991 ));
1992 let le = value.to_le_bytes_fixed::<32>();
1993 assert_eq!(U256::from_le_slice(&le), value);
1994 }
1995
1996 #[test]
1997 fn modular_addition_vectors() {
1998 struct Test {
1999 a: U256,
2000 b: U256,
2001 m: U256,
2002 expected: U256,
2003 }
2004 let tests = [
2005 Test {
2006 a: U256::ZERO,
2007 b: U256::ZERO,
2008 m: P256_MODULUS,
2009 expected: U256::ZERO,
2010 },
2011 Test {
2012 a: U256::ZERO,
2013 b: U256::ONE,
2014 m: P256_MODULUS,
2015 expected: U256::ONE,
2016 },
2017 Test {
2018 a: U256::ONE,
2019 b: U256::ONE,
2020 m: P256_MODULUS,
2021 expected: U256::from_u64(2),
2022 },
2023 Test {
2024 a: P256_MODULUS - U256::ONE,
2025 b: U256::ONE,
2026 m: P256_MODULUS,
2027 expected: U256::ZERO,
2028 },
2029 Test {
2030 a: P256_MODULUS - U256::ONE,
2031 b: U256::from_u64(2),
2032 m: P256_MODULUS,
2033 expected: U256::ONE,
2034 },
2035 Test {
2036 a: U256::ZERO,
2037 b: U256::ZERO,
2038 m: P256_ORDER,
2039 expected: U256::ZERO,
2040 },
2041 Test {
2042 a: U256::ZERO,
2043 b: U256::ONE,
2044 m: P256_ORDER,
2045 expected: U256::ONE,
2046 },
2047 Test {
2048 a: U256::ONE,
2049 b: U256::ONE,
2050 m: P256_ORDER,
2051 expected: U256::from_u64(2),
2052 },
2053 Test {
2054 a: U256::MAX,
2055 b: U256::ONE,
2056 m: P256_ORDER,
2057 expected: U256::from_limbs([
2058 0x0c46_353d_039c_daaf,
2059 0x4319_0552_58e8_617b,
2060 0x0000_0000_0000_0000,
2061 0x0000_0000_ffff_ffff,
2062 ]),
2063 },
2064 Test {
2065 a: P256_ORDER - U256::ONE,
2066 b: U256::ONE,
2067 m: P256_ORDER,
2068 expected: U256::ZERO,
2069 },
2070 Test {
2071 a: P256_ORDER - U256::ONE,
2072 b: U256::from_u64(2),
2073 m: P256_ORDER,
2074 expected: U256::ONE,
2075 },
2076 Test {
2077 a: U256::ZERO,
2078 b: U256::ZERO,
2079 m: ED25519_P,
2080 expected: U256::ZERO,
2081 },
2082 Test {
2083 a: U256::ZERO,
2084 b: U256::ONE,
2085 m: ED25519_P,
2086 expected: U256::ONE,
2087 },
2088 Test {
2089 a: U256::ONE,
2090 b: U256::ONE,
2091 m: ED25519_P,
2092 expected: U256::from_u64(2),
2093 },
2094 Test {
2095 a: U256::from_limbs([
2096 0xffff_ffff_ffff_ffff,
2097 0x0000_0000_0000_0000,
2098 0x0000_0000_0000_0000,
2099 0x0000_0000_0000_0000,
2100 ]),
2101 b: U256::ONE,
2102 m: P256_MODULUS,
2103 expected: U256::from_limbs([
2104 0x0000_0000_0000_0000,
2105 0x0000_0000_0000_0001,
2106 0x0000_0000_0000_0000,
2107 0x0000_0000_0000_0000,
2108 ]),
2109 },
2110 Test {
2111 a: U256::from_limbs([
2112 0xffff_ffff_ffff_ffff,
2113 0x0000_0000_0000_0000,
2114 0x0000_0000_0000_0000,
2115 0x0000_0000_0000_0000,
2116 ]),
2117 b: U256::ONE,
2118 m: P256_ORDER,
2119 expected: U256::from_limbs([
2120 0x0000_0000_0000_0000,
2121 0x0000_0000_0000_0001,
2122 0x0000_0000_0000_0000,
2123 0x0000_0000_0000_0000,
2124 ]),
2125 },
2126 Test {
2127 a: U256::from_limbs([
2128 0xffff_ffff_ffff_ffff,
2129 0x0000_0000_0000_0000,
2130 0x0000_0000_0000_0000,
2131 0x0000_0000_0000_0000,
2132 ]),
2133 b: U256::ONE,
2134 m: ED25519_P,
2135 expected: U256::from_limbs([
2136 0x0000_0000_0000_0000,
2137 0x0000_0000_0000_0001,
2138 0x0000_0000_0000_0000,
2139 0x0000_0000_0000_0000,
2140 ]),
2141 },
2142 Test {
2143 a: ED25519_P - U256::ONE,
2144 b: ED25519_P - U256::ONE,
2145 m: ED25519_P,
2146 expected: (ED25519_P - U256::ONE).double_mod(&ED25519_P),
2147 },
2148 ];
2149 for t in &tests {
2150 assert_eq!(t.a.add_mod(&t.b, &t.m), t.expected, "add_mod({:x}, {:x}, {:x})", t.a, t.b, t.m);
2151 }
2152 }
2153
2154 #[test]
2155 fn modular_subtraction_vectors() {
2156 struct Test {
2157 a: U256,
2158 b: U256,
2159 m: U256,
2160 expected: U256,
2161 }
2162 let tests = [
2163 Test {
2164 a: U256::ZERO,
2165 b: U256::ZERO,
2166 m: P256_MODULUS,
2167 expected: U256::ZERO,
2168 },
2169 Test {
2170 a: U256::ONE,
2171 b: U256::ZERO,
2172 m: P256_MODULUS,
2173 expected: U256::ONE,
2174 },
2175 Test {
2176 a: U256::ZERO,
2177 b: U256::ONE,
2178 m: P256_MODULUS,
2179 expected: P256_MODULUS - U256::ONE,
2180 },
2181 Test {
2182 a: P256_MODULUS - U256::ONE,
2183 b: U256::ONE,
2184 m: P256_MODULUS,
2185 expected: P256_MODULUS - U256::from_u64(2),
2186 },
2187 Test {
2188 a: U256::ONE,
2189 b: P256_MODULUS - U256::ONE,
2190 m: P256_MODULUS,
2191 expected: U256::from_u64(2),
2192 },
2193 Test {
2194 a: U256::ZERO,
2195 b: U256::ZERO,
2196 m: P256_ORDER,
2197 expected: U256::ZERO,
2198 },
2199 Test {
2200 a: U256::ONE,
2201 b: U256::ZERO,
2202 m: P256_ORDER,
2203 expected: U256::ONE,
2204 },
2205 Test {
2206 a: U256::ZERO,
2207 b: U256::ONE,
2208 m: P256_ORDER,
2209 expected: P256_ORDER - U256::ONE,
2210 },
2211 Test {
2212 a: P256_ORDER - U256::ONE,
2213 b: U256::ONE,
2214 m: P256_ORDER,
2215 expected: P256_ORDER - U256::from_u64(2),
2216 },
2217 Test {
2218 a: U256::ONE,
2219 b: P256_ORDER - U256::ONE,
2220 m: P256_ORDER,
2221 expected: U256::from_u64(2),
2222 },
2223 Test {
2224 a: U256::ZERO,
2225 b: U256::ZERO,
2226 m: ED25519_P,
2227 expected: U256::ZERO,
2228 },
2229 Test {
2230 a: U256::ONE,
2231 b: U256::ZERO,
2232 m: ED25519_P,
2233 expected: U256::ONE,
2234 },
2235 Test {
2236 a: U256::ZERO,
2237 b: U256::ONE,
2238 m: ED25519_P,
2239 expected: ED25519_P - U256::ONE,
2240 },
2241 Test {
2242 a: ED25519_P - U256::ONE,
2243 b: U256::ONE,
2244 m: ED25519_P,
2245 expected: ED25519_P - U256::from_u64(2),
2246 },
2247 Test {
2248 a: U256::ONE,
2249 b: ED25519_P - U256::ONE,
2250 m: ED25519_P,
2251 expected: U256::from_u64(2),
2252 },
2253 ];
2254 for t in &tests {
2255 assert_eq!(t.a.sub_mod(&t.b, &t.m), t.expected, "sub_mod({:x}, {:x}, {:x})", t.a, t.b, t.m);
2256 }
2257 }
2258
2259 #[test]
2260 fn modular_multiplication_vectors() {
2261 struct Test {
2262 a: U256,
2263 b: U256,
2264 m: U256,
2265 expected: U256,
2266 }
2267 let tests = [
2268 Test {
2269 a: U256::ZERO,
2270 b: U256::ZERO,
2271 m: P256_MODULUS,
2272 expected: U256::ZERO,
2273 },
2274 Test {
2275 a: U256::ZERO,
2276 b: U256::ONE,
2277 m: P256_MODULUS,
2278 expected: U256::ZERO,
2279 },
2280 Test {
2281 a: U256::ONE,
2282 b: U256::ZERO,
2283 m: P256_MODULUS,
2284 expected: U256::ZERO,
2285 },
2286 Test {
2287 a: U256::ONE,
2288 b: U256::ONE,
2289 m: P256_MODULUS,
2290 expected: U256::ONE,
2291 },
2292 Test {
2293 a: U256::from_u64(2),
2294 b: U256::from_u64(3),
2295 m: P256_MODULUS,
2296 expected: U256::from_u64(6),
2297 },
2298 Test {
2299 a: U256::MAX,
2300 b: U256::ONE,
2301 m: P256_MODULUS,
2302 expected: U256::from_limbs([
2303 0x0000_0000_0000_0000,
2304 0xffff_ffff_0000_0000,
2305 0xffff_ffff_ffff_ffff,
2306 0x0000_0000_ffff_fffe,
2307 ]),
2308 },
2309 Test {
2310 a: P256_MODULUS - U256::ONE,
2311 b: U256::ONE,
2312 m: P256_MODULUS,
2313 expected: P256_MODULUS - U256::ONE,
2314 },
2315 Test {
2316 a: P256_MODULUS - U256::ONE,
2317 b: P256_MODULUS - U256::ONE,
2318 m: P256_MODULUS,
2319 expected: U256::ONE,
2320 },
2321 Test {
2322 a: P256_MODULUS + U256::ONE,
2323 b: P256_MODULUS + U256::ONE,
2324 m: P256_MODULUS,
2325 expected: U256::ONE,
2326 },
2327 Test {
2328 a: U256::ZERO,
2329 b: U256::ZERO,
2330 m: P256_ORDER,
2331 expected: U256::ZERO,
2332 },
2333 Test {
2334 a: U256::ZERO,
2335 b: U256::ONE,
2336 m: P256_ORDER,
2337 expected: U256::ZERO,
2338 },
2339 Test {
2340 a: U256::ONE,
2341 b: U256::ZERO,
2342 m: P256_ORDER,
2343 expected: U256::ZERO,
2344 },
2345 Test {
2346 a: U256::ONE,
2347 b: U256::ONE,
2348 m: P256_ORDER,
2349 expected: U256::ONE,
2350 },
2351 Test {
2352 a: U256::from_u64(2),
2353 b: U256::from_u64(3),
2354 m: P256_ORDER,
2355 expected: U256::from_u64(6),
2356 },
2357 Test {
2358 a: P256_ORDER - U256::ONE,
2359 b: U256::ONE,
2360 m: P256_ORDER,
2361 expected: P256_ORDER - U256::ONE,
2362 },
2363 Test {
2364 a: P256_ORDER - U256::ONE,
2365 b: P256_ORDER - U256::ONE,
2366 m: P256_ORDER,
2367 expected: U256::ONE,
2368 },
2369 Test {
2370 a: P256_ORDER + U256::ONE,
2371 b: P256_ORDER + U256::ONE,
2372 m: P256_ORDER,
2373 expected: U256::ONE,
2374 },
2375 Test {
2376 a: U256::ZERO,
2377 b: U256::ZERO,
2378 m: ED25519_P,
2379 expected: U256::ZERO,
2380 },
2381 Test {
2382 a: U256::ZERO,
2383 b: U256::ONE,
2384 m: ED25519_P,
2385 expected: U256::ZERO,
2386 },
2387 Test {
2388 a: U256::ONE,
2389 b: U256::ZERO,
2390 m: ED25519_P,
2391 expected: U256::ZERO,
2392 },
2393 Test {
2394 a: U256::ONE,
2395 b: U256::ONE,
2396 m: ED25519_P,
2397 expected: U256::ONE,
2398 },
2399 Test {
2400 a: U256::from_u64(2),
2401 b: U256::from_u64(3),
2402 m: ED25519_P,
2403 expected: U256::from_u64(6),
2404 },
2405 Test {
2406 a: ED25519_P - U256::ONE,
2407 b: U256::ONE,
2408 m: ED25519_P,
2409 expected: ED25519_P - U256::ONE,
2410 },
2411 Test {
2412 a: ED25519_P - U256::ONE,
2413 b: ED25519_P - U256::ONE,
2414 m: ED25519_P,
2415 expected: U256::ONE,
2416 },
2417 Test {
2418 a: ED25519_P + U256::ONE,
2419 b: ED25519_P + U256::ONE,
2420 m: ED25519_P,
2421 expected: U256::ONE,
2422 },
2423 Test {
2424 a: U256::from_limbs([
2425 0xffff_ffff_ffff_ffff,
2426 0x0000_0000_0000_0000,
2427 0x0000_0000_0000_0000,
2428 0x0000_0000_0000_0000,
2429 ]),
2430 b: U256::from_limbs([
2431 0xffff_ffff_ffff_ffff,
2432 0x0000_0000_0000_0000,
2433 0x0000_0000_0000_0000,
2434 0x0000_0000_0000_0000,
2435 ]),
2436 m: P256_MODULUS,
2437 expected: U256::from_limbs([
2438 0x0000_0000_0000_0001,
2439 0xffff_ffff_ffff_fffe,
2440 0x0000_0000_0000_0000,
2441 0x0000_0000_0000_0000,
2442 ]),
2443 },
2444 ];
2445 for t in &tests {
2446 assert_eq!(t.a.mul_mod(&t.b, &t.m), t.expected, "mul_mod({:x}, {:x}, {:x})", t.a, t.b, t.m);
2447 }
2448 }
2449
2450 #[test]
2451 fn raw_addition_vectors() {
2452 struct Test {
2453 a: U256,
2454 b: U256,
2455 expected_sum: U256,
2456 expected_carry: u64,
2457 }
2458 let tests = [
2459 Test {
2460 a: U256::ZERO,
2461 b: U256::ZERO,
2462 expected_sum: U256::ZERO,
2463 expected_carry: 0,
2464 },
2465 Test {
2466 a: U256::ZERO,
2467 b: U256::ONE,
2468 expected_sum: U256::ONE,
2469 expected_carry: 0,
2470 },
2471 Test {
2472 a: U256::ONE,
2473 b: U256::ONE,
2474 expected_sum: U256::from_u64(2),
2475 expected_carry: 0,
2476 },
2477 Test {
2478 a: U256::MAX,
2479 b: U256::ZERO,
2480 expected_sum: U256::MAX,
2481 expected_carry: 0,
2482 },
2483 Test {
2484 a: U256::MAX,
2485 b: U256::ONE,
2486 expected_sum: U256::ZERO,
2487 expected_carry: 1,
2488 },
2489 Test {
2490 a: U256::MAX,
2491 b: U256::MAX,
2492 expected_sum: U256::MAX - U256::ONE,
2493 expected_carry: 1,
2494 },
2495 Test {
2496 a: U256::MAX - U256::ONE,
2497 b: U256::ONE,
2498 expected_sum: U256::MAX,
2499 expected_carry: 0,
2500 },
2501 Test {
2502 a: U256::ONE,
2503 b: U256::MAX,
2504 expected_sum: U256::ZERO,
2505 expected_carry: 1,
2506 },
2507 Test {
2508 a: U256::from_limbs([
2509 0xffff_ffff_ffff_ffff,
2510 0x0000_0000_0000_0000,
2511 0x0000_0000_0000_0000,
2512 0x0000_0000_0000_0000,
2513 ]),
2514 b: U256::ONE,
2515 expected_sum: U256::from_limbs([
2516 0x0000_0000_0000_0000,
2517 0x0000_0000_0000_0001,
2518 0x0000_0000_0000_0000,
2519 0x0000_0000_0000_0000,
2520 ]),
2521 expected_carry: 0,
2522 },
2523 Test {
2524 a: U256::from_limbs([
2525 0xffff_ffff_ffff_ffff,
2526 0xffff_ffff_ffff_ffff,
2527 0x0000_0000_0000_0000,
2528 0x0000_0000_0000_0000,
2529 ]),
2530 b: U256::ONE,
2531 expected_sum: U256::from_limbs([
2532 0x0000_0000_0000_0000,
2533 0x0000_0000_0000_0000,
2534 0x0000_0000_0000_0001,
2535 0x0000_0000_0000_0000,
2536 ]),
2537 expected_carry: 0,
2538 },
2539 ];
2540 for t in &tests {
2541 let (sum, carry) = t.a.add_raw(&t.b);
2542 assert_eq!(sum, t.expected_sum, "add_raw({:x}, {:x}).sum", t.a, t.b);
2543 assert_eq!(carry, t.expected_carry, "add_raw({:x}, {:x}).carry", t.a, t.b);
2544 }
2545 }
2546
2547 #[test]
2548 fn raw_subtraction_vectors() {
2549 struct Test {
2550 a: U256,
2551 b: U256,
2552 expected_diff: U256,
2553 expected_borrow: u64,
2554 }
2555 let tests = [
2556 Test {
2557 a: U256::ZERO,
2558 b: U256::ZERO,
2559 expected_diff: U256::ZERO,
2560 expected_borrow: 0,
2561 },
2562 Test {
2563 a: U256::ONE,
2564 b: U256::ZERO,
2565 expected_diff: U256::ONE,
2566 expected_borrow: 0,
2567 },
2568 Test {
2569 a: U256::ONE,
2570 b: U256::ONE,
2571 expected_diff: U256::ZERO,
2572 expected_borrow: 0,
2573 },
2574 Test {
2575 a: U256::ZERO,
2576 b: U256::ONE,
2577 expected_diff: U256::MAX,
2578 expected_borrow: 1,
2579 },
2580 Test {
2581 a: U256::MAX,
2582 b: U256::MAX,
2583 expected_diff: U256::ZERO,
2584 expected_borrow: 0,
2585 },
2586 Test {
2587 a: U256::MAX,
2588 b: U256::ZERO,
2589 expected_diff: U256::MAX,
2590 expected_borrow: 0,
2591 },
2592 Test {
2593 a: U256::MAX,
2594 b: U256::MAX - U256::ONE,
2595 expected_diff: U256::ONE,
2596 expected_borrow: 0,
2597 },
2598 Test {
2599 a: U256::ONE,
2600 b: U256::MAX,
2601 expected_diff: U256::from_u64(2),
2602 expected_borrow: 1,
2603 },
2604 ];
2605 for t in &tests {
2606 let (diff, borrow) = t.a.sub_raw(&t.b);
2607 assert_eq!(diff, t.expected_diff, "sub_raw({:x}, {:x}).diff", t.a, t.b);
2608 assert_eq!(borrow, t.expected_borrow, "sub_raw({:x}, {:x}).borrow", t.a, t.b);
2609 }
2610 }
2611
2612 #[test]
2613 fn string_roundtrip_vectors() {
2614 struct Test {
2615 value: U256,
2616 radix: u32,
2617 expected: &'static str,
2618 }
2619 let tests = [
2620 Test {
2621 value: U256::ZERO,
2622 radix: 2,
2623 expected: "0",
2624 },
2625 Test {
2626 value: U256::ZERO,
2627 radix: 10,
2628 expected: "0",
2629 },
2630 Test {
2631 value: U256::ZERO,
2632 radix: 16,
2633 expected: "0",
2634 },
2635 Test {
2636 value: U256::ONE,
2637 radix: 2,
2638 expected: "1",
2639 },
2640 Test {
2641 value: U256::ONE,
2642 radix: 10,
2643 expected: "1",
2644 },
2645 Test {
2646 value: U256::ONE,
2647 radix: 16,
2648 expected: "1",
2649 },
2650 Test {
2651 value: U256::MAX,
2652 radix: 10,
2653 expected: "115792089237316195423570985008687907853269984665640564039457584007913129639935",
2654 },
2655 Test {
2656 value: U256::MAX,
2657 radix: 16,
2658 expected: "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
2659 },
2660 Test {
2661 value: P256_MODULUS,
2662 radix: 10,
2663 expected: "115792089210356248762697446949407573530086143415290314195533631308867097853951",
2664 },
2665 Test {
2666 value: P256_MODULUS,
2667 radix: 16,
2668 expected: "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff",
2669 },
2670 Test {
2671 value: P256_ORDER,
2672 radix: 10,
2673 expected: "115792089210356248762697446949407573529996955224135760342422259061068512044369",
2674 },
2675 Test {
2676 value: P256_ORDER,
2677 radix: 16,
2678 expected: "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551",
2679 },
2680 Test {
2681 value: ED25519_P,
2682 radix: 10,
2683 expected: "57896044618658097711785492504343953926634992332820282019728792003956564819949",
2684 },
2685 Test {
2686 value: ED25519_P,
2687 radix: 16,
2688 expected: "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
2689 },
2690 ];
2691 for t in &tests {
2692 let encoded = t.value.to_string_radix(t.radix);
2693 assert_eq!(encoded, t.expected, "to_string_radix({:x}, {})", t.value, t.radix);
2694 let decoded = U256::from_str_radix(t.expected, t.radix).unwrap();
2695 assert_eq!(decoded, t.value, "from_str_radix round-trip");
2696 }
2697 }
2698
2699 #[test]
2700 fn mul_mod_edge_cases() {
2701 assert_eq!(P256_P_PLUS_ONE_OVER_FOUR.mul_mod(&U256::from_u64(4), &P256_MODULUS), U256::ONE);
2702
2703 let (a, _) = U256::MAX.mul_word(2);
2704 assert_eq!(a.add_mod(&U256::ZERO, &P256_MODULUS), U256::MAX.double_mod(&P256_MODULUS));
2705 }
2706
2707 const P256_GX: U256 = U256::from_be_slice_const(
2710 0x6b17d1f2, 0xe12c4247, 0xf8bce6e5, 0x63a440f2, 0x77037d81, 0x2deb33a0, 0xf4a13945, 0xd898c296,
2711 );
2712 const P256_GY: U256 = U256::from_be_slice_const(
2713 0x4fe342e2, 0xfe1a7f9b, 0x8ee7eb4a, 0x7c0f9e16, 0x2bce3357, 0x6b315ece, 0xcbb64068, 0x37bf51f5,
2714 );
2715
2716 impl<const BITS: usize, const LIMBS: usize> Uint<BITS, LIMBS> {
2717 const fn from_be_slice_const(w7: u32, w6: u32, w5: u32, w4: u32, w3: u32, w2: u32, w1: u32, w0: u32) -> Self {
2720 let limb3 = ((w7 as u64) << 32) | (w6 as u64);
2721 let limb2 = ((w5 as u64) << 32) | (w4 as u64);
2722 let limb1 = ((w3 as u64) << 32) | (w2 as u64);
2723 let limb0 = ((w1 as u64) << 32) | (w0 as u64);
2724 let limbs = [0u64; LIMBS];
2725 if LIMBS > 0 {
2726 let mut l = [0u64; LIMBS];
2727 l[0] = limb0;
2728 l[1] = limb1;
2729 l[2] = limb2;
2730 l[3] = limb3;
2731 return Self {
2732 limbs: l,
2733 };
2734 }
2735 Self {
2736 limbs,
2737 }
2738 }
2739 }
2740
2741 #[test]
2742 fn p256_mul_mod_with_generator_coordinates() {
2743 let gx_gy_mod_p = U256::from_be_slice(&decode_hex::<32>(
2745 "823cd15f6dd3c71933565064513a6b2bd183e554c6a08622f713ebbbface98be",
2746 ));
2747 let gx_sq_mod_p = U256::from_be_slice(&decode_hex::<32>(
2748 "98f6b84d29bef2b281819a5e0e3690d833b699495d694dd1002ae56c426b3f8c",
2749 ));
2750 let gy_sq_mod_p = U256::from_be_slice(&decode_hex::<32>(
2751 "55df5d5850f47bad82149139979369fe498a9022a412b5e0bedd2cfc21c3ed91",
2752 ));
2753
2754 assert_eq!(P256_GX.mul_mod(&P256_GY, &P256_MODULUS), gx_gy_mod_p, "Gx*Gy mod p");
2755 assert_eq!(
2757 P256_GY.mul_mod(&P256_GX, &P256_MODULUS),
2758 gx_gy_mod_p,
2759 "Gy*Gx mod p (commutativity)"
2760 );
2761 assert_eq!(P256_GX.mul_mod(&P256_GX, &P256_MODULUS), gx_sq_mod_p, "Gx^2 mod p");
2762 assert_eq!(P256_GY.mul_mod(&P256_GY, &P256_MODULUS), gy_sq_mod_p, "Gy^2 mod p");
2763 }
2764
2765 #[test]
2766 fn p256_add_sub_mod_with_generator_coordinates() {
2767 let gx_plus_gy = U256::from_be_slice(&decode_hex::<32>(
2769 "bafb14d5df46c1e387a4d22fdfb3df08a2d1b0d8991c926fc05779ae1058148b",
2770 ));
2771 let gx_minus_gy = U256::from_be_slice(&decode_hex::<32>(
2773 "1b348f0fe311c2ac69d4fb9ae794a2dc4b354a29c2b9d4d228eaf8dda0d970a1",
2774 ));
2775 let gy_minus_gx = U256::from_be_slice(&decode_hex::<32>(
2777 "e4cb70ef1cee3d54962b0465186b5d23b4cab5d73d462b2dd71507225f268f5e",
2778 ));
2779
2780 assert_eq!(P256_GX.add_mod(&P256_GY, &P256_MODULUS), gx_plus_gy);
2781 assert_eq!(P256_GX.sub_mod(&P256_GY, &P256_MODULUS), gx_minus_gy);
2782 assert_eq!(P256_GY.sub_mod(&P256_GX, &P256_MODULUS), gy_minus_gx);
2783 assert_eq!(gx_minus_gy.add_mod(&gy_minus_gx, &P256_MODULUS), U256::ZERO);
2785 }
2786
2787 #[test]
2788 fn bit_access() {
2789 assert!(!P256_GX.bit(0), "bit 0 of Gx");
2792 assert!(P256_GX.bit(1), "bit 1 of Gx");
2793 assert!(P256_GX.bit(2), "bit 2 of Gx");
2794 assert!(P256_GX.bit(63), "bit 63 of Gx");
2795 assert!(!P256_GX.bit(64), "bit 64 of Gx");
2796 assert!(!P256_GX.bit(65), "bit 65 of Gx");
2797 assert!(!P256_GX.bit(127), "bit 127 of Gx");
2798 assert!(!P256_GX.bit(128), "bit 128 of Gx");
2799 assert!(P256_GX.bit(192), "bit 192 of Gx");
2800 assert!(!P256_GX.bit(255), "bit 255 of Gx");
2801 assert!(!P256_GX.bit(256), "bit 256 (out of range) of Gx");
2803
2804 assert!(P256_MODULUS.bit(0), "bit 0 of p256_p");
2806 assert!(P256_MODULUS.bit(63), "bit 63 of p256_p");
2807 assert!(P256_MODULUS.bit(64), "bit 64 of p256_p");
2808 assert!(!P256_MODULUS.bit(96), "bit 96 of p256_p");
2809 assert!(P256_MODULUS.bit(255), "bit 255 of p256_p");
2810
2811 assert!(!U256::ZERO.bit(0));
2812 assert!(!U256::ZERO.bit(255));
2813 assert!(U256::ONE.bit(0));
2814 assert!(!U256::ONE.bit(1));
2815 assert!(U256::MAX.bit(0));
2816 assert!(U256::MAX.bit(255));
2817 }
2818
2819 #[test]
2820 fn is_odd_flag() {
2821 assert!(!U256::ZERO.is_odd(), "0 is even");
2822 assert!(U256::ONE.is_odd(), "1 is odd");
2823 assert!(!U256::from_u64(2).is_odd(), "2 is even");
2824 assert!(U256::from_u64(3).is_odd(), "3 is odd");
2825 assert!(P256_MODULUS.is_odd(), "p256_p is odd");
2826 assert!(P256_ORDER.is_odd(), "p256_n is odd");
2827 assert!(!P256_GX.is_odd(), "Gx is even");
2828 assert!(P256_GY.is_odd(), "Gy is odd");
2829 assert!(U256::MAX.is_odd(), "MAX is odd");
2830 }
2831
2832 #[test]
2833 fn ct_ge_comprehensive() {
2834 let zero = U256::ZERO;
2835 let one = U256::ONE;
2836 let max = U256::MAX;
2837
2838 assert!(zero.ct_ge(&zero), "0 >= 0");
2840 assert!(one.ct_ge(&one), "1 >= 1");
2841 assert!(max.ct_ge(&max), "MAX >= MAX");
2842 assert!(P256_MODULUS.ct_ge(&P256_MODULUS), "p >= p");
2843
2844 assert!(one.ct_ge(&zero), "1 >= 0");
2846 assert!(max.ct_ge(&zero), "MAX >= 0");
2847 assert!(max.ct_ge(&one), "MAX >= 1");
2848 assert!(P256_GX.ct_ge(&zero), "Gx >= 0");
2849
2850 assert!(!zero.ct_ge(&one), "NOT 0 >= 1");
2852 assert!(!zero.ct_ge(&max), "NOT 0 >= MAX");
2853 assert!(!one.ct_ge(&max), "NOT 1 >= MAX");
2854 assert!(!P256_GX.ct_ge(&max), "NOT Gx >= MAX");
2855
2856 assert!((P256_MODULUS - U256::ONE).ct_ge(&(P256_MODULUS - U256::from_u64(2))));
2858 assert!(!P256_MODULUS.sub_mod(&U256::ONE, &P256_MODULUS).ct_ge(&P256_MODULUS));
2859 }
2860
2861 #[test]
2862 fn div_rem_word_vectors() {
2863 struct Test {
2866 dividend: U256,
2867 divisor: u64,
2868 expected_quotient: U256,
2869 expected_rem: u64,
2870 }
2871 let tests = [
2872 Test {
2873 dividend: P256_MODULUS,
2874 divisor: 1,
2875 expected_quotient: P256_MODULUS,
2876 expected_rem: 0,
2877 },
2878 Test {
2879 dividend: P256_MODULUS,
2880 divisor: 2,
2881 expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2882 "7fffffff800000008000000000000000000000007fffffffffffffffffffffff",
2883 )),
2884 expected_rem: 1,
2885 },
2886 Test {
2887 dividend: P256_MODULUS,
2888 divisor: 10,
2889 expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2890 "1999999980000000199999999999999999999999b33333333333333333333333",
2891 )),
2892 expected_rem: 1,
2893 },
2894 Test {
2895 dividend: P256_MODULUS,
2896 divisor: 16,
2897 expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2898 "0ffffffff00000001000000000000000000000000fffffffffffffffffffffff",
2899 )),
2900 expected_rem: 0xf,
2901 },
2902 Test {
2903 dividend: P256_MODULUS,
2904 divisor: 0xffff_ffff,
2905 expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2906 "0000000100000000000000010000000100000001000000020000000200000002",
2907 )),
2908 expected_rem: 1,
2909 },
2910 Test {
2911 dividend: P256_MODULUS,
2912 divisor: 0x1_0000_0000,
2913 expected_quotient: U256::from_be_slice(&decode_hex::<32>(
2914 "00000000ffffffff00000001000000000000000000000000ffffffffffffffff",
2915 )),
2916 expected_rem: 0xffff_ffff,
2917 },
2918 Test {
2919 dividend: U256::ZERO,
2920 divisor: 7,
2921 expected_quotient: U256::ZERO,
2922 expected_rem: 0,
2923 },
2924 Test {
2925 dividend: U256::ONE,
2926 divisor: 7,
2927 expected_quotient: U256::ZERO,
2928 expected_rem: 1,
2929 },
2930 Test {
2931 dividend: U256::from_u64(100),
2932 divisor: 7,
2933 expected_quotient: U256::from_u64(14),
2934 expected_rem: 2,
2935 },
2936 ];
2937 for t in &tests {
2938 let (q, r) = t.dividend.div_rem_word(t.divisor);
2939 assert_eq!(q, t.expected_quotient, "div_rem_word({:x}, {}).quotient", t.dividend, t.divisor);
2940 assert_eq!(r, t.expected_rem, "div_rem_word({:x}, {}).rem", t.dividend, t.divisor);
2941 }
2942 }
2943
2944 #[test]
2945 fn add_word_vectors() {
2946 let gx = P256_GX;
2948 let gx_plus_1 = U256::from_be_slice(&decode_hex::<32>(
2949 "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c297",
2950 ));
2951 let gx_minus_1 = U256::from_be_slice(&decode_hex::<32>(
2952 "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c295",
2953 ));
2954
2955 let (sum, carry) = gx.add_word(1);
2956 assert_eq!(sum, gx_plus_1, "Gx + 1");
2957 assert_eq!(carry, 0);
2958
2959 let (diff, borrow) = gx.sub_word(1);
2960 assert_eq!(diff, gx_minus_1, "Gx - 1");
2961 assert_eq!(borrow, 0);
2962
2963 let (sum_max, carry_max) = U256::MAX.add_word(1);
2965 assert_eq!(sum_max, U256::ZERO);
2966 assert_eq!(carry_max, 1);
2967
2968 let (diff_zero, borrow_zero) = U256::ZERO.sub_word(1);
2970 assert_eq!(diff_zero, U256::MAX);
2971 assert_eq!(borrow_zero, 1);
2972
2973 let val = U256::from_u64(u64::MAX);
2975 let (sum2, carry2) = val.add_word(1);
2976 assert_eq!(sum2, U256::from_limbs([0, 1, 0, 0]));
2977 assert_eq!(carry2, 0);
2978 }
2979
2980 #[test]
2981 fn mul_word_vectors() {
2982 let gx_times_2 = U256::from_be_slice(&decode_hex::<32>(
2985 "d62fa3e5c258848ff179cdcac74881e4ee06fb025bd66741e942728bb131852c",
2986 ));
2987 let (prod, carry) = P256_GX.mul_word(2);
2988 assert_eq!(prod, gx_times_2, "Gx * 2");
2989 assert_eq!(carry, 0, "Gx * 2 carry");
2990
2991 let (prod_max, carry_max) = U256::MAX.mul_word(2);
2993 assert_eq!(prod_max, U256::from_limbs([u64::MAX - 1, u64::MAX, u64::MAX, u64::MAX]));
2994 assert_eq!(carry_max, 1);
2995
2996 let (zero_prod, zero_carry) = U256::ONE.mul_word(0);
2998 assert_eq!(zero_prod, U256::ZERO);
2999 assert_eq!(zero_carry, 0);
3000
3001 let (p, c) = U128::from_u64(u64::MAX).mul_word(u64::MAX);
3003 assert_eq!(p, U128::from_limbs([1, u64::MAX - 1]));
3006 assert_eq!(c, 0);
3007 }
3008
3009 #[test]
3010 fn fibonacci_number_round_trip() {
3011 let fib100_dec = "354224848179261915075";
3015 let fib100_hex = "1333db76a7c594bfc3";
3016
3017 let from_dec = U128::from_str_radix(fib100_dec, 10).unwrap();
3018 let from_hex = U128::from_str_radix(fib100_hex, 16).unwrap();
3019
3020 assert_eq!(from_dec, from_hex, "Fib(100) from decimal == from hex");
3021 assert_eq!(from_dec.to_string_radix(10), fib100_dec);
3022 assert_eq!(from_dec.to_string_radix(16), fib100_hex);
3023
3024 let fib100_bin = from_dec.to_string_radix(2);
3026 let from_bin = U128::from_str_radix(&fib100_bin, 2).unwrap();
3027 assert_eq!(from_bin, from_dec);
3028
3029 let fib100_oct = from_dec.to_string_radix(8);
3031 let from_oct = U128::from_str_radix(&fib100_oct, 8).unwrap();
3032 assert_eq!(from_oct, from_dec);
3033 }
3034
3035 #[test]
3036 fn display_and_debug_formatting() {
3037 assert_eq!(format!("{}", U256::ZERO), "0");
3039 assert_eq!(format!("{}", U256::ONE), "1");
3040 assert_eq!(
3041 format!("{}", U256::MAX),
3042 "115792089237316195423570985008687907853269984665640564039457584007913129639935"
3043 );
3044 assert_eq!(
3045 format!("{}", P256_MODULUS),
3046 "115792089210356248762697446949407573530086143415290314195533631308867097853951"
3047 );
3048
3049 assert_eq!(format!("{:x}", U256::ZERO), "0");
3051 assert_eq!(format!("{:x}", U256::ONE), "1");
3052 assert_eq!(
3053 format!("{:x}", U256::MAX),
3054 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
3055 );
3056 assert_eq!(format!("{:#x}", U256::from_u64(255)), "0xff");
3057
3058 assert_eq!(format!("{:X}", U256::ZERO), "0");
3060 assert_eq!(
3061 format!("{:X}", P256_MODULUS),
3062 "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"
3063 );
3064 assert_eq!(format!("{:#X}", U256::from_u64(255)), "0xFF");
3065
3066 assert_eq!(format!("{:?}", U256::ZERO), "Uint(0x0)");
3068 assert_eq!(format!("{:?}", U256::ONE), "Uint(0x1)");
3069 assert_eq!(
3070 format!("{:?}", P256_MODULUS),
3071 "Uint(0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff)"
3072 );
3073 }
3074
3075 #[test]
3076 fn to_be_le_bytes_vec() {
3077 let values = [U256::ZERO, U256::ONE, U256::MAX, P256_MODULUS, P256_GX, P256_GY];
3079 for v in &values {
3080 let be_vec = v.to_be_bytes();
3081 let be_fixed = v.to_be_bytes_fixed::<32>();
3082 assert_eq!(be_vec.as_slice(), be_fixed.as_slice(), "BE bytes of {:x}", v);
3083
3084 let le_vec = v.to_le_bytes();
3085 let le_fixed = v.to_le_bytes_fixed::<32>();
3086 assert_eq!(le_vec.as_slice(), le_fixed.as_slice(), "LE bytes of {:x}", v);
3087
3088 let rt_be = U256::from_be_slice(&be_vec);
3090 assert_eq!(rt_be, *v, "BE round-trip of {:x}", v);
3091
3092 let rt_le = U256::from_le_slice(&le_vec);
3094 assert_eq!(rt_le, *v, "LE round-trip of {:x}", v);
3095 }
3096 }
3097
3098 #[test]
3099 fn max_for_non_64_multiple_bits() {
3100 type U130 = Uint<130, 3>;
3106 let max = U130::MAX;
3107 assert_eq!(max.limbs[0], u64::MAX, "U130::MAX limb[0]");
3108 assert_eq!(max.limbs[1], u64::MAX, "U130::MAX limb[1]");
3109 assert_eq!(max.limbs[2], 0b11, "U130::MAX limb[2] should have only 2 bits set");
3110
3111 type U192 = Uint<192, 3>;
3113 let max192 = U192::MAX;
3114 assert_eq!(max192.limbs[0], u64::MAX, "U192::MAX limb[0]");
3115 assert_eq!(max192.limbs[1], u64::MAX, "U192::MAX limb[1]");
3116 assert_eq!(max192.limbs[2], u64::MAX, "U192::MAX limb[2]");
3117
3118 type U65 = Uint<65, 2>;
3120 let max65 = U65::MAX;
3121 assert_eq!(max65.limbs[0], u64::MAX, "U65::MAX limb[0]");
3122 assert_eq!(max65.limbs[1], 1, "U65::MAX limb[1] should be 1 (bit 64 only)");
3123 }
3124
3125 #[test]
3126 fn mul_mod_associativity_and_identity() {
3127 let a = P256_GX;
3129 let b = P256_GY;
3130 let c = P256_MODULUS - U256::ONE;
3131 let m = P256_MODULUS;
3132
3133 let ab = a.mul_mod(&b, &m);
3134 let bc = b.mul_mod(&c, &m);
3135
3136 assert_eq!(ab.mul_mod(&c, &m), a.mul_mod(&bc, &m), "associativity");
3137
3138 assert_eq!(a.mul_mod(&U256::ONE, &m), a, "a * 1 = a");
3140 assert_eq!(U256::ONE.mul_mod(&a, &m), a, "1 * a = a");
3141
3142 assert_eq!(a.mul_mod(&U256::ZERO, &m), U256::ZERO, "a * 0 = 0");
3144 assert_eq!(U256::ZERO.mul_mod(&a, &m), U256::ZERO, "0 * a = 0");
3145
3146 let ab_sum = a.add_mod(&b, &m);
3148 let lhs = ab_sum.mul_mod(&c, &m);
3149 let rhs = a.mul_mod(&c, &m).add_mod(&b.mul_mod(&c, &m), &m);
3150 assert_eq!(lhs, rhs, "distributivity");
3151 }
3152
3153 #[test]
3154 fn mul_mod_barrett_agrees_with_mul_mod() {
3155 type U256 = Uint<256, 4>;
3157 let a = U256::from_u64(7);
3158 let b = U256::from_u64(11);
3159 let m = U256::from_limbs([
3160 0xffff_ffff_ffff_ffff,
3161 0x0000_0000_ffff_ffff,
3162 0x0000_0000_0000_0000,
3163 0xffff_ffff_0000_0001,
3164 ]);
3165 let mu = m.compute_mu_for_barrett();
3166 let barrett = a.mul_mod_barrett(&b, &m, &mu);
3167 let standard = a.mul_mod(&b, &m);
3168 assert_eq!(barrett, standard);
3169 }
3170
3171 #[test]
3172 fn modpow_barrett_agrees_with_modpow() {
3173 type U256 = Uint<256, 4>;
3174 let m = U256::from_limbs([
3176 0xffff_ffff_ffff_ffff,
3177 0x0000_0000_ffff_ffff,
3178 0x0000_0000_0000_0000,
3179 0xffff_ffff_0000_0001,
3180 ]);
3181 let mu = m.compute_mu_for_barrett();
3182
3183 let base = U256::from_u64(3);
3185 let exp = U256::from_u64(5);
3186 let barrett = base.modpow_barrett(&exp, &m, &mu);
3187 let standard = base.modpow(&exp, &m);
3188 assert_eq!(barrett, standard, "3^5 mod P256");
3189
3190 let base = U256::from_u64(2);
3192 let exp = U256::from_u64(10);
3193 let barrett = base.modpow_barrett(&exp, &m, &mu);
3194 let standard = base.modpow(&exp, &m);
3195 assert_eq!(barrett, standard, "2^10 mod P256");
3196
3197 let base = U256::from_u64(123);
3199 let exp = U256::from_u64(456);
3200 let barrett = base.modpow_barrett(&exp, &m, &mu);
3201 let standard = base.modpow(&exp, &m);
3202 assert_eq!(barrett, standard, "123^456 mod P256");
3203
3204 let base = m;
3206 let exp = U256::from_u64(5);
3207 let barrett = base.modpow_barrett(&exp, &m, &mu);
3208 let standard = base.modpow(&exp, &m);
3209 assert_eq!(barrett, U256::ZERO, "m^5 mod m should be 0");
3210 assert_eq!(barrett, standard);
3211
3212 let base = U256::from_u64(123);
3214 let exp = U256::from_u64(0);
3215 let barrett = base.modpow_barrett(&exp, &m, &mu);
3216 let standard = base.modpow(&exp, &m);
3217 assert_eq!(barrett, standard, "123^0 mod P256");
3218 assert_eq!(barrett, U256::ONE, "123^0 mod P256 should be 1");
3219 }
3220
3221 #[test]
3222 fn barrett_reduction_comprehensive() {
3223 type U256 = Uint<256, 4>;
3224 let m = U256::from_limbs([
3225 0xffff_ffff_ffff_ffff,
3226 0x0000_0000_ffff_ffff,
3227 0x0000_0000_0000_0000,
3228 0xffff_ffff_0000_0001,
3229 ]);
3230 let mu = m.compute_mu_for_barrett();
3231
3232 for i in 0..100 {
3234 let a = U256::from_limbs([
3235 (i * 1234567 + 1) as u64,
3236 (i * 7654321 + 2) as u64,
3237 (i * 1357924 + 3) as u64,
3238 (i * 2468013 + 4) as u64,
3239 ]);
3240 let b = U256::from_limbs([
3241 (i * 9876543 + 5) as u64,
3242 (i * 3456789 + 6) as u64,
3243 (i * 567899 + 7) as u64,
3244 (i * 1122334 + 8) as u64,
3245 ]);
3246 let expected = a.mul_mod(&b, &m);
3247 let barrett = a.mul_mod_barrett(&b, &m, &mu);
3248 assert_eq!(barrett, expected, "mul_mod_barrett vs mul_mod iteration {i}");
3249 }
3250
3251 let (am1, _) = m.sub_word(1);
3253 let barrett = am1.mul_mod_barrett(&am1, &m, &mu);
3254 let expected = am1.mul_mod(&am1, &m);
3255 assert_eq!(barrett, expected, "(m-1)^2 mod m");
3256 }
3257
3258 #[test]
3259 fn barrett_modpow_step_trace() {
3260 type U256 = Uint<256, 4>;
3261 let m = U256::from_limbs([
3262 0xffff_ffff_ffff_ffff,
3263 0x0000_0000_ffff_ffff,
3264 0x0000_0000_0000_0000,
3265 0xffff_ffff_0000_0001,
3266 ]);
3267 let mu = m.compute_mu_for_barrett();
3268
3269 let a = U256::from_u64(123);
3271
3272 let base1 = a.mul_mod_barrett(&U256::ONE, &m, &mu);
3274 assert_eq!(base1, U256::from_u64(123), "step1: self*1 mod m");
3275
3276 let a2 = base1.mul_mod_barrett(&base1, &m, &mu);
3280 let a2_expected = a.mul_mod(&a, &m);
3281 assert_eq!(a2, a2_expected, "123*123 mod m");
3282
3283 let a4 = a2.mul_mod_barrett(&a2, &m, &mu);
3285 let a4_expected = a2.mul_mod(&a2, &m);
3286 assert_eq!(a4, a4_expected, "123^2*123^2 mod m");
3287
3288 let a8 = a4.mul_mod_barrett(&a4, &m, &mu);
3290 let result_bit2 = a4.mul_mod_barrett(&U256::ONE, &m, &mu);
3291 assert_eq!(result_bit2, a4, "result after bit 2");
3292 let a8_expected = a4.mul_mod(&a4, &m);
3293 assert_eq!(a8, a8_expected, "123^4*123^4 mod m");
3294
3295 let final_barrett = a.modpow_barrett(&U256::from_u64(4), &m, &mu);
3297 let final_expected = a.modpow(&U256::from_u64(4), &m);
3298 assert_eq!(final_barrett, final_expected, "123^4 mod m via modpow_barrett");
3299 }
3300}