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 mul;
18mod mul_mod;
19mod neg;
20mod neg_mod;
21mod pow;
22mod pow_mod;
23mod shl;
24mod shr;
25mod sqrt;
26mod sub;
27mod sub_mod;
28
29#[cfg(feature = "rand_core")]
30mod rand;
31
32use crate::{
33 Choice, CtAssign, CtEq, CtOption, Integer, Limb, NonZero, Odd, One, Resize, UintRef, Unsigned,
34 UnsignedWithMontyForm, Word, Zero, modular::BoxedMontyForm, traits::sealed::Sealed,
35};
36use alloc::{boxed::Box, vec, vec::Vec};
37use core::{
38 borrow::{Borrow, BorrowMut},
39 fmt,
40 iter::repeat,
41};
42
43#[cfg(feature = "zeroize")]
44use zeroize::Zeroize;
45
46#[derive(Clone)]
55pub struct BoxedUint {
56 pub(crate) limbs: Box<[Limb]>,
60}
61
62impl BoxedUint {
63 fn limbs_for_precision(at_least_bits_precision: u32) -> usize {
64 at_least_bits_precision.div_ceil(Limb::BITS) as usize
65 }
66
67 #[must_use]
69 pub fn zero() -> Self {
70 Self {
71 limbs: vec![Limb::ZERO; 1].into(),
72 }
73 }
74
75 #[must_use]
79 pub fn zero_with_precision(at_least_bits_precision: u32) -> Self {
80 vec![Limb::ZERO; Self::limbs_for_precision(at_least_bits_precision)].into()
81 }
82
83 #[must_use]
85 pub fn one() -> Self {
86 Self {
87 limbs: vec![Limb::ONE; 1].into(),
88 }
89 }
90
91 #[must_use]
95 pub fn one_with_precision(at_least_bits_precision: u32) -> Self {
96 let mut ret = Self::zero_with_precision(at_least_bits_precision);
97 ret.limbs[0] = Limb::ONE;
98 ret
99 }
100
101 #[must_use]
103 pub fn is_zero(&self) -> Choice {
104 self.limbs
105 .iter()
106 .fold(Choice::TRUE, |acc, limb| acc & limb.is_zero())
107 }
108
109 #[inline]
111 #[must_use]
112 pub fn is_nonzero(&self) -> Choice {
113 !self.is_zero()
114 }
115
116 #[must_use]
118 pub fn is_one(&self) -> Choice {
119 let mut iter = self.limbs.iter();
120 let choice = iter.next().copied().unwrap_or(Limb::ZERO).ct_eq(&Limb::ONE);
121 iter.fold(choice, |acc, limb| acc & limb.is_zero())
122 }
123
124 #[must_use]
129 pub fn max(at_least_bits_precision: u32) -> Self {
130 vec![Limb::MAX; Self::limbs_for_precision(at_least_bits_precision)].into()
131 }
132
133 #[inline]
136 pub fn from_words(words: impl IntoIterator<Item = Word>) -> Self {
137 Self {
138 limbs: words.into_iter().map(Into::into).collect(),
139 }
140 }
141
142 #[inline]
146 pub fn from_words_with_precision(
147 words: impl IntoIterator<Item = Word>,
148 at_least_bits_precision: u32,
149 ) -> Self {
150 let size = Self::limbs_for_precision(at_least_bits_precision);
151 Self {
152 limbs: words
153 .into_iter()
154 .map(Into::into)
155 .chain(repeat(Limb::ZERO))
156 .take(size)
157 .collect(),
158 }
159 }
160
161 #[inline]
164 pub fn to_words(&self) -> Box<[Word]> {
165 self.limbs.iter().copied().map(Into::into).collect()
166 }
167
168 #[must_use]
170 pub fn as_words(&self) -> &[Word] {
171 self.as_uint_ref().as_words()
172 }
173
174 pub fn as_mut_words(&mut self) -> &mut [Word] {
176 self.as_mut_uint_ref().as_mut_words()
177 }
178
179 #[deprecated(since = "0.7.0", note = "please use `as_mut_words` instead")]
181 pub fn as_words_mut(&mut self) -> &mut [Word] {
182 self.as_mut_words()
183 }
184
185 #[must_use]
187 pub fn as_limbs(&self) -> &[Limb] {
188 self.limbs.as_ref()
189 }
190
191 pub fn as_mut_limbs(&mut self) -> &mut [Limb] {
193 self.limbs.as_mut()
194 }
195
196 #[deprecated(since = "0.7.0", note = "please use `as_mut_limbs` instead")]
198 pub fn as_limbs_mut(&mut self) -> &mut [Limb] {
199 self.as_mut_limbs()
200 }
201
202 #[must_use]
204 pub fn to_limbs(&self) -> Box<[Limb]> {
205 self.limbs.clone()
206 }
207
208 #[must_use]
210 pub fn into_limbs(self) -> Box<[Limb]> {
211 self.limbs
212 }
213
214 #[inline]
216 #[must_use]
217 pub const fn as_uint_ref(&self) -> &UintRef {
218 UintRef::new(&self.limbs)
219 }
220
221 #[inline]
223 #[must_use]
224 pub const fn as_mut_uint_ref(&mut self) -> &mut UintRef {
225 UintRef::new_mut(&mut self.limbs)
226 }
227
228 #[must_use]
230 pub fn nlimbs(&self) -> usize {
231 self.limbs.len()
232 }
233
234 #[must_use]
238 pub fn to_nz(&self) -> CtOption<NonZero<Self>> {
239 self.clone().into_nz()
240 }
241
242 #[must_use]
246 pub fn to_odd(&self) -> CtOption<Odd<Self>> {
247 self.clone().into_odd()
248 }
249
250 #[must_use]
254 pub fn into_nz(mut self) -> CtOption<NonZero<Self>> {
255 let is_nz = self.is_nonzero();
256
257 self.limbs[0].ct_assign(&Limb::ONE, !is_nz);
259 CtOption::new(NonZero(self), is_nz)
260 }
261
262 #[must_use]
266 pub fn into_odd(mut self) -> CtOption<Odd<Self>> {
267 let is_odd = self.is_odd();
268
269 self.limbs[0].ct_assign(&Limb::ONE, !is_odd);
271 CtOption::new(Odd(self.clone()), is_odd)
272 }
273
274 #[must_use]
279 #[deprecated(since = "0.7.0", note = "please use `resize` instead")]
280 pub fn widen(&self, at_least_bits_precision: u32) -> BoxedUint {
281 assert!(at_least_bits_precision >= self.bits_precision());
282
283 let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
284 ret.limbs[..self.nlimbs()].copy_from_slice(&self.limbs);
285 ret
286 }
287
288 #[must_use]
293 #[deprecated(since = "0.7.0", note = "please use `resize` instead")]
294 pub fn shorten(&self, at_least_bits_precision: u32) -> BoxedUint {
295 assert!(at_least_bits_precision <= self.bits_precision());
296 let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
297 let nlimbs = ret.nlimbs();
298 ret.limbs.copy_from_slice(&self.limbs[..nlimbs]);
299 ret
300 }
301
302 #[inline]
305 fn map_limbs<F>(lhs: &Self, rhs: &Self, f: F) -> Self
306 where
307 F: Fn(Limb, Limb) -> Limb,
308 {
309 let nlimbs = cmp::max(lhs.nlimbs(), rhs.nlimbs());
310 let mut limbs = Vec::with_capacity(nlimbs);
311
312 for i in 0..nlimbs {
313 let &a = lhs.limbs.get(i).unwrap_or(&Limb::ZERO);
314 let &b = rhs.limbs.get(i).unwrap_or(&Limb::ZERO);
315 limbs.push(f(a, b));
316 }
317
318 limbs.into()
319 }
320
321 pub(crate) fn is_within_bits(&self, bits: u32) -> bool {
323 bits >= self.bits_precision() || bits >= self.bits()
324 }
325}
326
327impl Resize for BoxedUint {
328 type Output = BoxedUint;
329
330 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
331 let new_len = Self::limbs_for_precision(at_least_bits_precision);
332 if new_len == self.limbs.len() {
333 self
334 } else {
335 let mut limbs = self.limbs.into_vec();
336 limbs.resize(new_len, Limb::ZERO);
337 Self::from(limbs)
338 }
339 }
340
341 fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
342 if self.is_within_bits(at_least_bits_precision) {
343 Some(self.resize_unchecked(at_least_bits_precision))
344 } else {
345 None
346 }
347 }
348}
349
350impl Resize for &BoxedUint {
351 type Output = BoxedUint;
352
353 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
354 let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
355 let num_limbs_to_copy = core::cmp::min(ret.limbs.len(), self.limbs.len());
356 ret.limbs[..num_limbs_to_copy].copy_from_slice(&self.limbs[..num_limbs_to_copy]);
357 ret
358 }
359
360 fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
361 if self.is_within_bits(at_least_bits_precision) {
362 Some(self.resize_unchecked(at_least_bits_precision))
363 } else {
364 None
365 }
366 }
367}
368
369impl Resize for NonZero<BoxedUint> {
370 type Output = Self;
371
372 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
373 NonZero(self.0.resize_unchecked(at_least_bits_precision))
374 }
375
376 fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
377 self.0.try_resize(at_least_bits_precision).map(NonZero)
378 }
379}
380
381impl Resize for &NonZero<BoxedUint> {
382 type Output = NonZero<BoxedUint>;
383
384 fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
385 NonZero((&self.0).resize_unchecked(at_least_bits_precision))
386 }
387
388 fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
389 (&self.0).try_resize(at_least_bits_precision).map(NonZero)
390 }
391}
392
393impl AsRef<[Word]> for BoxedUint {
394 fn as_ref(&self) -> &[Word] {
395 self.as_words()
396 }
397}
398
399impl AsMut<[Word]> for BoxedUint {
400 fn as_mut(&mut self) -> &mut [Word] {
401 self.as_mut_words()
402 }
403}
404
405impl AsRef<[Limb]> for BoxedUint {
406 fn as_ref(&self) -> &[Limb] {
407 self.as_limbs()
408 }
409}
410
411impl AsMut<[Limb]> for BoxedUint {
412 fn as_mut(&mut self) -> &mut [Limb] {
413 self.as_mut_limbs()
414 }
415}
416
417impl AsRef<UintRef> for BoxedUint {
418 fn as_ref(&self) -> &UintRef {
419 self.as_uint_ref()
420 }
421}
422
423impl AsMut<UintRef> for BoxedUint {
424 fn as_mut(&mut self) -> &mut UintRef {
425 self.as_mut_uint_ref()
426 }
427}
428
429impl Borrow<UintRef> for BoxedUint {
430 fn borrow(&self) -> &UintRef {
431 self.as_uint_ref()
432 }
433}
434
435impl BorrowMut<UintRef> for BoxedUint {
436 fn borrow_mut(&mut self) -> &mut UintRef {
437 self.as_mut_uint_ref()
438 }
439}
440
441impl Default for BoxedUint {
442 fn default() -> Self {
443 Self::zero()
444 }
445}
446
447impl Integer for BoxedUint {
448 fn as_limbs(&self) -> &[Limb] {
449 &self.limbs
450 }
451
452 fn as_mut_limbs(&mut self) -> &mut [Limb] {
453 &mut self.limbs
454 }
455
456 fn nlimbs(&self) -> usize {
457 self.nlimbs()
458 }
459}
460
461impl Sealed for BoxedUint {}
462
463impl Unsigned for BoxedUint {
464 fn as_uint_ref(&self) -> &UintRef {
465 self.as_uint_ref()
466 }
467
468 fn as_mut_uint_ref(&mut self) -> &mut UintRef {
469 self.as_mut_uint_ref()
470 }
471
472 fn from_limb_like(limb: Limb, other: &Self) -> Self {
473 let mut ret = Self::zero_with_precision(other.bits_precision());
474 ret.limbs[0] = limb;
475 ret
476 }
477}
478
479impl UnsignedWithMontyForm for BoxedUint {
480 type MontyForm = BoxedMontyForm;
481}
482
483impl Zero for BoxedUint {
484 fn zero() -> Self {
485 Self::zero()
486 }
487
488 fn is_zero(&self) -> Choice {
489 self.is_zero()
490 }
491
492 fn set_zero(&mut self) {
493 self.limbs.as_mut().fill(Limb::ZERO);
494 }
495}
496
497impl One for BoxedUint {
498 fn one() -> Self {
499 Self::one()
500 }
501
502 fn one_like(other: &Self) -> Self {
503 let mut ret = other.clone();
504 ret.set_one();
505 ret
506 }
507
508 fn is_one(&self) -> Choice {
509 self.is_one()
510 }
511
512 fn set_one(&mut self) {
513 self.limbs.as_mut().fill(Limb::ZERO);
514 self.limbs[0] = Limb::ONE;
515 }
516}
517
518impl num_traits::Zero for BoxedUint {
519 fn zero() -> Self {
520 Self::zero()
521 }
522
523 fn is_zero(&self) -> bool {
524 self.is_zero().into()
525 }
526
527 fn set_zero(&mut self) {
528 Zero::set_zero(self);
529 }
530}
531
532impl num_traits::One for BoxedUint {
533 fn one() -> Self {
534 Self::one()
535 }
536
537 fn is_one(&self) -> bool {
538 self.is_one().into()
539 }
540
541 fn set_one(&mut self) {
542 One::set_one(self);
543 }
544}
545
546#[cfg(feature = "zeroize")]
547impl Zeroize for BoxedUint {
548 fn zeroize(&mut self) {
549 self.limbs.zeroize();
550 }
551}
552
553impl fmt::Debug for BoxedUint {
554 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
555 write!(f, "BoxedUint(0x{:X})", self.as_uint_ref())
556 }
557}
558
559impl fmt::Display for BoxedUint {
560 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561 fmt::UpperHex::fmt(self, f)
562 }
563}
564
565impl fmt::Binary for BoxedUint {
566 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
567 fmt::Binary::fmt(self.as_uint_ref(), f)
568 }
569}
570
571impl fmt::LowerHex for BoxedUint {
572 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
573 fmt::LowerHex::fmt(self.as_uint_ref(), f)
574 }
575}
576
577impl fmt::UpperHex for BoxedUint {
578 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579 fmt::UpperHex::fmt(self.as_uint_ref(), f)
580 }
581}
582
583#[cfg(test)]
584mod tests {
585 use super::BoxedUint;
586 use crate::Word;
587 use alloc::vec::Vec;
588
589 #[test]
590 fn from_word_vec() {
591 let words: &[Word] = &[0, 1, 2, 3];
592 let uint = BoxedUint::from(Vec::from(words));
593 assert_eq!(uint.nlimbs(), 4);
594 assert_eq!(uint.as_words(), words);
595 }
596
597 #[test]
598 fn fmt_lower_hex() {
599 let n = BoxedUint::from_be_hex("AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD", 128).unwrap();
600 assert_eq!(format!("{n:x}"), "aaaaaaaabbbbbbbbccccccccdddddddd");
601 assert_eq!(format!("{n:#x}"), "0xaaaaaaaabbbbbbbbccccccccdddddddd");
602 }
603
604 #[test]
605 fn fmt_upper_hex() {
606 let n = BoxedUint::from_be_hex("aaaaaaaabbbbbbbbccccccccdddddddd", 128).unwrap();
607 assert_eq!(format!("{n:X}"), "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD");
608 assert_eq!(format!("{n:#X}"), "0xAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD");
609 }
610
611 #[test]
612 fn fmt_binary() {
613 let n = BoxedUint::from_be_hex("aaaaaaaabbbbbbbbccccccccdddddddd", 128).unwrap();
614 assert_eq!(
615 format!("{n:b}"),
616 "10101010101010101010101010101010101110111011101110111011101110111100110011001100110011001100110011011101110111011101110111011101"
617 );
618 assert_eq!(
619 format!("{n:#b}"),
620 "0b10101010101010101010101010101010101110111011101110111011101110111100110011001100110011001100110011011101110111011101110111011101"
621 );
622 }
623
624 #[test]
625 fn test_unsigned() {
626 crate::traits::tests::test_unsigned(
627 BoxedUint::zero_with_precision(128),
628 BoxedUint::max(128),
629 );
630 }
631
632 #[test]
633 fn test_unsigned_monty_form() {
634 crate::traits::tests::test_unsigned_monty_form::<BoxedUint>();
635 }
636}