1mod add;
4mod add_mod;
5mod bit_and;
6mod bit_not;
7mod bit_or;
8mod bit_xor;
9mod bits;
10mod cmp;
11mod ct;
12pub(crate) mod div;
13pub(crate) mod encoding;
14mod from;
15mod gcd;
16mod invert_mod;
17mod lcm;
18mod mul;
19mod mul_mod;
20mod neg;
21mod neg_mod;
22mod pow;
23mod pow_mod;
24mod shl;
25mod shr;
26mod sqrt;
27mod sub;
28mod sub_mod;
29
30#[cfg(feature = "rand_core")]
31mod rand;
32
33use crate::{
34 Choice, CtAssign, CtEq, CtOption, Integer, Limb, NonZero, Odd, One, Resize, UintRef, Unsigned,
35 UnsignedWithMontyForm, Word, Zero, bitlen, modular::BoxedMontyForm, traits::sealed::Sealed,
36};
37use alloc::{boxed::Box, vec, vec::Vec};
38use core::{
39 borrow::{Borrow, BorrowMut},
40 fmt,
41 iter::repeat,
42};
43
44#[cfg(feature = "zeroize")]
45use zeroize::Zeroize;
46
47#[derive(Clone)]
56pub struct BoxedUint {
57 pub(crate) limbs: Box<[Limb]>,
61}
62
63impl BoxedUint {
64 #[must_use]
66 pub fn zero() -> Self {
67 Self {
68 limbs: vec![Limb::ZERO; 1].into(),
69 }
70 }
71
72 #[must_use]
76 pub fn zero_with_precision(at_least_bits_precision: u32) -> Self {
77 vec![Limb::ZERO; bitlen::to_limbs(at_least_bits_precision)].into()
78 }
79
80 #[must_use]
82 pub fn one() -> Self {
83 Self {
84 limbs: vec![Limb::ONE; 1].into(),
85 }
86 }
87
88 #[must_use]
92 pub fn one_with_precision(at_least_bits_precision: u32) -> Self {
93 let mut ret = Self::zero_with_precision(at_least_bits_precision);
94 ret.limbs[0] = Limb::ONE;
95 ret
96 }
97
98 #[must_use]
100 pub fn is_zero(&self) -> Choice {
101 self.limbs
102 .iter()
103 .fold(Choice::TRUE, |acc, limb| acc & limb.is_zero())
104 }
105
106 #[inline]
108 #[must_use]
109 pub fn is_nonzero(&self) -> Choice {
110 !self.is_zero()
111 }
112
113 #[must_use]
115 pub fn is_one(&self) -> Choice {
116 let mut iter = self.limbs.iter();
117 let choice = iter.next().copied().unwrap_or(Limb::ZERO).ct_eq(&Limb::ONE);
118 iter.fold(choice, |acc, limb| acc & limb.is_zero())
119 }
120
121 #[must_use]
126 pub fn max(at_least_bits_precision: u32) -> Self {
127 vec![Limb::MAX; bitlen::to_limbs(at_least_bits_precision)].into()
128 }
129
130 #[inline]
133 pub fn from_words(words: impl IntoIterator<Item = Word>) -> Self {
134 Self {
135 limbs: words.into_iter().map(Into::into).collect(),
136 }
137 }
138
139 #[inline]
143 pub fn from_words_with_precision(
144 words: impl IntoIterator<Item = Word>,
145 at_least_bits_precision: u32,
146 ) -> Self {
147 let size = bitlen::to_limbs(at_least_bits_precision);
148 Self {
149 limbs: words
150 .into_iter()
151 .map(Into::into)
152 .chain(repeat(Limb::ZERO))
153 .take(size)
154 .collect(),
155 }
156 }
157
158 #[inline]
161 pub fn to_words(&self) -> Box<[Word]> {
162 self.limbs.iter().copied().map(Into::into).collect()
163 }
164
165 #[must_use]
167 pub fn as_words(&self) -> &[Word] {
168 self.as_uint_ref().as_words()
169 }
170
171 pub fn as_mut_words(&mut self) -> &mut [Word] {
173 self.as_mut_uint_ref().as_mut_words()
174 }
175
176 #[deprecated(since = "0.7.0", note = "please use `as_mut_words` instead")]
178 pub fn as_words_mut(&mut self) -> &mut [Word] {
179 self.as_mut_words()
180 }
181
182 #[must_use]
184 pub fn as_limbs(&self) -> &[Limb] {
185 self.limbs.as_ref()
186 }
187
188 pub fn as_mut_limbs(&mut self) -> &mut [Limb] {
190 self.limbs.as_mut()
191 }
192
193 #[deprecated(since = "0.7.0", note = "please use `as_mut_limbs` instead")]
195 pub fn as_limbs_mut(&mut self) -> &mut [Limb] {
196 self.as_mut_limbs()
197 }
198
199 #[must_use]
201 pub fn to_limbs(&self) -> Box<[Limb]> {
202 self.limbs.clone()
203 }
204
205 #[must_use]
207 pub fn into_limbs(self) -> Box<[Limb]> {
208 self.limbs
209 }
210
211 #[inline]
213 #[must_use]
214 pub const fn as_uint_ref(&self) -> &UintRef {
215 UintRef::new(&self.limbs)
216 }
217
218 #[inline]
220 #[must_use]
221 pub const fn as_mut_uint_ref(&mut self) -> &mut UintRef {
222 UintRef::new_mut(&mut self.limbs)
223 }
224
225 #[must_use]
227 pub fn nlimbs(&self) -> usize {
228 self.limbs.len()
229 }
230
231 #[must_use]
233 pub fn as_nz_vartime(&self) -> Option<&NonZero<Self>> {
234 if self.is_zero_vartime() {
235 None
236 } else {
237 Some(NonZero::new_ref_unchecked(self))
238 }
239 }
240
241 #[must_use]
245 pub fn to_nz(&self) -> CtOption<NonZero<Self>> {
246 self.clone().into_nz()
247 }
248
249 #[inline(always)]
254 #[must_use]
255 pub(crate) fn to_nz_or_one(&self) -> (NonZero<Self>, Choice) {
256 let is_zero = self.is_zero();
257 let mut nz = self.clone();
258 nz.as_mut_uint_ref().conditional_set_one(is_zero);
259 (NonZero::new_unchecked(nz), !is_zero)
260 }
261
262 #[inline(always)]
267 #[must_use]
268 pub(crate) fn to_odd_or_one(&self) -> (Odd<Self>, Choice) {
269 let is_odd = self.is_odd();
270 let mut odd = self.clone();
271 odd.as_mut_uint_ref().conditional_set_one(is_odd.not());
272 (Odd::new_unchecked(odd), is_odd)
273 }
274
275 #[must_use]
277 pub fn as_odd_vartime(&self) -> Option<&Odd<Self>> {
278 if !self.is_odd().to_bool_vartime() {
279 None
280 } else {
281 Some(Odd::new_ref_unchecked(self))
282 }
283 }
284
285 #[must_use]
289 pub fn to_odd(&self) -> CtOption<Odd<Self>> {
290 self.clone().into_odd()
291 }
292
293 #[must_use]
297 pub fn into_nz(mut self) -> CtOption<NonZero<Self>> {
298 let is_nz = self.is_nonzero();
299
300 self.limbs[0].ct_assign(&Limb::ONE, !is_nz);
302 CtOption::new(NonZero::new_unchecked(self), is_nz)
303 }
304
305 #[must_use]
309 pub fn into_odd(mut self) -> CtOption<Odd<Self>> {
310 let is_odd = self.is_odd();
311
312 self.limbs[0].ct_assign(&Limb::ONE, !is_odd);
314 CtOption::new(Odd::new_unchecked(self.clone()), is_odd)
315 }
316
317 #[must_use]
322 #[deprecated(since = "0.7.0", note = "please use `resize` instead")]
323 pub fn widen(&self, at_least_bits_precision: u32) -> BoxedUint {
324 assert!(at_least_bits_precision >= self.bits_precision());
325
326 let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
327 ret.limbs[..self.nlimbs()].copy_from_slice(&self.limbs);
328 ret
329 }
330
331 #[must_use]
336 #[deprecated(since = "0.7.0", note = "please use `resize` instead")]
337 pub fn shorten(&self, at_least_bits_precision: u32) -> BoxedUint {
338 assert!(at_least_bits_precision <= self.bits_precision());
339 let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
340 let nlimbs = ret.nlimbs();
341 ret.limbs.copy_from_slice(&self.limbs[..nlimbs]);
342 ret
343 }
344
345 #[inline]
348 fn map_limbs<F>(lhs: &Self, rhs: &Self, f: F) -> Self
349 where
350 F: Fn(Limb, Limb) -> Limb,
351 {
352 let nlimbs = cmp::max(lhs.nlimbs(), rhs.nlimbs());
353 let mut limbs = Vec::with_capacity(nlimbs);
354
355 for i in 0..nlimbs {
356 let &a = lhs.limbs.get(i).unwrap_or(&Limb::ZERO);
357 let &b = rhs.limbs.get(i).unwrap_or(&Limb::ZERO);
358 limbs.push(f(a, b));
359 }
360
361 limbs.into()
362 }
363
364 pub(crate) fn resize_in_place_unchecked(&mut self, at_least_bits_precision: u32) {
370 let new_len = bitlen::to_limbs(at_least_bits_precision);
371
372 if new_len != self.limbs.len() {
373 let mut limbs = core::mem::take(&mut self.limbs).into_vec();
374 limbs.resize(new_len, Limb::ZERO);
375 *self = Self::from(limbs);
376 }
377 }
378
379 pub(crate) fn is_within_bits(&self, bits: u32) -> bool {
381 bits >= self.bits_precision() || bits >= self.bits()
382 }
383}
384
385impl Resize for BoxedUint {
386 type Output = BoxedUint;
387
388 fn resize_unchecked(mut self, at_least_bits_precision: u32) -> Self::Output {
389 self.resize_in_place_unchecked(at_least_bits_precision);
390 self
391 }
392
393 fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
394 if self.is_within_bits(at_least_bits_precision) {
395 Some(self.resize_unchecked(at_least_bits_precision))
396 } else {
397 None
398 }
399 }
400}
401
402impl Resize for &BoxedUint {
403 type Output = BoxedUint;
404
405 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
406 let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
407 let num_limbs_to_copy = core::cmp::min(ret.limbs.len(), self.limbs.len());
408 ret.limbs[..num_limbs_to_copy].copy_from_slice(&self.limbs[..num_limbs_to_copy]);
409 ret
410 }
411
412 fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
413 if self.is_within_bits(at_least_bits_precision) {
414 Some(self.resize_unchecked(at_least_bits_precision))
415 } else {
416 None
417 }
418 }
419}
420
421impl Resize for NonZero<BoxedUint> {
422 type Output = Self;
423
424 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
425 NonZero::new_unchecked(self.get().resize_unchecked(at_least_bits_precision))
426 }
427
428 fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
429 self.get()
430 .try_resize(at_least_bits_precision)
431 .map(NonZero::new_unchecked)
432 }
433}
434
435impl Resize for &NonZero<BoxedUint> {
436 type Output = NonZero<BoxedUint>;
437
438 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
439 NonZero::new_unchecked(self.as_ref().resize_unchecked(at_least_bits_precision))
440 }
441
442 fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
443 self.as_ref()
444 .try_resize(at_least_bits_precision)
445 .map(NonZero::new_unchecked)
446 }
447}
448
449impl AsRef<[Word]> for BoxedUint {
450 fn as_ref(&self) -> &[Word] {
451 self.as_words()
452 }
453}
454
455impl AsMut<[Word]> for BoxedUint {
456 fn as_mut(&mut self) -> &mut [Word] {
457 self.as_mut_words()
458 }
459}
460
461impl AsRef<[Limb]> for BoxedUint {
462 fn as_ref(&self) -> &[Limb] {
463 self.as_limbs()
464 }
465}
466
467impl AsMut<[Limb]> for BoxedUint {
468 fn as_mut(&mut self) -> &mut [Limb] {
469 self.as_mut_limbs()
470 }
471}
472
473impl AsRef<UintRef> for BoxedUint {
474 fn as_ref(&self) -> &UintRef {
475 self.as_uint_ref()
476 }
477}
478
479impl AsMut<UintRef> for BoxedUint {
480 fn as_mut(&mut self) -> &mut UintRef {
481 self.as_mut_uint_ref()
482 }
483}
484
485impl Borrow<UintRef> for BoxedUint {
486 fn borrow(&self) -> &UintRef {
487 self.as_uint_ref()
488 }
489}
490
491impl BorrowMut<UintRef> for BoxedUint {
492 fn borrow_mut(&mut self) -> &mut UintRef {
493 self.as_mut_uint_ref()
494 }
495}
496
497impl Default for BoxedUint {
498 fn default() -> Self {
499 Self::zero()
500 }
501}
502
503impl Integer for BoxedUint {
504 fn as_limbs(&self) -> &[Limb] {
505 &self.limbs
506 }
507
508 fn as_mut_limbs(&mut self) -> &mut [Limb] {
509 &mut self.limbs
510 }
511
512 fn nlimbs(&self) -> usize {
513 self.nlimbs()
514 }
515}
516
517impl Sealed for BoxedUint {}
518
519impl Unsigned for BoxedUint {
520 fn as_uint_ref(&self) -> &UintRef {
521 self.as_uint_ref()
522 }
523
524 fn as_mut_uint_ref(&mut self) -> &mut UintRef {
525 self.as_mut_uint_ref()
526 }
527
528 fn from_limb_like(limb: Limb, other: &Self) -> Self {
529 let mut ret = Self::zero_with_precision(other.bits_precision());
530 ret.limbs[0] = limb;
531 ret
532 }
533}
534
535impl UnsignedWithMontyForm for BoxedUint {
536 type MontyForm = BoxedMontyForm;
537}
538
539impl Zero for BoxedUint {
540 fn zero() -> Self {
541 Self::zero()
542 }
543
544 fn is_zero(&self) -> Choice {
545 self.is_zero()
546 }
547
548 fn set_zero(&mut self) {
549 self.limbs.as_mut().fill(Limb::ZERO);
550 }
551}
552
553impl One for BoxedUint {
554 fn one() -> Self {
555 Self::one()
556 }
557
558 fn one_like(other: &Self) -> Self {
559 let mut ret = other.clone();
560 ret.set_one();
561 ret
562 }
563
564 fn is_one(&self) -> Choice {
565 self.is_one()
566 }
567
568 fn set_one(&mut self) {
569 self.limbs.as_mut().fill(Limb::ZERO);
570 self.limbs[0] = Limb::ONE;
571 }
572}
573
574impl num_traits::Zero for BoxedUint {
575 fn zero() -> Self {
576 Self::zero()
577 }
578
579 fn is_zero(&self) -> bool {
580 self.is_zero().into()
581 }
582
583 fn set_zero(&mut self) {
584 Zero::set_zero(self);
585 }
586}
587
588impl num_traits::One for BoxedUint {
589 fn one() -> Self {
590 Self::one()
591 }
592
593 fn is_one(&self) -> bool {
594 self.is_one().into()
595 }
596
597 fn set_one(&mut self) {
598 One::set_one(self);
599 }
600}
601
602#[cfg(feature = "zeroize")]
603impl Zeroize for BoxedUint {
604 fn zeroize(&mut self) {
605 self.limbs.zeroize();
606 }
607}
608
609impl fmt::Debug for BoxedUint {
610 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
611 write!(f, "BoxedUint(0x{:X})", self.as_uint_ref())
612 }
613}
614
615impl fmt::Display for BoxedUint {
616 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
617 fmt::UpperHex::fmt(self, f)
618 }
619}
620
621impl fmt::Binary for BoxedUint {
622 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
623 fmt::Binary::fmt(self.as_uint_ref(), f)
624 }
625}
626
627impl fmt::LowerHex for BoxedUint {
628 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
629 fmt::LowerHex::fmt(self.as_uint_ref(), f)
630 }
631}
632
633impl fmt::UpperHex for BoxedUint {
634 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635 fmt::UpperHex::fmt(self.as_uint_ref(), f)
636 }
637}
638
639#[cfg(test)]
640mod tests {
641 use super::BoxedUint;
642 use crate::Word;
643 use alloc::vec::Vec;
644
645 #[test]
646 fn from_word_vec() {
647 let words: &[Word] = &[0, 1, 2, 3];
648 let uint = BoxedUint::from(Vec::from(words));
649 assert_eq!(uint.nlimbs(), 4);
650 assert_eq!(uint.as_words(), words);
651 }
652
653 #[test]
654 fn fmt_lower_hex() {
655 let n = BoxedUint::from_be_hex("AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD", 128).unwrap();
656 assert_eq!(format!("{n:x}"), "aaaaaaaabbbbbbbbccccccccdddddddd");
657 assert_eq!(format!("{n:#x}"), "0xaaaaaaaabbbbbbbbccccccccdddddddd");
658 }
659
660 #[test]
661 fn fmt_upper_hex() {
662 let n = BoxedUint::from_be_hex("aaaaaaaabbbbbbbbccccccccdddddddd", 128).unwrap();
663 assert_eq!(format!("{n:X}"), "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD");
664 assert_eq!(format!("{n:#X}"), "0xAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD");
665 }
666
667 #[test]
668 fn fmt_binary() {
669 let n = BoxedUint::from_be_hex("aaaaaaaabbbbbbbbccccccccdddddddd", 128).unwrap();
670 assert_eq!(
671 format!("{n:b}"),
672 "10101010101010101010101010101010101110111011101110111011101110111100110011001100110011001100110011011101110111011101110111011101"
673 );
674 assert_eq!(
675 format!("{n:#b}"),
676 "0b10101010101010101010101010101010101110111011101110111011101110111100110011001100110011001100110011011101110111011101110111011101"
677 );
678 }
679
680 #[test]
681 fn test_unsigned() {
682 crate::traits::tests::test_unsigned(
683 BoxedUint::zero_with_precision(128),
684 BoxedUint::max(128),
685 );
686 }
687
688 #[test]
689 fn test_unsigned_monty_form() {
690 crate::traits::tests::test_unsigned_monty_form::<BoxedUint>();
691 }
692}