1use super::cmp::ct_select;
16use super::{HeaplessBigInt, is_zero, zero};
17use crate::MachineWord;
18use const_num_traits::{
19 BorrowingSub, Bounded, CarryingAdd, CarryingMul, CheckedAdd, CheckedMul, CheckedSub, Ct, Nct,
20 OverflowingAdd, OverflowingMul, OverflowingSub, Personality, PersonalityTag, SaturatingAdd,
21 SaturatingMul, SaturatingSub, WrappingAdd, WrappingMul, WrappingSub,
22};
23use core::marker::PhantomData;
24
25#[inline]
35pub(crate) fn max_at_len<T: MachineWord, const CAP: usize, P: Personality>(
36 len: u16,
37) -> HeaplessBigInt<T, CAP, P> {
38 let mut limbs = [zero::<T>(); CAP];
39 for l in &mut limbs[..len as usize] {
40 *l = <T as Bounded>::max_value();
41 }
42 HeaplessBigInt {
43 limbs,
44 len,
45 _p: PhantomData,
46 }
47}
48
49#[inline]
50fn panic_on_overflow_if_nct<P: Personality>(overflow: bool, msg: &'static str) {
51 match P::TAG {
52 PersonalityTag::Nct => assert!(!overflow, "{}", msg),
53 PersonalityTag::Ct => {}
54 }
55}
56
57macro_rules! forward_arith_receivers {
62 ($imp:ident, $method:ident $($bound:tt)*) => {
63 impl<T: MachineWord $($bound)*, const CAP: usize, P: Personality> core::ops::$imp
64 for HeaplessBigInt<T, CAP, P>
65 {
66 type Output = Self;
67 fn $method(self, other: Self) -> Self {
68 (&self).$method(&other)
69 }
70 }
71 impl<T: MachineWord $($bound)*, const CAP: usize, P: Personality>
72 core::ops::$imp<&HeaplessBigInt<T, CAP, P>> for HeaplessBigInt<T, CAP, P>
73 {
74 type Output = Self;
75 fn $method(self, other: &Self) -> Self {
76 (&self).$method(other)
77 }
78 }
79 impl<T: MachineWord $($bound)*, const CAP: usize, P: Personality>
80 core::ops::$imp<HeaplessBigInt<T, CAP, P>> for &HeaplessBigInt<T, CAP, P>
81 {
82 type Output = HeaplessBigInt<T, CAP, P>;
83 fn $method(self, other: HeaplessBigInt<T, CAP, P>) -> HeaplessBigInt<T, CAP, P> {
84 self.$method(&other)
85 }
86 }
87 };
88}
89
90#[inline]
102pub(crate) fn add_slice<T: MachineWord>(a: &[T], b: &[T], out: &mut [T], n: usize) -> bool {
103 let mut carry = false;
104 for ((&ai, &bi), oi) in a[..n].iter().zip(&b[..n]).zip(&mut out[..n]) {
105 let (sum, c) = <T as CarryingAdd>::carrying_add(ai, bi, carry);
106 *oi = sum;
107 carry = c;
108 }
109 carry
110}
111
112#[inline]
115pub(crate) fn sub_slice<T: MachineWord>(a: &[T], b: &[T], out: &mut [T], n: usize) -> bool {
116 let mut borrow = false;
117 for ((&ai, &bi), oi) in a[..n].iter().zip(&b[..n]).zip(&mut out[..n]) {
118 let (diff, br) = <T as BorrowingSub>::borrowing_sub(ai, bi, borrow);
119 *oi = diff;
120 borrow = br;
121 }
122 borrow
123}
124
125#[inline]
135pub(crate) fn mul_slice<T: MachineWord + CarryingMul<Unsigned = T, Output = T>>(
136 a: &[T],
137 a_n: usize,
138 b: &[T],
139 b_n: usize,
140 out: &mut [T],
141 out_n: usize,
142) {
143 let a = &a[..a_n];
147 let b = &b[..b_n];
148 let out = &mut out[..out_n];
149 let mut i = 0;
150 while i < a_n {
151 let mut carry = zero::<T>();
152 let mut j = 0;
153 while j < b_n {
154 let pos = i + j;
155 if pos < out_n {
156 let (lo, hi) = <T as CarryingMul>::carrying_mul(a[i], b[j], carry);
157 let (sum, c1) = <T as CarryingAdd>::carrying_add(out[pos], lo, false);
158 out[pos] = sum;
159 let (new_carry, _) = <T as CarryingAdd>::carrying_add(hi, zero::<T>(), c1);
160 carry = new_carry;
161 }
162 j += 1;
163 }
164 let tail = i + b_n;
165 if tail < out_n {
166 let (sum, _) = <T as CarryingAdd>::carrying_add(out[tail], carry, false);
167 out[tail] = sum;
168 }
169 i += 1;
170 }
171}
172
173impl<T: MachineWord, const CAP: usize, P: Personality> HeaplessBigInt<T, CAP, P> {
176 pub fn wrapping_add(&self, other: &Self) -> Self {
179 let out_len = core::cmp::max(self.len as usize, other.len as usize);
180 let mut out = Self::new_zero_with_len(out_len as u16);
181 let _carry = add_slice(&self.limbs, &other.limbs, &mut out.limbs, out_len);
182 debug_assert!(zero_tail_ok(&out.limbs, out_len));
183 out
184 }
185
186 pub fn overflowing_add(&self, other: &Self) -> (Self, bool) {
192 let out_len = core::cmp::max(self.len as usize, other.len as usize);
193 let mut out = Self::new_zero_with_len(out_len as u16);
194 let carry = add_slice(&self.limbs, &other.limbs, &mut out.limbs, out_len);
195 (out, carry)
196 }
197
198 pub fn checked_add(&self, other: &Self) -> Option<Self> {
200 let (res, overflow) = self.overflowing_add(other);
201 if overflow { None } else { Some(res) }
202 }
203
204 pub fn wrapping_sub(&self, other: &Self) -> Self {
208 let out_len = core::cmp::max(self.len as usize, other.len as usize);
209 let mut out = Self::new_zero_with_len(out_len as u16);
210 let _borrow = sub_slice(&self.limbs, &other.limbs, &mut out.limbs, out_len);
211 debug_assert!(zero_tail_ok(&out.limbs, out_len));
212 out
213 }
214
215 pub fn overflowing_sub(&self, other: &Self) -> (Self, bool) {
219 let out_len = core::cmp::max(self.len as usize, other.len as usize);
220 let mut out = Self::new_zero_with_len(out_len as u16);
221 let borrow = sub_slice(&self.limbs, &other.limbs, &mut out.limbs, out_len);
222 (out, borrow)
223 }
224
225 pub fn checked_sub(&self, other: &Self) -> Option<Self> {
227 let (res, borrow) = self.overflowing_sub(other);
228 if borrow { None } else { Some(res) }
229 }
230}
231
232impl<T: MachineWord + CarryingMul<Unsigned = T, Output = T>, const CAP: usize, P: Personality>
236 HeaplessBigInt<T, CAP, P>
237{
238 pub fn wrapping_mul(&self, other: &Self) -> Self {
243 let out_len = core::cmp::max(self.len as usize, other.len as usize);
244 let mut out = Self::new_zero_with_len(out_len as u16);
245 mul_slice(
246 &self.limbs,
247 self.len as usize,
248 &other.limbs,
249 other.len as usize,
250 &mut out.limbs,
251 out_len,
252 );
253 debug_assert!(zero_tail_ok(&out.limbs, out_len));
254 out
255 }
256
257 pub fn overflowing_mul(&self, other: &Self) -> (Self, bool) {
264 let zero_v = <Self as const_num_traits::Zero>::zero();
265 let (lo, hi) = <Self as CarryingMul>::carrying_mul(*self, *other, zero_v);
266 (lo, !<Self as const_num_traits::Zero>::is_zero(&hi))
267 }
268
269 pub fn checked_mul(&self, other: &Self) -> Option<Self> {
273 let (res, overflow) = self.overflowing_mul(other);
274 if overflow { None } else { Some(res) }
275 }
276}
277
278impl<T, const CAP: usize> CheckedAdd for HeaplessBigInt<T, CAP, Nct>
288where
289 T: MachineWord,
290{
291 type Output = Self;
292 fn checked_add(self, v: Self) -> Option<Self> {
293 Self::checked_add(&self, &v)
294 }
295}
296
297impl<T, const CAP: usize> CheckedMul for HeaplessBigInt<T, CAP, Nct>
298where
299 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
300{
301 type Output = Self;
302 fn checked_mul(self, v: Self) -> Option<Self> {
303 Self::checked_mul(&self, &v)
304 }
305}
306
307impl<T, const CAP: usize> CheckedSub for HeaplessBigInt<T, CAP, Nct>
308where
309 T: MachineWord,
310{
311 type Output = Self;
312 fn checked_sub(self, v: Self) -> Option<Self> {
313 Self::checked_sub(&self, &v)
314 }
315}
316
317impl<T, const CAP: usize> CheckedAdd for &HeaplessBigInt<T, CAP, Nct>
323where
324 T: MachineWord,
325{
326 type Output = HeaplessBigInt<T, CAP, Nct>;
327 fn checked_add(self, v: Self) -> Option<Self::Output> {
328 HeaplessBigInt::<T, CAP, Nct>::checked_add(self, v)
329 }
330}
331
332impl<T, const CAP: usize> CheckedMul for &HeaplessBigInt<T, CAP, Nct>
333where
334 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
335{
336 type Output = HeaplessBigInt<T, CAP, Nct>;
337 fn checked_mul(self, v: Self) -> Option<Self::Output> {
338 HeaplessBigInt::<T, CAP, Nct>::checked_mul(self, v)
339 }
340}
341
342impl<T, const CAP: usize> CheckedSub for &HeaplessBigInt<T, CAP, Nct>
343where
344 T: MachineWord,
345{
346 type Output = HeaplessBigInt<T, CAP, Nct>;
347 fn checked_sub(self, v: Self) -> Option<Self::Output> {
348 HeaplessBigInt::<T, CAP, Nct>::checked_sub(self, v)
349 }
350}
351
352#[cfg(feature = "num-traits")]
359impl<T, const CAP: usize> num_traits::CheckedAdd for HeaplessBigInt<T, CAP, Nct>
360where
361 T: MachineWord,
362{
363 fn checked_add(&self, v: &Self) -> Option<Self> {
364 Self::checked_add(self, v)
365 }
366}
367
368#[cfg(feature = "num-traits")]
369impl<T, const CAP: usize> num_traits::CheckedSub for HeaplessBigInt<T, CAP, Nct>
370where
371 T: MachineWord,
372{
373 fn checked_sub(&self, v: &Self) -> Option<Self> {
374 Self::checked_sub(self, v)
375 }
376}
377
378#[cfg(feature = "num-traits")]
379impl<T, const CAP: usize> num_traits::CheckedMul for HeaplessBigInt<T, CAP, Nct>
380where
381 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
382{
383 fn checked_mul(&self, v: &Self) -> Option<Self> {
384 Self::checked_mul(self, v)
385 }
386}
387
388impl<T, const CAP: usize> SaturatingAdd for HeaplessBigInt<T, CAP, Nct>
396where
397 T: MachineWord,
398{
399 type Output = Self;
400 fn saturating_add(self, v: Self) -> Self {
401 Self::saturating_add(&self, &v)
402 }
403}
404
405impl<T, const CAP: usize> SaturatingSub for HeaplessBigInt<T, CAP, Nct>
406where
407 T: MachineWord,
408{
409 type Output = Self;
410 fn saturating_sub(self, v: Self) -> Self {
411 Self::saturating_sub(&self, &v)
412 }
413}
414
415impl<T, const CAP: usize> SaturatingMul for HeaplessBigInt<T, CAP, Nct>
416where
417 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
418{
419 type Output = Self;
420 fn saturating_mul(self, v: Self) -> Self {
421 Self::saturating_mul(&self, &v)
422 }
423}
424
425impl<T, const CAP: usize> SaturatingAdd for HeaplessBigInt<T, CAP, Ct>
434where
435 T: MachineWord + subtle::ConditionallySelectable,
436{
437 type Output = Self;
438 fn saturating_add(self, v: Self) -> Self {
439 let (res, overflow) = OverflowingAdd::overflowing_add(self, v);
440 ct_select(&res, &max_at_len(res.len), overflow)
441 }
442}
443
444impl<T, const CAP: usize> SaturatingSub for HeaplessBigInt<T, CAP, Ct>
445where
446 T: MachineWord + subtle::ConditionallySelectable,
447{
448 type Output = Self;
449 fn saturating_sub(self, v: Self) -> Self {
450 let (res, borrow) = OverflowingSub::overflowing_sub(self, v);
451 ct_select(&res, &Self::new_zero_with_len(res.len), borrow)
452 }
453}
454
455impl<T, const CAP: usize> SaturatingMul for HeaplessBigInt<T, CAP, Ct>
456where
457 T: MachineWord + CarryingMul<Unsigned = T, Output = T> + subtle::ConditionallySelectable,
458{
459 type Output = Self;
460 fn saturating_mul(self, v: Self) -> Self {
461 let (res, overflow) = OverflowingMul::overflowing_mul(self, v);
462 ct_select(&res, &max_at_len(res.len), overflow)
463 }
464}
465
466impl<T, const CAP: usize> SaturatingAdd for &HeaplessBigInt<T, CAP, Nct>
471where
472 T: MachineWord,
473{
474 type Output = HeaplessBigInt<T, CAP, Nct>;
475 fn saturating_add(self, v: Self) -> Self::Output {
476 <HeaplessBigInt<T, CAP, Nct> as SaturatingAdd>::saturating_add(*self, *v)
477 }
478}
479
480impl<T, const CAP: usize> SaturatingSub for &HeaplessBigInt<T, CAP, Nct>
481where
482 T: MachineWord,
483{
484 type Output = HeaplessBigInt<T, CAP, Nct>;
485 fn saturating_sub(self, v: Self) -> Self::Output {
486 <HeaplessBigInt<T, CAP, Nct> as SaturatingSub>::saturating_sub(*self, *v)
487 }
488}
489
490impl<T, const CAP: usize> SaturatingMul for &HeaplessBigInt<T, CAP, Nct>
491where
492 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
493{
494 type Output = HeaplessBigInt<T, CAP, Nct>;
495 fn saturating_mul(self, v: Self) -> Self::Output {
496 <HeaplessBigInt<T, CAP, Nct> as SaturatingMul>::saturating_mul(*self, *v)
497 }
498}
499
500impl<T, const CAP: usize> SaturatingAdd for &HeaplessBigInt<T, CAP, Ct>
501where
502 T: MachineWord + subtle::ConditionallySelectable,
503{
504 type Output = HeaplessBigInt<T, CAP, Ct>;
505 fn saturating_add(self, v: Self) -> Self::Output {
506 <HeaplessBigInt<T, CAP, Ct> as SaturatingAdd>::saturating_add(*self, *v)
507 }
508}
509
510impl<T, const CAP: usize> SaturatingSub for &HeaplessBigInt<T, CAP, Ct>
511where
512 T: MachineWord + subtle::ConditionallySelectable,
513{
514 type Output = HeaplessBigInt<T, CAP, Ct>;
515 fn saturating_sub(self, v: Self) -> Self::Output {
516 <HeaplessBigInt<T, CAP, Ct> as SaturatingSub>::saturating_sub(*self, *v)
517 }
518}
519
520impl<T, const CAP: usize> SaturatingMul for &HeaplessBigInt<T, CAP, Ct>
521where
522 T: MachineWord + CarryingMul<Unsigned = T, Output = T> + subtle::ConditionallySelectable,
523{
524 type Output = HeaplessBigInt<T, CAP, Ct>;
525 fn saturating_mul(self, v: Self) -> Self::Output {
526 <HeaplessBigInt<T, CAP, Ct> as SaturatingMul>::saturating_mul(*self, *v)
527 }
528}
529
530impl<T, const CAP: usize, P: Personality> const_num_traits::ops::ct::CtCheckedAdd
539 for HeaplessBigInt<T, CAP, P>
540where
541 T: MachineWord,
542{
543 fn ct_checked_add(&self, v: &Self) -> subtle::CtOption<Self> {
544 let (val, overflow) = self.overflowing_add(v);
545 subtle::CtOption::new(val, subtle::Choice::from(!overflow as u8))
546 }
547}
548
549impl<T, const CAP: usize, P: Personality> const_num_traits::ops::ct::CtCheckedSub
550 for HeaplessBigInt<T, CAP, P>
551where
552 T: MachineWord,
553{
554 fn ct_checked_sub(&self, v: &Self) -> subtle::CtOption<Self> {
555 let (val, borrow) = self.overflowing_sub(v);
556 subtle::CtOption::new(val, subtle::Choice::from(!borrow as u8))
557 }
558}
559
560impl<T, const CAP: usize, P: Personality> const_num_traits::ops::ct::CtCheckedMul
561 for HeaplessBigInt<T, CAP, P>
562where
563 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
564{
565 fn ct_checked_mul(&self, v: &Self) -> subtle::CtOption<Self> {
566 let (val, overflow) = self.overflowing_mul(v);
567 subtle::CtOption::new(val, subtle::Choice::from(!overflow as u8))
568 }
569}
570
571#[cfg(feature = "num-traits")]
574impl<T, const CAP: usize> num_traits::Saturating for HeaplessBigInt<T, CAP, Nct>
575where
576 T: MachineWord,
577{
578 fn saturating_add(self, v: Self) -> Self {
579 <Self as SaturatingAdd>::saturating_add(self, v)
580 }
581 fn saturating_sub(self, v: Self) -> Self {
582 <Self as SaturatingSub>::saturating_sub(self, v)
583 }
584}
585
586fn trim_content<T: MachineWord, const CAP: usize, P: Personality>(
591 mut v: HeaplessBigInt<T, CAP, P>,
592) -> HeaplessBigInt<T, CAP, P> {
593 let mut new_len: u16 = 0;
596 let mut i = 0;
597 while i < v.len as usize {
598 if !is_zero(&v.limbs[i]) {
599 new_len = (i + 1) as u16;
600 }
601 i += 1;
602 }
603 v.len = new_len;
604 v
605}
606
607impl<T: MachineWord, const CAP: usize> HeaplessBigInt<T, CAP, Nct> {
612 #[inline]
615 pub fn trim(self) -> Self {
616 trim_content(self)
617 }
618
619 pub fn saturating_add(&self, other: &Self) -> Self {
625 let (res, overflow) = self.overflowing_add(other);
626 if overflow { max_at_len(res.len) } else { res }
627 }
628
629 pub fn saturating_sub(&self, other: &Self) -> Self {
632 let (res, borrow) = self.overflowing_sub(other);
633 if borrow {
634 Self::new_zero_with_len(res.len)
635 } else {
636 res
637 }
638 }
639}
640
641impl<T: MachineWord + CarryingMul<Unsigned = T, Output = T>, const CAP: usize>
642 HeaplessBigInt<T, CAP, Nct>
643{
644 pub fn saturating_mul(&self, other: &Self) -> Self {
648 let (res, overflow) = self.overflowing_mul(other);
649 if overflow { max_at_len(res.len) } else { res }
650 }
651}
652
653impl<T: MachineWord, const CAP: usize, P: Personality> core::ops::Add<&HeaplessBigInt<T, CAP, P>>
660 for &HeaplessBigInt<T, CAP, P>
661{
662 type Output = HeaplessBigInt<T, CAP, P>;
663 fn add(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
664 let (res, overflow) = self.overflowing_add(other);
665 panic_on_overflow_if_nct::<P>(overflow, "HeaplessBigInt::add overflow");
666 res
667 }
668}
669
670impl<T: MachineWord, const CAP: usize, P: Personality> core::ops::Sub<&HeaplessBigInt<T, CAP, P>>
671 for &HeaplessBigInt<T, CAP, P>
672{
673 type Output = HeaplessBigInt<T, CAP, P>;
674 fn sub(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
675 let (res, borrow) = self.overflowing_sub(other);
676 panic_on_overflow_if_nct::<P>(borrow, "HeaplessBigInt::sub underflow");
677 res
678 }
679}
680
681impl<T: MachineWord + CarryingMul<Unsigned = T, Output = T>, const CAP: usize, P: Personality>
682 core::ops::Mul<&HeaplessBigInt<T, CAP, P>> for &HeaplessBigInt<T, CAP, P>
683{
684 type Output = HeaplessBigInt<T, CAP, P>;
685 fn mul(self, other: &HeaplessBigInt<T, CAP, P>) -> Self::Output {
686 let (res, overflow) = self.overflowing_mul(other);
687 panic_on_overflow_if_nct::<P>(overflow, "HeaplessBigInt::mul overflow");
688 res
689 }
690}
691
692forward_arith_receivers!(Add, add);
695forward_arith_receivers!(Sub, sub);
696forward_arith_receivers!(Mul, mul + CarryingMul<Unsigned = T, Output = T>);
697
698impl<T: MachineWord, const CAP: usize, P: Personality> core::ops::AddAssign
701 for HeaplessBigInt<T, CAP, P>
702{
703 fn add_assign(&mut self, other: Self) {
704 self.add_assign(&other);
705 }
706}
707
708impl<T: MachineWord, const CAP: usize, P: Personality>
709 core::ops::AddAssign<&HeaplessBigInt<T, CAP, P>> for HeaplessBigInt<T, CAP, P>
710{
711 fn add_assign(&mut self, other: &Self) {
712 let out_len = core::cmp::max(self.len as usize, other.len as usize);
713 let mut out = Self::new_zero_with_len(out_len as u16);
714 let overflow = add_slice(&self.limbs, &other.limbs, &mut out.limbs, out_len);
715 panic_on_overflow_if_nct::<P>(overflow, "HeaplessBigInt::add overflow");
716 *self = out;
717 }
718}
719
720impl<T: MachineWord, const CAP: usize, P: Personality> core::ops::SubAssign
721 for HeaplessBigInt<T, CAP, P>
722{
723 fn sub_assign(&mut self, other: Self) {
724 self.sub_assign(&other);
725 }
726}
727
728impl<T: MachineWord, const CAP: usize, P: Personality>
729 core::ops::SubAssign<&HeaplessBigInt<T, CAP, P>> for HeaplessBigInt<T, CAP, P>
730{
731 fn sub_assign(&mut self, other: &Self) {
732 let out_len = core::cmp::max(self.len as usize, other.len as usize);
733 let mut out = Self::new_zero_with_len(out_len as u16);
734 let borrow = sub_slice(&self.limbs, &other.limbs, &mut out.limbs, out_len);
735 panic_on_overflow_if_nct::<P>(borrow, "HeaplessBigInt::sub underflow");
736 *self = out;
737 }
738}
739
740impl<T: MachineWord + CarryingMul<Unsigned = T, Output = T>, const CAP: usize, P: Personality>
741 core::ops::MulAssign for HeaplessBigInt<T, CAP, P>
742{
743 fn mul_assign(&mut self, other: Self) {
744 self.mul_assign(&other);
745 }
746}
747
748impl<T: MachineWord + CarryingMul<Unsigned = T, Output = T>, const CAP: usize, P: Personality>
749 core::ops::MulAssign<&HeaplessBigInt<T, CAP, P>> for HeaplessBigInt<T, CAP, P>
750{
751 fn mul_assign(&mut self, other: &Self) {
752 let zero_v = <Self as const_num_traits::Zero>::zero();
755 let (lo, hi) = <Self as CarryingMul>::carrying_mul(*self, *other, zero_v);
756 let overflow = !<Self as const_num_traits::Zero>::is_zero(&hi);
757 panic_on_overflow_if_nct::<P>(overflow, "HeaplessBigInt::mul overflow");
758 *self = lo;
759 }
760}
761
762impl<T: MachineWord, const CAP: usize, P: Personality> WrappingAdd for HeaplessBigInt<T, CAP, P> {
769 type Output = Self;
770 fn wrapping_add(self, v: Self) -> Self::Output {
771 Self::wrapping_add(&self, &v)
772 }
773}
774
775impl<T: MachineWord, const CAP: usize, P: Personality> WrappingSub for HeaplessBigInt<T, CAP, P> {
776 type Output = Self;
777 fn wrapping_sub(self, v: Self) -> Self::Output {
778 Self::wrapping_sub(&self, &v)
779 }
780}
781
782impl<T: MachineWord, const CAP: usize, P: Personality> OverflowingAdd
783 for HeaplessBigInt<T, CAP, P>
784{
785 type Output = Self;
786 fn overflowing_add(self, v: Self) -> (Self::Output, bool) {
787 Self::overflowing_add(&self, &v)
788 }
789}
790
791impl<T: MachineWord, const CAP: usize, P: Personality> OverflowingSub
792 for HeaplessBigInt<T, CAP, P>
793{
794 type Output = Self;
795 fn overflowing_sub(self, v: Self) -> (Self::Output, bool) {
796 Self::overflowing_sub(&self, &v)
797 }
798}
799
800impl<T: MachineWord, const CAP: usize, P: Personality> WrappingAdd for &HeaplessBigInt<T, CAP, P> {
804 type Output = HeaplessBigInt<T, CAP, P>;
805 fn wrapping_add(self, v: Self) -> Self::Output {
806 HeaplessBigInt::wrapping_add(self, v)
807 }
808}
809
810impl<T: MachineWord, const CAP: usize, P: Personality> WrappingSub for &HeaplessBigInt<T, CAP, P> {
811 type Output = HeaplessBigInt<T, CAP, P>;
812 fn wrapping_sub(self, v: Self) -> Self::Output {
813 HeaplessBigInt::wrapping_sub(self, v)
814 }
815}
816
817impl<T: MachineWord, const CAP: usize, P: Personality> OverflowingAdd
818 for &HeaplessBigInt<T, CAP, P>
819{
820 type Output = HeaplessBigInt<T, CAP, P>;
821 fn overflowing_add(self, v: Self) -> (Self::Output, bool) {
822 HeaplessBigInt::overflowing_add(self, v)
823 }
824}
825
826impl<T: MachineWord, const CAP: usize, P: Personality> OverflowingSub
827 for &HeaplessBigInt<T, CAP, P>
828{
829 type Output = HeaplessBigInt<T, CAP, P>;
830 fn overflowing_sub(self, v: Self) -> (Self::Output, bool) {
831 HeaplessBigInt::overflowing_sub(self, v)
832 }
833}
834
835impl<T, const CAP: usize, P: Personality> WrappingMul for HeaplessBigInt<T, CAP, P>
839where
840 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
841{
842 type Output = Self;
843 fn wrapping_mul(self, v: Self) -> Self::Output {
844 Self::wrapping_mul(&self, &v)
845 }
846}
847
848impl<T, const CAP: usize, P: Personality> WrappingMul for &HeaplessBigInt<T, CAP, P>
849where
850 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
851{
852 type Output = HeaplessBigInt<T, CAP, P>;
853 fn wrapping_mul(self, v: Self) -> Self::Output {
854 HeaplessBigInt::wrapping_mul(self, v)
855 }
856}
857
858impl<T, const CAP: usize, P: Personality> OverflowingMul for HeaplessBigInt<T, CAP, P>
861where
862 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
863{
864 type Output = Self;
865 fn overflowing_mul(self, v: Self) -> (Self::Output, bool) {
866 Self::overflowing_mul(&self, &v)
867 }
868}
869
870impl<T, const CAP: usize, P: Personality> OverflowingMul for &HeaplessBigInt<T, CAP, P>
871where
872 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
873{
874 type Output = HeaplessBigInt<T, CAP, P>;
875 fn overflowing_mul(self, v: Self) -> (Self::Output, bool) {
876 HeaplessBigInt::overflowing_mul(self, v)
877 }
878}
879
880impl<T, const CAP: usize, P: Personality> CarryingAdd for HeaplessBigInt<T, CAP, P>
890where
891 T: MachineWord,
892{
893 type Output = Self;
894 fn carrying_add(self, rhs: Self, carry_in: bool) -> (Self::Output, bool) {
895 let out_len = core::cmp::max(self.len as usize, rhs.len as usize);
896 let mut out_limbs = [zero::<T>(); CAP];
897 let mut carry = carry_in;
898 let mut i = 0;
899 while i < out_len {
900 let (sum, c) = <T as CarryingAdd>::carrying_add(self.limbs[i], rhs.limbs[i], carry);
901 out_limbs[i] = sum;
902 carry = c;
903 i += 1;
904 }
905 (
906 HeaplessBigInt {
907 limbs: out_limbs,
908 len: out_len as u16,
909 _p: PhantomData,
910 },
911 carry,
912 )
913 }
914}
915
916impl<T, const CAP: usize, P: Personality> CarryingAdd for &HeaplessBigInt<T, CAP, P>
919where
920 T: MachineWord,
921{
922 type Output = HeaplessBigInt<T, CAP, P>;
923 fn carrying_add(self, rhs: Self, carry_in: bool) -> (Self::Output, bool) {
924 <HeaplessBigInt<T, CAP, P> as CarryingAdd>::carrying_add(*self, *rhs, carry_in)
925 }
926}
927
928impl<T, const CAP: usize, P: Personality> BorrowingSub for HeaplessBigInt<T, CAP, P>
933where
934 T: MachineWord,
935{
936 type Output = Self;
937 fn borrowing_sub(self, rhs: Self, borrow_in: bool) -> (Self::Output, bool) {
938 let out_len = core::cmp::max(self.len as usize, rhs.len as usize);
939 let mut out_limbs = [zero::<T>(); CAP];
940 let mut borrow = borrow_in;
941 let mut i = 0;
942 while i < out_len {
943 let (diff, br) =
944 <T as BorrowingSub>::borrowing_sub(self.limbs[i], rhs.limbs[i], borrow);
945 out_limbs[i] = diff;
946 borrow = br;
947 i += 1;
948 }
949 (
950 HeaplessBigInt {
951 limbs: out_limbs,
952 len: out_len as u16,
953 _p: PhantomData,
954 },
955 borrow,
956 )
957 }
958}
959
960impl<T, const CAP: usize, P: Personality> BorrowingSub for &HeaplessBigInt<T, CAP, P>
963where
964 T: MachineWord,
965{
966 type Output = HeaplessBigInt<T, CAP, P>;
967 fn borrowing_sub(self, rhs: Self, borrow_in: bool) -> (Self::Output, bool) {
968 <HeaplessBigInt<T, CAP, P> as BorrowingSub>::borrowing_sub(*self, *rhs, borrow_in)
969 }
970}
971
972impl<T, const CAP: usize, P: Personality> CarryingMul for HeaplessBigInt<T, CAP, P>
990where
991 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
992{
993 type Unsigned = Self;
994 type Output = Self;
995
996 fn carrying_mul(self, rhs: Self, carry: Self) -> (Self::Unsigned, Self::Output) {
997 let zero_v = <Self as const_num_traits::Zero>::zero();
998 self.carrying_mul_add(rhs, carry, zero_v)
999 }
1000
1001 fn carrying_mul_add(self, rhs: Self, carry: Self, add: Self) -> (Self::Unsigned, Self::Output) {
1002 let w = core::cmp::max(
1005 core::cmp::max(self.len as usize, rhs.len as usize),
1006 core::cmp::max(carry.len as usize, add.len as usize),
1007 );
1008 let mut lo_limbs = [zero::<T>(); CAP];
1009 let mut hi_limbs = [zero::<T>(); CAP];
1010
1011 let a_n = self.len as usize;
1015 let b_n = rhs.len as usize;
1016 let mut i = 0;
1017 while i < a_n {
1018 let mut c = zero::<T>();
1019 let mut j = 0;
1020 while j < b_n {
1021 let pos = i + j;
1022 let (t_lo, t_hi) = <T as CarryingMul>::carrying_mul(self.limbs[i], rhs.limbs[j], c);
1023 let existing = if pos < w {
1024 lo_limbs[pos]
1025 } else {
1026 hi_limbs[pos - w]
1027 };
1028 let (sum, c1) = <T as CarryingAdd>::carrying_add(existing, t_lo, false);
1029 if pos < w {
1030 lo_limbs[pos] = sum;
1031 } else {
1032 hi_limbs[pos - w] = sum;
1033 }
1034 let (new_c, _) = <T as CarryingAdd>::carrying_add(t_hi, zero::<T>(), c1);
1035 c = new_c;
1036 j += 1;
1037 }
1038 let tail = i + b_n;
1040 if tail < w {
1041 let (sum, _) = <T as CarryingAdd>::carrying_add(lo_limbs[tail], c, false);
1042 lo_limbs[tail] = sum;
1043 } else {
1044 let (sum, _) = <T as CarryingAdd>::carrying_add(hi_limbs[tail - w], c, false);
1045 hi_limbs[tail - w] = sum;
1046 }
1047 i += 1;
1048 }
1049
1050 for src in [&carry, &add] {
1052 let mut cin = false;
1053 let mut i = 0;
1054 while i < w {
1055 let (sum, c) = <T as CarryingAdd>::carrying_add(lo_limbs[i], src.limbs[i], cin);
1056 lo_limbs[i] = sum;
1057 cin = c;
1058 i += 1;
1059 }
1060 let mut i = 0;
1067 match P::TAG {
1068 PersonalityTag::Nct => {
1069 while cin && i < w {
1070 let (sum, c) =
1071 <T as CarryingAdd>::carrying_add(hi_limbs[i], zero::<T>(), true);
1072 hi_limbs[i] = sum;
1073 cin = c;
1074 i += 1;
1075 }
1076 }
1077 PersonalityTag::Ct => {
1078 while i < w {
1079 let (sum, c) =
1080 <T as CarryingAdd>::carrying_add(hi_limbs[i], zero::<T>(), cin);
1081 hi_limbs[i] = sum;
1082 cin = c;
1083 i += 1;
1084 }
1085 }
1086 }
1087 }
1088
1089 let lo = HeaplessBigInt {
1090 limbs: lo_limbs,
1091 len: w as u16,
1092 _p: PhantomData,
1093 };
1094 let hi = HeaplessBigInt {
1095 limbs: hi_limbs,
1096 len: w as u16,
1097 _p: PhantomData,
1098 };
1099 (lo, hi)
1100 }
1101}
1102
1103impl<T, const CAP: usize, P: Personality> CarryingMul for &HeaplessBigInt<T, CAP, P>
1108where
1109 T: MachineWord + CarryingMul<Unsigned = T, Output = T>,
1110{
1111 type Unsigned = HeaplessBigInt<T, CAP, P>;
1112 type Output = HeaplessBigInt<T, CAP, P>;
1113
1114 fn carrying_mul(self, rhs: Self, carry: Self) -> (Self::Unsigned, Self::Output) {
1115 <HeaplessBigInt<T, CAP, P> as CarryingMul>::carrying_mul(*self, *rhs, *carry)
1116 }
1117
1118 fn carrying_mul_add(self, rhs: Self, carry: Self, add: Self) -> (Self::Unsigned, Self::Output) {
1119 <HeaplessBigInt<T, CAP, P> as CarryingMul>::carrying_mul_add(*self, *rhs, *carry, *add)
1120 }
1121}
1122
1123#[inline]
1124pub(crate) fn zero_tail_ok<T: MachineWord>(limbs: &[T], used: usize) -> bool {
1125 let mut i = used;
1126 while i < limbs.len() {
1127 if !is_zero(&limbs[i]) {
1128 return false;
1129 }
1130 i += 1;
1131 }
1132 true
1133}
1134
1135#[cfg(test)]
1136mod tests {
1137 use super::*;
1138 use const_num_traits::Zero;
1139
1140 type H = HeaplessBigInt<u32, 8, Nct>; #[test]
1143 fn saturation_is_operand_width_not_cap() {
1144 let a = H::from_le_bytes(&0xFFFF_FFFFu32.to_le_bytes()); let one = H::from_le_bytes(&1u32.to_le_bytes());
1150 let s = SaturatingAdd::saturating_add(a, one);
1151 assert_eq!(s.len, 1);
1152 assert_eq!(s.limbs[0], 0xFFFF_FFFF);
1153
1154 let big = H::from_le_bytes(&0x1_0000u32.to_le_bytes());
1156 let m = SaturatingMul::saturating_mul(big, big);
1157 assert_eq!(m.len, 1);
1158 assert_eq!(m.limbs[0], 0xFFFF_FFFF);
1159 }
1160
1161 #[test]
1162 fn saturating_sub_clamps_to_zero_at_width() {
1163 let one = H::from_le_bytes(&1u32.to_le_bytes()); let two = H::from_le_bytes(&2u32.to_le_bytes());
1165 let s = SaturatingSub::saturating_sub(one, two);
1166 assert_eq!(s.len, 1);
1167 assert!(<H as Zero>::is_zero(&s));
1168 }
1169
1170 #[test]
1171 fn checked_div_rem_by_zero_is_none() {
1172 let a = H::from_le_bytes(&100u32.to_le_bytes());
1173 let z = <H as Zero>::zero();
1174 assert_eq!(a.checked_div(&z), None);
1175 assert_eq!(a.checked_rem(&z), None);
1176 let seven = H::from_le_bytes(&7u32.to_le_bytes());
1177 assert_eq!(a.checked_div(&seven).unwrap().limbs[0], 14);
1178 assert_eq!(a.checked_rem(&seven).unwrap().limbs[0], 2);
1179 }
1180
1181 #[test]
1184 fn ct_checked_arithmetic() {
1185 use const_num_traits::ops::ct::{CtCheckedAdd, CtCheckedMul, CtCheckedSub};
1186 type Cc = HeaplessBigInt<u8, 4, Ct>;
1187
1188 let a = Cc::from(100u32);
1190 let b = Cc::from(50u32);
1191 let s = a.ct_checked_add(&b);
1192 assert!(bool::from(s.is_some()));
1193 assert_eq!(s.unwrap(), Cc::from(150u32));
1194 assert!(bool::from(a.ct_checked_sub(&b).is_some()));
1195 assert!(bool::from(
1196 Cc::from(7u32).ct_checked_mul(&Cc::from(9u32)).is_some()
1197 ));
1198
1199 assert!(!bool::from(
1201 Cc::from(u32::MAX).ct_checked_add(&Cc::from(1u32)).is_some()
1202 ));
1203 assert!(!bool::from(
1204 Cc::from(0u32).ct_checked_sub(&Cc::from(1u32)).is_some()
1205 ));
1206 assert!(!bool::from(
1207 Cc::from(0x1_0000u32)
1208 .ct_checked_mul(&Cc::from(0x1_0000u32))
1209 .is_some()
1210 ));
1211 }
1212
1213 #[test]
1216 fn ct_saturating_matches_nct() {
1217 type Cn = HeaplessBigInt<u8, 4, Nct>;
1218 type Cc = HeaplessBigInt<u8, 4, Ct>;
1219 let cases = [(100u32, 50u32), (u32::MAX, 1), (u32::MAX, u32::MAX), (5, 9)];
1220 for (a, b) in cases {
1221 assert_eq!(
1222 SaturatingAdd::saturating_add(Cc::from(a), Cc::from(b)),
1223 Cc::from(a.saturating_add(b)),
1224 "ct saturating_add({a},{b})"
1225 );
1226 assert_eq!(
1227 SaturatingSub::saturating_sub(Cc::from(a), Cc::from(b)),
1228 Cc::from(a.saturating_sub(b))
1229 );
1230 assert_eq!(
1231 SaturatingMul::saturating_mul(Cc::from(a), Cc::from(b)),
1232 Cc::from(a.saturating_mul(b))
1233 );
1234 assert_eq!(
1236 SaturatingAdd::saturating_add(Cn::from(a), Cn::from(b)),
1237 Cn::from(a.saturating_add(b))
1238 );
1239 }
1240 }
1241
1242 #[test]
1246 fn by_ref_matches_value() {
1247 let a = H::from(100u32);
1248 let b = H::from(7u32);
1249 assert_eq!(
1250 CheckedAdd::checked_add(&a, &b),
1251 CheckedAdd::checked_add(a, b)
1252 );
1253 assert_eq!(
1254 CheckedSub::checked_sub(&a, &b),
1255 CheckedSub::checked_sub(a, b)
1256 );
1257 assert_eq!(
1258 CheckedMul::checked_mul(&a, &b),
1259 CheckedMul::checked_mul(a, b)
1260 );
1261 assert_eq!(
1262 SaturatingAdd::saturating_add(&a, &b),
1263 SaturatingAdd::saturating_add(a, b)
1264 );
1265 assert_eq!(
1266 SaturatingSub::saturating_sub(&a, &b),
1267 SaturatingSub::saturating_sub(a, b)
1268 );
1269 assert_eq!(
1270 SaturatingMul::saturating_mul(&a, &b),
1271 SaturatingMul::saturating_mul(a, b)
1272 );
1273 assert_eq!(
1274 CarryingAdd::carrying_add(&a, &b, true),
1275 CarryingAdd::carrying_add(a, b, true)
1276 );
1277 assert_eq!(
1278 BorrowingSub::borrowing_sub(&a, &b, true),
1279 BorrowingSub::borrowing_sub(a, b, true)
1280 );
1281 let z = <H as Zero>::zero();
1282 assert_eq!(
1283 CarryingMul::carrying_mul(&a, &b, &z),
1284 CarryingMul::carrying_mul(a, b, z)
1285 );
1286 assert_eq!(
1287 CarryingMul::carrying_mul_add(&a, &b, &z, &b),
1288 CarryingMul::carrying_mul_add(a, b, z, b)
1289 );
1290
1291 type Cc = HeaplessBigInt<u8, 4, Ct>;
1293 let ca = Cc::from(u32::MAX);
1294 let cb = Cc::from(1u32);
1295 assert_eq!(
1296 SaturatingAdd::saturating_add(&ca, &cb),
1297 SaturatingAdd::saturating_add(ca, cb)
1298 );
1299 }
1300}