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