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,
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 Unsigned for BoxedUint {
462 fn as_uint_ref(&self) -> &UintRef {
463 self.as_uint_ref()
464 }
465
466 fn as_mut_uint_ref(&mut self) -> &mut UintRef {
467 self.as_mut_uint_ref()
468 }
469
470 fn from_limb_like(limb: Limb, other: &Self) -> Self {
471 let mut ret = Self::zero_with_precision(other.bits_precision());
472 ret.limbs[0] = limb;
473 ret
474 }
475}
476
477impl UnsignedWithMontyForm for BoxedUint {
478 type MontyForm = BoxedMontyForm;
479}
480
481impl Zero for BoxedUint {
482 fn zero() -> Self {
483 Self::zero()
484 }
485
486 fn is_zero(&self) -> Choice {
487 self.is_zero()
488 }
489
490 fn set_zero(&mut self) {
491 self.limbs.as_mut().fill(Limb::ZERO);
492 }
493}
494
495impl One for BoxedUint {
496 fn one() -> Self {
497 Self::one()
498 }
499
500 fn one_like(other: &Self) -> Self {
501 let mut ret = other.clone();
502 ret.set_one();
503 ret
504 }
505
506 fn is_one(&self) -> Choice {
507 self.is_one()
508 }
509
510 fn set_one(&mut self) {
511 self.limbs.as_mut().fill(Limb::ZERO);
512 self.limbs[0] = Limb::ONE;
513 }
514}
515
516impl num_traits::Zero for BoxedUint {
517 fn zero() -> Self {
518 Self::zero()
519 }
520
521 fn is_zero(&self) -> bool {
522 self.is_zero().into()
523 }
524
525 fn set_zero(&mut self) {
526 Zero::set_zero(self);
527 }
528}
529
530impl num_traits::One for BoxedUint {
531 fn one() -> Self {
532 Self::one()
533 }
534
535 fn is_one(&self) -> bool {
536 self.is_one().into()
537 }
538
539 fn set_one(&mut self) {
540 One::set_one(self);
541 }
542}
543
544#[cfg(feature = "zeroize")]
545impl Zeroize for BoxedUint {
546 fn zeroize(&mut self) {
547 self.limbs.zeroize();
548 }
549}
550
551impl fmt::Debug for BoxedUint {
552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553 write!(f, "BoxedUint(0x{:X})", self.as_uint_ref())
554 }
555}
556
557impl fmt::Display for BoxedUint {
558 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
559 fmt::UpperHex::fmt(self, f)
560 }
561}
562
563impl fmt::Binary for BoxedUint {
564 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
565 fmt::Binary::fmt(self.as_uint_ref(), f)
566 }
567}
568
569impl fmt::LowerHex for BoxedUint {
570 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
571 fmt::LowerHex::fmt(self.as_uint_ref(), f)
572 }
573}
574
575impl fmt::UpperHex for BoxedUint {
576 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
577 fmt::UpperHex::fmt(self.as_uint_ref(), f)
578 }
579}
580
581#[cfg(test)]
582mod tests {
583 use super::BoxedUint;
584 use crate::Word;
585 use alloc::vec::Vec;
586
587 #[test]
588 fn from_word_vec() {
589 let words: &[Word] = &[0, 1, 2, 3];
590 let uint = BoxedUint::from(Vec::from(words));
591 assert_eq!(uint.nlimbs(), 4);
592 assert_eq!(uint.as_words(), words);
593 }
594
595 #[test]
596 fn fmt_lower_hex() {
597 let n = BoxedUint::from_be_hex("AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD", 128).unwrap();
598 assert_eq!(format!("{n:x}"), "aaaaaaaabbbbbbbbccccccccdddddddd");
599 assert_eq!(format!("{n:#x}"), "0xaaaaaaaabbbbbbbbccccccccdddddddd");
600 }
601
602 #[test]
603 fn fmt_upper_hex() {
604 let n = BoxedUint::from_be_hex("aaaaaaaabbbbbbbbccccccccdddddddd", 128).unwrap();
605 assert_eq!(format!("{n:X}"), "AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD");
606 assert_eq!(format!("{n:#X}"), "0xAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD");
607 }
608
609 #[test]
610 fn fmt_binary() {
611 let n = BoxedUint::from_be_hex("aaaaaaaabbbbbbbbccccccccdddddddd", 128).unwrap();
612 assert_eq!(
613 format!("{n:b}"),
614 "10101010101010101010101010101010101110111011101110111011101110111100110011001100110011001100110011011101110111011101110111011101"
615 );
616 assert_eq!(
617 format!("{n:#b}"),
618 "0b10101010101010101010101010101010101110111011101110111011101110111100110011001100110011001100110011011101110111011101110111011101"
619 );
620 }
621
622 #[test]
623 fn test_unsigned() {
624 crate::traits::tests::test_unsigned(
625 BoxedUint::zero_with_precision(128),
626 BoxedUint::max(128),
627 );
628 }
629}