1use crate::{
2 bits::{BitIteratorBE, BitIteratorLE},
3 const_for, UniformRand,
4};
5use ark_ff_macros::unroll_for_loops;
6use ark_serialize::{
7 CanonicalDeserialize, CanonicalSerialize, Compress, SerializationError, Valid, Validate,
8};
9use ark_std::{
10 borrow::Borrow,
11 fmt::{Debug, Display, UpperHex},
13 io::{Read, Write},
14 ops::{
15 BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, ShlAssign, Shr,
16 ShrAssign,
17 },
18 rand::{
19 distributions::{Distribution, Standard},
20 Rng,
21 },
22 str::FromStr,
23 vec::Vec,
24 Zero,
25};
26use num_bigint::BigUint;
27use zeroize::Zeroize;
28
29#[macro_use]
30pub mod arithmetic;
31
32#[derive(Copy, Clone, PartialEq, Eq, Hash)]
33#[must_use]
34pub struct BigInt<const N: usize>(pub [u64; N]);
35
36impl<const N: usize> Zeroize for BigInt<N> {
37 #[inline]
38 fn zeroize(&mut self) {
39 self.0.zeroize();
40 }
41}
42
43impl<const N: usize> Default for BigInt<N> {
44 #[inline]
45 fn default() -> Self {
46 Self([0u64; N])
47 }
48}
49
50impl<const N: usize> CanonicalSerialize for BigInt<N> {
51 #[inline]
52 fn serialize_with_mode<W: Write>(
53 &self,
54 writer: W,
55 compress: Compress,
56 ) -> Result<(), SerializationError> {
57 self.0.serialize_with_mode(writer, compress)
58 }
59
60 #[inline]
61 fn serialized_size(&self, compress: Compress) -> usize {
62 self.0.serialized_size(compress)
63 }
64}
65
66impl<const N: usize> Valid for BigInt<N> {
67 const TRIVIAL_CHECK: bool = true;
68
69 #[inline]
70 fn check(&self) -> Result<(), SerializationError> {
71 self.0.check()
72 }
73}
74
75impl<const N: usize> CanonicalDeserialize for BigInt<N> {
76 #[inline]
77 fn deserialize_with_mode<R: Read>(
78 reader: R,
79 compress: Compress,
80 validate: Validate,
81 ) -> Result<Self, SerializationError> {
82 Ok(BigInt(<[u64; N]>::deserialize_with_mode(
83 reader, compress, validate,
84 )?))
85 }
86}
87
88#[macro_export]
107macro_rules! BigInt {
108 ($c0:expr) => {{
109 let (is_positive, limbs) = $crate::ark_ff_macros::to_sign_and_limbs!($c0);
110 assert!(is_positive);
111 let mut integer = $crate::BigInt::zero();
112 assert!(integer.0.len() >= limbs.len());
113 $crate::const_for!((i in 0..(limbs.len())) {
114 integer.0[i] = limbs[i];
115 });
116 integer
117 }};
118}
119
120#[doc(hidden)]
121macro_rules! const_modulo {
122 ($a:expr, $divisor:expr) => {{
123 assert!(!$divisor.const_is_zero());
126 let mut remainder = Self::new([0u64; N]);
127 let mut i = ($a.num_bits() - 1) as isize;
128 let mut carry;
129 while i >= 0 {
130 (remainder, carry) = remainder.const_mul2_with_carry();
131 remainder.0[0] |= $a.get_bit(i as usize) as u64;
132 if remainder.const_geq($divisor) || carry {
133 let (r, borrow) = remainder.const_sub_with_borrow($divisor);
134 remainder = r;
135 assert!(borrow == carry);
136 }
137 i -= 1;
138 }
139 remainder
140 }};
141}
142
143impl<const N: usize> BigInt<N> {
144 #[inline]
145 pub const fn new(value: [u64; N]) -> Self {
146 Self(value)
147 }
148
149 #[inline]
150 pub const fn zero() -> Self {
151 Self([0u64; N])
152 }
153
154 #[inline]
155 pub const fn one() -> Self {
156 let mut one = Self::zero();
157 one.0[0] = 1;
158 one
159 }
160
161 #[doc(hidden)]
162 #[inline]
163 pub const fn const_is_even(&self) -> bool {
164 self.0[0] % 2 == 0
165 }
166
167 #[doc(hidden)]
168 #[inline]
169 pub const fn const_is_odd(&self) -> bool {
170 self.0[0] % 2 == 1
171 }
172
173 #[doc(hidden)]
174 #[inline]
175 pub const fn mod_4(&self) -> u8 {
176 (((self.0[0] << 62) >> 62) % 4) as u8
179 }
180
181 #[doc(hidden)]
182 pub const fn mod_8(&self) -> u8 {
183 (((self.0[0] << 61) >> 61) % 8) as u8
186 }
187
188 #[doc(hidden)]
191 #[inline]
192 pub const fn const_shr(&self) -> Self {
193 let mut result = *self;
194 let mut t = 0;
195 crate::const_for!((i in 0..N) {
196 let a = result.0[N - i - 1];
197 let t2 = a << 63;
198 result.0[N - i - 1] >>= 1;
199 result.0[N - i - 1] |= t;
200 t = t2;
201 });
202 result
203 }
204
205 #[inline]
206 const fn const_geq(&self, other: &Self) -> bool {
207 const_for!((i in 0..N) {
208 let a = self.0[N - i - 1];
209 let b = other.0[N - i - 1];
210 if a < b {
211 return false;
212 } else if a > b {
213 return true;
214 }
215 });
216 true
217 }
218
219 #[doc(hidden)]
221 #[inline]
222 pub const fn two_adic_valuation(mut self) -> u32 {
223 assert!(self.const_is_odd());
224 let mut two_adicity = 0;
225 self.0[0] -= 1;
228 while self.const_is_even() {
229 self = self.const_shr();
230 two_adicity += 1;
231 }
232 two_adicity
233 }
234
235 #[doc(hidden)]
238 #[inline]
239 pub const fn two_adic_coefficient(mut self) -> Self {
240 assert!(self.const_is_odd());
241 self.0[0] -= 1;
244 while self.const_is_even() {
245 self = self.const_shr();
246 }
247 assert!(self.const_is_odd());
248 self
249 }
250
251 #[doc(hidden)]
255 #[inline]
256 pub const fn divide_by_2_round_down(mut self) -> Self {
257 if self.const_is_odd() {
258 self.0[0] -= 1;
259 }
260 self.const_shr()
261 }
262
263 #[doc(hidden)]
265 #[inline]
266 pub const fn const_num_bits(self) -> u32 {
267 ((N - 1) * 64) as u32 + (64 - self.0[N - 1].leading_zeros())
268 }
269
270 #[inline]
271 pub(crate) const fn const_sub_with_borrow(mut self, other: &Self) -> (Self, bool) {
272 let mut borrow = 0;
273
274 const_for!((i in 0..N) {
275 borrow = arithmetic::sbb(&mut self.0[i], other.0[i], borrow);
276 });
277
278 (self, borrow != 0)
279 }
280
281 #[inline]
282 pub(crate) const fn const_add_with_carry(mut self, other: &Self) -> (Self, bool) {
283 let mut carry = 0;
284
285 crate::const_for!((i in 0..N) {
286 carry = arithmetic::adc(&mut self.0[i], other.0[i], carry);
287 });
288
289 (self, carry != 0)
290 }
291
292 #[inline]
293 const fn const_mul2_with_carry(mut self) -> (Self, bool) {
294 let mut last = 0;
295 crate::const_for!((i in 0..N) {
296 let a = self.0[i];
297 let tmp = a >> 63;
298 self.0[i] <<= 1;
299 self.0[i] |= last;
300 last = tmp;
301 });
302 (self, last != 0)
303 }
304
305 #[inline]
306 pub(crate) const fn const_is_zero(&self) -> bool {
307 let mut is_zero = true;
308 crate::const_for!((i in 0..N) {
309 is_zero &= self.0[i] == 0;
310 });
311 is_zero
312 }
313
314 #[doc(hidden)]
316 #[inline]
317 pub const fn montgomery_r(&self) -> Self {
318 let two_pow_n_times_64 = crate::const_helpers::RBuffer([0u64; N], 1);
319 const_modulo!(two_pow_n_times_64, self)
320 }
321
322 #[doc(hidden)]
324 #[inline]
325 pub const fn montgomery_r2(&self) -> Self {
326 let two_pow_n_times_64_square = crate::const_helpers::R2Buffer([0u64; N], [0u64; N], 1);
327 const_modulo!(two_pow_n_times_64_square, self)
328 }
329}
330
331impl<const N: usize> BigInteger for BigInt<N> {
332 const NUM_LIMBS: usize = N;
333
334 #[unroll_for_loops(6)]
335 #[inline]
336 fn add_with_carry(&mut self, other: &Self) -> bool {
337 let mut carry = 0;
338
339 for i in 0..N {
340 carry = arithmetic::adc_for_add_with_carry(&mut self.0[i], other.0[i], carry);
341 }
342
343 carry != 0
344 }
345
346 #[unroll_for_loops(6)]
347 #[inline]
348 fn sub_with_borrow(&mut self, other: &Self) -> bool {
349 let mut borrow = 0;
350
351 for i in 0..N {
352 borrow = arithmetic::sbb_for_sub_with_borrow(&mut self.0[i], other.0[i], borrow);
353 }
354
355 borrow != 0
356 }
357
358 #[inline]
359 fn mul2(&mut self) -> bool {
360 #[cfg(target_arch = "x86_64")]
361 #[allow(unused_unsafe, unsafe_code)]
362 {
363 let mut carry = 0;
364
365 for i in 0..N {
366 unsafe {
367 use core::arch::x86_64::_addcarry_u64;
368 carry = _addcarry_u64(carry, self.0[i], self.0[i], &mut self.0[i])
369 };
370 }
371
372 carry != 0
373 }
374
375 #[cfg(not(target_arch = "x86_64"))]
376 {
377 let mut last = 0;
378 for i in 0..N {
379 let a = &mut self.0[i];
380 let tmp = *a >> 63;
381 *a <<= 1;
382 *a |= last;
383 last = tmp;
384 }
385 last != 0
386 }
387 }
388
389 #[inline]
390 fn muln(&mut self, mut n: u32) {
391 if n >= (64 * N) as u32 {
392 *self = Self::from(0u64);
393 return;
394 }
395
396 while n >= 64 {
397 let mut t = 0;
398 for i in 0..N {
399 core::mem::swap(&mut t, &mut self.0[i]);
400 }
401 n -= 64;
402 }
403
404 if n > 0 {
405 let mut t = 0;
406 for i in 0..N {
407 let a = &mut self.0[i];
408 let t2 = *a >> (64 - n);
409 *a <<= n;
410 *a |= t;
411 t = t2;
412 }
413 }
414 }
415
416 #[inline]
417 fn mul(&self, other: &Self) -> (Self, Self) {
418 if self.is_zero() || other.is_zero() {
419 let zero = Self::zero();
420 return (zero, zero);
421 }
422
423 let mut r = crate::const_helpers::MulBuffer::zeroed();
424
425 let mut carry = 0;
426
427 for i in 0..N {
428 for j in 0..N {
429 r[i + j] = arithmetic::mac_with_carry(r[i + j], self.0[i], other.0[j], &mut carry);
430 }
431 r.b1[i] = carry;
432 carry = 0;
433 }
434
435 (Self(r.b0), Self(r.b1))
436 }
437
438 #[inline]
439 fn mul_low(&self, other: &Self) -> Self {
440 if self.is_zero() || other.is_zero() {
441 return Self::zero();
442 }
443
444 let mut res = Self::zero();
445 let mut carry = 0;
446
447 for i in 0..N {
448 for j in 0..(N - i) {
449 res.0[i + j] =
450 arithmetic::mac_with_carry(res.0[i + j], self.0[i], other.0[j], &mut carry);
451 }
452 carry = 0;
453 }
454
455 res
456 }
457
458 #[inline]
459 fn mul_high(&self, other: &Self) -> Self {
460 self.mul(other).1
461 }
462
463 #[inline]
464 fn div2(&mut self) {
465 let mut t = 0;
466 for a in self.0.iter_mut().rev() {
467 let t2 = *a << 63;
468 *a >>= 1;
469 *a |= t;
470 t = t2;
471 }
472 }
473
474 #[inline]
475 fn divn(&mut self, mut n: u32) {
476 if n >= (64 * N) as u32 {
477 *self = Self::from(0u64);
478 return;
479 }
480
481 while n >= 64 {
482 let mut t = 0;
483 for i in 0..N {
484 core::mem::swap(&mut t, &mut self.0[N - i - 1]);
485 }
486 n -= 64;
487 }
488
489 if n > 0 {
490 let mut t = 0;
491 for i in 0..N {
492 let a = &mut self.0[N - i - 1];
493 let t2 = *a << (64 - n);
494 *a >>= n;
495 *a |= t;
496 t = t2;
497 }
498 }
499 }
500
501 #[inline]
502 fn is_odd(&self) -> bool {
503 self.0[0] & 1 == 1
504 }
505
506 #[inline]
507 fn is_even(&self) -> bool {
508 !self.is_odd()
509 }
510
511 #[inline]
512 fn is_zero(&self) -> bool {
513 self.0.iter().all(Zero::is_zero)
514 }
515
516 #[inline]
517 fn num_bits(&self) -> u32 {
518 let mut ret = N as u32 * 64;
519 for i in self.0.iter().rev() {
520 let leading = i.leading_zeros();
521 ret -= leading;
522 if leading != 64 {
523 break;
524 }
525 }
526
527 ret
528 }
529
530 #[inline]
531 fn get_bit(&self, i: usize) -> bool {
532 if i >= 64 * N {
533 false
534 } else {
535 let limb = i / 64;
536 let bit = i - (64 * limb);
537 (self.0[limb] & (1 << bit)) != 0
538 }
539 }
540
541 #[inline]
542 fn from_bits_be(bits: &[bool]) -> Self {
543 let mut bits = bits.to_vec();
544 bits.reverse();
545 Self::from_bits_le(&bits)
546 }
547
548 #[inline]
549 fn from_bits_le(bits: &[bool]) -> Self {
550 let mut res = Self::zero();
551 for (bits64, res_i) in bits.chunks(64).zip(&mut res.0) {
552 for (i, bit) in bits64.iter().enumerate() {
553 *res_i |= (*bit as u64) << i;
554 }
555 }
556 res
557 }
558
559 #[inline]
560 fn to_bytes_be(&self) -> Vec<u8> {
561 let mut le_bytes = self.to_bytes_le();
562 le_bytes.reverse();
563 le_bytes
564 }
565
566 #[inline]
567 fn to_bytes_le(&self) -> Vec<u8> {
568 self.0.iter().flat_map(|&limb| limb.to_le_bytes()).collect()
569 }
570}
571
572impl<const N: usize> UpperHex for BigInt<N> {
573 #[inline]
574 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
575 write!(f, "{:016X}", BigUint::from(*self))
576 }
577}
578
579impl<const N: usize> Debug for BigInt<N> {
580 #[inline]
581 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
582 write!(f, "{:?}", BigUint::from(*self))
583 }
584}
585
586impl<const N: usize> Display for BigInt<N> {
587 #[inline]
588 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
589 write!(f, "{}", BigUint::from(*self))
590 }
591}
592
593impl<const N: usize> Ord for BigInt<N> {
594 #[inline]
595 #[cfg_attr(target_arch = "x86_64", unroll_for_loops(12))]
596 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
597 use core::cmp::Ordering;
598 #[cfg(target_arch = "x86_64")]
599 for i in 0..N {
600 let a = &self.0[N - i - 1];
601 let b = &other.0[N - i - 1];
602 match a.cmp(b) {
603 Ordering::Equal => {},
604 order => return order,
605 };
606 }
607 #[cfg(not(target_arch = "x86_64"))]
608 for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
609 if let order @ (Ordering::Less | Ordering::Greater) = a.cmp(b) {
610 return order;
611 }
612 }
613 Ordering::Equal
614 }
615}
616
617impl<const N: usize> PartialOrd for BigInt<N> {
618 #[inline]
619 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
620 Some(self.cmp(other))
621 }
622}
623
624impl<const N: usize> Distribution<BigInt<N>> for Standard {
625 #[inline]
626 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> BigInt<N> {
627 BigInt([(); N].map(|_| rng.gen()))
628 }
629}
630
631impl<const N: usize> AsMut<[u64]> for BigInt<N> {
632 #[inline]
633 fn as_mut(&mut self) -> &mut [u64] {
634 &mut self.0
635 }
636}
637
638impl<const N: usize> AsRef<[u64]> for BigInt<N> {
639 #[inline]
640 fn as_ref(&self) -> &[u64] {
641 &self.0
642 }
643}
644
645impl<const N: usize> From<u64> for BigInt<N> {
646 #[inline]
647 fn from(val: u64) -> BigInt<N> {
648 let mut repr = Self::default();
649 repr.0[0] = val;
650 repr
651 }
652}
653
654impl<const N: usize> From<u32> for BigInt<N> {
655 #[inline]
656 fn from(val: u32) -> BigInt<N> {
657 let mut repr = Self::default();
658 repr.0[0] = val.into();
659 repr
660 }
661}
662
663impl<const N: usize> From<u16> for BigInt<N> {
664 #[inline]
665 fn from(val: u16) -> BigInt<N> {
666 let mut repr = Self::default();
667 repr.0[0] = val.into();
668 repr
669 }
670}
671
672impl<const N: usize> From<u8> for BigInt<N> {
673 #[inline]
674 fn from(val: u8) -> BigInt<N> {
675 let mut repr = Self::default();
676 repr.0[0] = val.into();
677 repr
678 }
679}
680
681impl<const N: usize> TryFrom<BigUint> for BigInt<N> {
682 type Error = ();
683
684 #[inline]
686 fn try_from(val: num_bigint::BigUint) -> Result<BigInt<N>, Self::Error> {
687 let bytes = val.to_bytes_le();
688
689 if bytes.len() > N * 8 {
690 Err(())
691 } else {
692 let mut limbs = [0u64; N];
693
694 bytes.chunks(8).enumerate().for_each(|(i, chunk)| {
695 let mut chunk_padded = [0u8; 8];
696 chunk_padded[..chunk.len()].copy_from_slice(chunk);
697 limbs[i] = u64::from_le_bytes(chunk_padded)
698 });
699
700 Ok(Self(limbs))
701 }
702 }
703}
704
705impl<const N: usize> FromStr for BigInt<N> {
706 type Err = ();
707
708 fn from_str(s: &str) -> Result<Self, Self::Err> {
709 let biguint = BigUint::from_str(s).map_err(|_| ())?;
710 Self::try_from(biguint)
711 }
712}
713
714impl<const N: usize> From<BigInt<N>> for BigUint {
715 #[inline]
716 fn from(val: BigInt<N>) -> num_bigint::BigUint {
717 BigUint::from_bytes_le(&val.to_bytes_le())
718 }
719}
720
721impl<const N: usize> From<BigInt<N>> for num_bigint::BigInt {
722 #[inline]
723 fn from(val: BigInt<N>) -> num_bigint::BigInt {
724 use num_bigint::Sign;
725 let sign = if val.is_zero() {
726 Sign::NoSign
727 } else {
728 Sign::Plus
729 };
730 num_bigint::BigInt::from_bytes_le(sign, &val.to_bytes_le())
731 }
732}
733
734impl<B: Borrow<Self>, const N: usize> BitXorAssign<B> for BigInt<N> {
735 #[inline]
736 fn bitxor_assign(&mut self, rhs: B) {
737 (0..N).for_each(|i| self.0[i] ^= rhs.borrow().0[i])
738 }
739}
740
741impl<B: Borrow<Self>, const N: usize> BitXor<B> for BigInt<N> {
742 type Output = Self;
743
744 #[inline]
745 fn bitxor(mut self, rhs: B) -> Self::Output {
746 self ^= rhs;
747 self
748 }
749}
750
751impl<B: Borrow<Self>, const N: usize> BitAndAssign<B> for BigInt<N> {
752 #[inline]
753 fn bitand_assign(&mut self, rhs: B) {
754 (0..N).for_each(|i| self.0[i] &= rhs.borrow().0[i])
755 }
756}
757
758impl<B: Borrow<Self>, const N: usize> BitAnd<B> for BigInt<N> {
759 type Output = Self;
760
761 #[inline]
762 fn bitand(mut self, rhs: B) -> Self::Output {
763 self &= rhs;
764 self
765 }
766}
767
768impl<B: Borrow<Self>, const N: usize> BitOrAssign<B> for BigInt<N> {
769 #[inline]
770 fn bitor_assign(&mut self, rhs: B) {
771 (0..N).for_each(|i| self.0[i] |= rhs.borrow().0[i])
772 }
773}
774
775impl<B: Borrow<Self>, const N: usize> BitOr<B> for BigInt<N> {
776 type Output = Self;
777
778 #[inline]
779 fn bitor(mut self, rhs: B) -> Self::Output {
780 self |= rhs;
781 self
782 }
783}
784
785impl<const N: usize> ShrAssign<u32> for BigInt<N> {
786 #[inline]
793 fn shr_assign(&mut self, mut rhs: u32) {
794 if rhs >= (64 * N) as u32 {
795 *self = Self::from(0u64);
796 return;
797 }
798
799 while rhs >= 64 {
800 let mut t = 0;
801 for limb in self.0.iter_mut().rev() {
802 core::mem::swap(&mut t, limb);
803 }
804 rhs -= 64;
805 }
806
807 if rhs > 0 {
808 let mut t = 0;
809 for a in self.0.iter_mut().rev() {
810 let t2 = *a << (64 - rhs);
811 *a >>= rhs;
812 *a |= t;
813 t = t2;
814 }
815 }
816 }
817}
818
819impl<const N: usize> Shr<u32> for BigInt<N> {
820 type Output = Self;
821
822 #[inline]
829 fn shr(mut self, rhs: u32) -> Self::Output {
830 self >>= rhs;
831 self
832 }
833}
834
835impl<const N: usize> ShlAssign<u32> for BigInt<N> {
836 #[inline]
843 fn shl_assign(&mut self, mut rhs: u32) {
844 if rhs >= (64 * N) as u32 {
845 *self = Self::from(0u64);
846 return;
847 }
848
849 while rhs >= 64 {
850 let mut t = 0;
851 for i in 0..N {
852 core::mem::swap(&mut t, &mut self.0[i]);
853 }
854 rhs -= 64;
855 }
856
857 if rhs > 0 {
858 let mut t = 0;
859 for i in 0..N {
860 let a = &mut self.0[i];
861 let t2 = *a >> (64 - rhs);
862 *a <<= rhs;
863 *a |= t;
864 t = t2;
865 }
866 }
867 }
868}
869
870impl<const N: usize> Shl<u32> for BigInt<N> {
871 type Output = Self;
872
873 #[inline]
880 fn shl(mut self, rhs: u32) -> Self::Output {
881 self <<= rhs;
882 self
883 }
884}
885
886impl<const N: usize> Not for BigInt<N> {
887 type Output = Self;
888
889 #[inline]
890 fn not(self) -> Self::Output {
891 let mut result = Self::zero();
892 for i in 0..N {
893 result.0[i] = !self.0[i];
894 }
895 result
896 }
897}
898
899#[inline]
908pub const fn signed_mod_reduction(n: u64, modulus: u64) -> i64 {
909 let t = (n % modulus) as i64;
910 if t as u64 >= (modulus / 2) {
911 t - (modulus as i64)
912 } else {
913 t
914 }
915}
916
917pub type BigInteger64 = BigInt<1>;
918pub type BigInteger128 = BigInt<2>;
919pub type BigInteger256 = BigInt<4>;
920pub type BigInteger320 = BigInt<5>;
921pub type BigInteger384 = BigInt<6>;
922pub type BigInteger448 = BigInt<7>;
923pub type BigInteger768 = BigInt<12>;
924pub type BigInteger832 = BigInt<13>;
925
926#[cfg(test)]
927mod tests;
928
929pub trait BigInteger:
933 CanonicalSerialize
934 + CanonicalDeserialize
935 + Copy
936 + Clone
937 + Debug
938 + Default
939 + Display
940 + Eq
941 + Ord
942 + Send
943 + Sized
944 + Sync
945 + 'static
946 + UniformRand
947 + Zeroize
948 + AsMut<[u64]>
949 + AsRef<[u64]>
950 + From<u64>
951 + From<u32>
952 + From<u16>
953 + From<u8>
954 + TryFrom<BigUint, Error = ()>
955 + FromStr
956 + Into<BigUint>
957 + BitXorAssign<Self>
958 + for<'a> BitXorAssign<&'a Self>
959 + BitXor<Self, Output = Self>
960 + for<'a> BitXor<&'a Self, Output = Self>
961 + BitAndAssign<Self>
962 + for<'a> BitAndAssign<&'a Self>
963 + BitAnd<Self, Output = Self>
964 + for<'a> BitAnd<&'a Self, Output = Self>
965 + BitOrAssign<Self>
966 + for<'a> BitOrAssign<&'a Self>
967 + BitOr<Self, Output = Self>
968 + for<'a> BitOr<&'a Self, Output = Self>
969 + Shr<u32, Output = Self>
970 + ShrAssign<u32>
971 + Shl<u32, Output = Self>
972 + ShlAssign<u32>
973{
974 const NUM_LIMBS: usize;
976
977 fn add_with_carry(&mut self, other: &Self) -> bool;
998
999 fn sub_with_borrow(&mut self, other: &Self) -> bool;
1019
1020 fn mul2(&mut self) -> bool;
1044
1045 #[deprecated(since = "0.4.2", note = "please use the operator `<<` instead")]
1069 fn muln(&mut self, amt: u32);
1070
1071 fn mul_low(&self, other: &Self) -> Self;
1089
1090 fn mul_high(&self, other: &Self) -> Self;
1108
1109 fn mul(&self, other: &Self) -> (Self, Self);
1132
1133 fn div2(&mut self);
1155
1156 #[deprecated(since = "0.4.2", note = "please use the operator `>>` instead")]
1175 fn divn(&mut self, amt: u32);
1176
1177 fn is_odd(&self) -> bool;
1187
1188 fn is_even(&self) -> bool;
1198
1199 fn is_zero(&self) -> bool;
1209
1210 fn num_bits(&self) -> u32;
1225
1226 fn get_bit(&self, i: usize) -> bool;
1237
1238 fn from_bits_be(bits: &[bool]) -> Self;
1251
1252 fn from_bits_le(bits: &[bool]) -> Self;
1265
1266 #[inline]
1280 fn to_bits_be(&self) -> Vec<bool> {
1281 BitIteratorBE::new(self).collect()
1282 }
1283
1284 #[inline]
1298 fn to_bits_le(&self) -> Vec<bool> {
1299 BitIteratorLE::new(self).collect()
1300 }
1301
1302 fn to_bytes_be(&self) -> Vec<u8>;
1316
1317 fn to_bytes_le(&self) -> Vec<u8>;
1331
1332 #[inline]
1334 fn find_wnaf(&self, w: usize) -> Option<Vec<i64>> {
1335 if (2..64).contains(&w) {
1338 let mut res = Vec::new();
1339 let mut e = *self;
1340
1341 while !e.is_zero() {
1342 let z: i64;
1343 if e.is_odd() {
1344 z = signed_mod_reduction(e.as_ref()[0], 1 << w);
1345 if z >= 0 {
1346 e.sub_with_borrow(&Self::from(z as u64));
1347 } else {
1348 e.add_with_carry(&Self::from((-z) as u64));
1349 }
1350 } else {
1351 z = 0;
1352 }
1353 res.push(z);
1354 e.div2();
1355 }
1356
1357 Some(res)
1358 } else {
1359 None
1360 }
1361 }
1362}