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