1 //! [`UInt`] addition operations.
3 use crate::{Checked, CheckedMul, Concat, Limb, UInt, Wrapping, Zero}
;
4 use core
::ops
::{Mul, MulAssign}
;
7 impl<const LIMBS
: usize> UInt
<LIMBS
> {
8 /// Compute "wide" multiplication, with a product twice the size of the input.
10 /// Returns a tuple containing the `(lo, hi)` components of the product.
14 /// Releases of `crypto-bigint` prior to v0.3 used `(hi, lo)` ordering
15 /// instead. This has been changed for better consistency with the rest of
16 /// the APIs in this crate.
18 /// For more info see: <https://github.com/RustCrypto/crypto-bigint/issues/4>
19 // TODO(tarcieri): use `concat` to construct a wide output
20 pub const fn mul_wide(&self, rhs
: &Self) -> (Self, Self) {
22 let mut lo
= Self::ZERO
;
23 let mut hi
= Self::ZERO
;
25 // Schoolbook multiplication.
26 // TODO(tarcieri): use Karatsuba for better performance?
29 let mut carry
= Limb
::ZERO
;
35 let (n
, c
) = hi
.limbs
[k
- LIMBS
].mac(self.limbs
[i
], rhs
.limbs
[j
], carry
);
36 hi
.limbs
[k
- LIMBS
] = n
;
39 let (n
, c
) = lo
.limbs
[k
].mac(self.limbs
[i
], rhs
.limbs
[j
], carry
);
47 hi
.limbs
[i
+ j
- LIMBS
] = carry
;
54 /// Perform saturating multiplication, returning `MAX` on overflow.
55 pub const fn saturating_mul(&self, rhs
: &Self) -> Self {
56 let (res
, overflow
) = self.mul_wide(rhs
);
59 let mut accumulator
= 0;
62 accumulator
|= overflow
.limbs
[i
].0;
73 /// Perform wrapping multiplication, discarding overflow.
74 pub const fn wrapping_mul(&self, rhs
: &Self) -> Self {
78 /// Square self, returning a "wide" result.
79 pub fn square(&self) -> <Self as Concat
>::Output
83 let (lo
, hi
) = self.mul_wide(self);
88 impl<const LIMBS
: usize> CheckedMul
<&UInt
<LIMBS
>> for UInt
<LIMBS
> {
91 fn checked_mul(&self, rhs
: &Self) -> CtOption
<Self> {
92 let (lo
, hi
) = self.mul_wide(rhs
);
93 CtOption
::new(lo
, hi
.is_zero())
97 impl<const LIMBS
: usize> Mul
for Wrapping
<UInt
<LIMBS
>> {
100 fn mul(self, rhs
: Self) -> Wrapping
<UInt
<LIMBS
>> {
101 Wrapping(self.0.wrapping_mul(&rhs
.0))
105 impl<const LIMBS
: usize> Mul
<&Wrapping
<UInt
<LIMBS
>>> for Wrapping
<UInt
<LIMBS
>> {
106 type Output
= Wrapping
<UInt
<LIMBS
>>;
108 fn mul(self, rhs
: &Wrapping
<UInt
<LIMBS
>>) -> Wrapping
<UInt
<LIMBS
>> {
109 Wrapping(self.0.wrapping_mul(&rhs
.0))
113 impl<const LIMBS
: usize> Mul
<Wrapping
<UInt
<LIMBS
>>> for &Wrapping
<UInt
<LIMBS
>> {
114 type Output
= Wrapping
<UInt
<LIMBS
>>;
116 fn mul(self, rhs
: Wrapping
<UInt
<LIMBS
>>) -> Wrapping
<UInt
<LIMBS
>> {
117 Wrapping(self.0.wrapping_mul(&rhs
.0))
121 impl<const LIMBS
: usize> Mul
<&Wrapping
<UInt
<LIMBS
>>> for &Wrapping
<UInt
<LIMBS
>> {
122 type Output
= Wrapping
<UInt
<LIMBS
>>;
124 fn mul(self, rhs
: &Wrapping
<UInt
<LIMBS
>>) -> Wrapping
<UInt
<LIMBS
>> {
125 Wrapping(self.0.wrapping_mul(&rhs
.0))
129 impl<const LIMBS
: usize> MulAssign
for Wrapping
<UInt
<LIMBS
>> {
130 fn mul_assign(&mut self, other
: Self) {
131 *self = *self * other
;
135 impl<const LIMBS
: usize> MulAssign
<&Wrapping
<UInt
<LIMBS
>>> for Wrapping
<UInt
<LIMBS
>> {
136 fn mul_assign(&mut self, other
: &Self) {
137 *self = *self * other
;
141 impl<const LIMBS
: usize> Mul
for Checked
<UInt
<LIMBS
>> {
144 fn mul(self, rhs
: Self) -> Checked
<UInt
<LIMBS
>> {
145 Checked(self.0.and_then(|a
| rhs
.0.and_then(|b
| a
.checked_mul(&b
))))
149 impl<const LIMBS
: usize> Mul
<&Checked
<UInt
<LIMBS
>>> for Checked
<UInt
<LIMBS
>> {
150 type Output
= Checked
<UInt
<LIMBS
>>;
152 fn mul(self, rhs
: &Checked
<UInt
<LIMBS
>>) -> Checked
<UInt
<LIMBS
>> {
153 Checked(self.0.and_then(|a
| rhs
.0.and_then(|b
| a
.checked_mul(&b
))))
157 impl<const LIMBS
: usize> Mul
<Checked
<UInt
<LIMBS
>>> for &Checked
<UInt
<LIMBS
>> {
158 type Output
= Checked
<UInt
<LIMBS
>>;
160 fn mul(self, rhs
: Checked
<UInt
<LIMBS
>>) -> Checked
<UInt
<LIMBS
>> {
161 Checked(self.0.and_then(|a
| rhs
.0.and_then(|b
| a
.checked_mul(&b
))))
165 impl<const LIMBS
: usize> Mul
<&Checked
<UInt
<LIMBS
>>> for &Checked
<UInt
<LIMBS
>> {
166 type Output
= Checked
<UInt
<LIMBS
>>;
168 fn mul(self, rhs
: &Checked
<UInt
<LIMBS
>>) -> Checked
<UInt
<LIMBS
>> {
169 Checked(self.0.and_then(|a
| rhs
.0.and_then(|b
| a
.checked_mul(&b
))))
173 impl<const LIMBS
: usize> MulAssign
for Checked
<UInt
<LIMBS
>> {
174 fn mul_assign(&mut self, other
: Self) {
175 *self = *self * other
;
179 impl<const LIMBS
: usize> MulAssign
<&Checked
<UInt
<LIMBS
>>> for Checked
<UInt
<LIMBS
>> {
180 fn mul_assign(&mut self, other
: &Self) {
181 *self = *self * other
;
187 use crate::{CheckedMul, Zero, U64}
;
190 fn mul_wide_zero_and_one() {
191 assert_eq
!(U64
::ZERO
.mul_wide(&U64
::ZERO
), (U64
::ZERO
, U64
::ZERO
));
192 assert_eq
!(U64
::ZERO
.mul_wide(&U64
::ONE
), (U64
::ZERO
, U64
::ZERO
));
193 assert_eq
!(U64
::ONE
.mul_wide(&U64
::ZERO
), (U64
::ZERO
, U64
::ZERO
));
194 assert_eq
!(U64
::ONE
.mul_wide(&U64
::ONE
), (U64
::ONE
, U64
::ZERO
));
198 fn mul_wide_lo_only() {
199 let primes
: &[u32] = &[3, 5, 17, 256, 65537];
201 for &a_int
in primes
{
202 for &b_int
in primes
{
203 let (lo
, hi
) = U64
::from_u32(a_int
).mul_wide(&U64
::from_u32(b_int
));
204 let expected
= U64
::from_u64(a_int
as u64 * b_int
as u64);
205 assert_eq
!(lo
, expected
);
206 assert
!(bool
::from(hi
.is_zero()));
212 fn checked_mul_ok() {
213 let n
= U64
::from_u32(0xffff_ffff);
215 n
.checked_mul(&n
).unwrap(),
216 U64
::from_u64(0xffff_fffe_0000_0001)
221 fn checked_mul_overflow() {
222 let n
= U64
::from_u64(0xffff_ffff_ffff_ffff);
223 assert
!(bool
::from(n
.checked_mul(&n
).is_none()));
227 fn saturating_mul_no_overflow() {
228 let n
= U64
::from_u8(8);
229 assert_eq
!(n
.saturating_mul(&n
), U64
::from_u8(64));
233 fn saturating_mul_overflow() {
234 let a
= U64
::from(0xffff_ffff_ffff_ffffu64);
235 let b
= U64
::from(2u8);
236 assert_eq
!(a
.saturating_mul(&b
), U64
::MAX
);
241 let n
= U64
::from_u64(0xffff_ffff_ffff_ffff);
242 let (hi
, lo
) = n
.square().split();
243 assert_eq
!(lo
, U64
::from_u64(1));
244 assert_eq
!(hi
, U64
::from_u64(0xffff_ffff_ffff_fffe));