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