Skip to main content

crypto_bigint/
wrapping.rs

1//! Wrapping arithmetic.
2
3use crate::{
4    Choice, CtEq, CtSelect, One, UintRef, WrappingAdd, WrappingMul, WrappingNeg, WrappingShl,
5    WrappingShr, WrappingSub, Zero,
6};
7use core::{
8    fmt,
9    ops::{Add, Mul, Neg, Shl, Shr, Sub},
10};
11
12#[cfg(feature = "rand_core")]
13use {crate::Random, rand_core::TryRng};
14
15#[cfg(feature = "serde")]
16use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer};
17
18/// Provides intentionally-wrapped arithmetic on `T`.
19///
20/// This is analogous to [`core::num::Wrapping`] but allows this crate to
21/// define trait impls for this type.
22#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
23pub struct Wrapping<T>(pub T);
24
25impl<T: AsRef<UintRef>> AsRef<UintRef> for Wrapping<T> {
26    fn as_ref(&self) -> &UintRef {
27        self.0.as_ref()
28    }
29}
30
31impl<T: AsMut<UintRef>> AsMut<UintRef> for Wrapping<T> {
32    fn as_mut(&mut self) -> &mut UintRef {
33        self.0.as_mut()
34    }
35}
36
37impl<T: WrappingAdd> Add<Self> for Wrapping<T> {
38    type Output = Wrapping<T>;
39
40    #[inline]
41    fn add(self, rhs: Self) -> Self::Output {
42        Wrapping(self.0.wrapping_add(&rhs.0))
43    }
44}
45
46impl<T: WrappingAdd> Add<&Self> for Wrapping<T> {
47    type Output = Wrapping<T>;
48
49    #[inline]
50    fn add(self, rhs: &Self) -> Self::Output {
51        Wrapping(self.0.wrapping_add(&rhs.0))
52    }
53}
54
55impl<T: WrappingAdd> Add<Wrapping<T>> for &Wrapping<T> {
56    type Output = Wrapping<T>;
57
58    #[inline]
59    fn add(self, rhs: Wrapping<T>) -> Self::Output {
60        Wrapping(self.0.wrapping_add(&rhs.0))
61    }
62}
63
64impl<T: WrappingAdd> Add<&Wrapping<T>> for &Wrapping<T> {
65    type Output = Wrapping<T>;
66
67    #[inline]
68    fn add(self, rhs: &Wrapping<T>) -> Self::Output {
69        Wrapping(self.0.wrapping_add(&rhs.0))
70    }
71}
72
73impl<T: WrappingSub> Sub<Self> for Wrapping<T> {
74    type Output = Wrapping<T>;
75
76    #[inline]
77    fn sub(self, rhs: Self) -> Self::Output {
78        Wrapping(self.0.wrapping_sub(&rhs.0))
79    }
80}
81
82impl<T: WrappingSub> Sub<&Self> for Wrapping<T> {
83    type Output = Wrapping<T>;
84
85    #[inline]
86    fn sub(self, rhs: &Self) -> Self::Output {
87        Wrapping(self.0.wrapping_sub(&rhs.0))
88    }
89}
90
91impl<T: WrappingSub> Sub<Wrapping<T>> for &Wrapping<T> {
92    type Output = Wrapping<T>;
93
94    #[inline]
95    fn sub(self, rhs: Wrapping<T>) -> Self::Output {
96        Wrapping(self.0.wrapping_sub(&rhs.0))
97    }
98}
99
100impl<T: WrappingSub> Sub<&Wrapping<T>> for &Wrapping<T> {
101    type Output = Wrapping<T>;
102
103    #[inline]
104    fn sub(self, rhs: &Wrapping<T>) -> Self::Output {
105        Wrapping(self.0.wrapping_sub(&rhs.0))
106    }
107}
108
109impl<T: WrappingMul> Mul<Self> for Wrapping<T> {
110    type Output = Wrapping<T>;
111
112    #[inline]
113    fn mul(self, rhs: Self) -> Self::Output {
114        Wrapping(self.0.wrapping_mul(&rhs.0))
115    }
116}
117
118impl<T: WrappingMul> Mul<&Self> for Wrapping<T> {
119    type Output = Wrapping<T>;
120
121    #[inline]
122    fn mul(self, rhs: &Self) -> Self::Output {
123        Wrapping(self.0.wrapping_mul(&rhs.0))
124    }
125}
126
127impl<T: WrappingMul> Mul<Wrapping<T>> for &Wrapping<T> {
128    type Output = Wrapping<T>;
129
130    #[inline]
131    fn mul(self, rhs: Wrapping<T>) -> Self::Output {
132        Wrapping(self.0.wrapping_mul(&rhs.0))
133    }
134}
135
136impl<T: WrappingMul> Mul<&Wrapping<T>> for &Wrapping<T> {
137    type Output = Wrapping<T>;
138
139    #[inline]
140    fn mul(self, rhs: &Wrapping<T>) -> Self::Output {
141        Wrapping(self.0.wrapping_mul(&rhs.0))
142    }
143}
144
145impl<T: WrappingNeg> Neg for Wrapping<T> {
146    type Output = Wrapping<T>;
147
148    #[inline]
149    fn neg(self) -> Self::Output {
150        Wrapping(self.0.wrapping_neg())
151    }
152}
153
154impl<T: WrappingNeg> Neg for &Wrapping<T> {
155    type Output = Wrapping<T>;
156
157    #[inline]
158    fn neg(self) -> Self::Output {
159        Wrapping(self.0.wrapping_neg())
160    }
161}
162
163impl<T: WrappingShl> Shl<u32> for Wrapping<T> {
164    type Output = Wrapping<T>;
165
166    #[inline]
167    fn shl(self, rhs: u32) -> Self::Output {
168        Wrapping(self.0.wrapping_shl(rhs))
169    }
170}
171
172impl<T: WrappingShl> Shl<u32> for &Wrapping<T> {
173    type Output = Wrapping<T>;
174
175    #[inline]
176    fn shl(self, rhs: u32) -> Self::Output {
177        Wrapping(self.0.wrapping_shl(rhs))
178    }
179}
180
181impl<T: WrappingShr> Shr<u32> for Wrapping<T> {
182    type Output = Wrapping<T>;
183
184    #[inline]
185    fn shr(self, rhs: u32) -> Self::Output {
186        Wrapping(self.0.wrapping_shr(rhs))
187    }
188}
189
190impl<T: WrappingShr> Shr<u32> for &Wrapping<T> {
191    type Output = Wrapping<T>;
192
193    #[inline]
194    fn shr(self, rhs: u32) -> Self::Output {
195        Wrapping(self.0.wrapping_shr(rhs))
196    }
197}
198
199impl<T> CtEq for Wrapping<T>
200where
201    T: CtEq,
202{
203    #[inline]
204    fn ct_eq(&self, other: &Self) -> Choice {
205        CtEq::ct_eq(&self.0, &other.0)
206    }
207}
208
209impl<T> CtSelect for Wrapping<T>
210where
211    T: CtSelect,
212{
213    #[inline]
214    fn ct_select(&self, other: &Self, choice: Choice) -> Self {
215        Self(self.0.ct_select(&other.0, choice))
216    }
217}
218
219impl<T: Zero> Zero for Wrapping<T> {
220    #[inline]
221    fn zero() -> Self {
222        Wrapping(T::zero())
223    }
224}
225
226impl<T: One> One for Wrapping<T> {
227    #[inline]
228    fn one() -> Self {
229        Wrapping(T::one())
230    }
231}
232
233impl<T: num_traits::Zero + WrappingAdd> num_traits::Zero for Wrapping<T> {
234    #[inline]
235    fn zero() -> Self {
236        Wrapping(T::zero())
237    }
238
239    #[inline]
240    fn is_zero(&self) -> bool {
241        self.0.is_zero()
242    }
243}
244
245impl<T: num_traits::One + WrappingMul + PartialEq> num_traits::One for Wrapping<T> {
246    #[inline]
247    fn one() -> Self {
248        Wrapping(T::one())
249    }
250
251    #[inline]
252    fn is_one(&self) -> bool {
253        self.0.is_one()
254    }
255}
256
257impl<T: fmt::Display> fmt::Display for Wrapping<T> {
258    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
259        self.0.fmt(f)
260    }
261}
262
263impl<T: fmt::Binary> fmt::Binary for Wrapping<T> {
264    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265        self.0.fmt(f)
266    }
267}
268
269impl<T: fmt::Octal> fmt::Octal for Wrapping<T> {
270    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271        self.0.fmt(f)
272    }
273}
274
275impl<T: fmt::LowerHex> fmt::LowerHex for Wrapping<T> {
276    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277        self.0.fmt(f)
278    }
279}
280
281impl<T: fmt::UpperHex> fmt::UpperHex for Wrapping<T> {
282    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
283        self.0.fmt(f)
284    }
285}
286
287#[cfg(feature = "rand_core")]
288impl<T: Random> Random for Wrapping<T> {
289    fn try_random_from_rng<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
290        Ok(Wrapping(Random::try_random_from_rng(rng)?))
291    }
292}
293
294#[cfg(feature = "serde")]
295impl<'de, T: Deserialize<'de>> Deserialize<'de> for Wrapping<T> {
296    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
297    where
298        D: Deserializer<'de>,
299    {
300        Ok(Self(T::deserialize(deserializer)?))
301    }
302}
303
304#[cfg(feature = "serde")]
305impl<T: Serialize> Serialize for Wrapping<T> {
306    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
307    where
308        S: Serializer,
309    {
310        self.0.serialize(serializer)
311    }
312}
313
314#[cfg(feature = "subtle")]
315impl<T> subtle::ConditionallySelectable for Wrapping<T>
316where
317    T: Copy,
318    Self: CtSelect,
319{
320    #[inline]
321    fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
322        a.ct_select(b, choice.into())
323    }
324}
325
326#[cfg(feature = "subtle")]
327impl<T> subtle::ConstantTimeEq for Wrapping<T>
328where
329    Self: CtEq,
330{
331    #[inline]
332    fn ct_eq(&self, other: &Self) -> subtle::Choice {
333        CtEq::ct_eq(self, other).into()
334    }
335}
336
337#[cfg(test)]
338mod tests {
339    use super::Wrapping;
340    use crate::{
341        Choice, CtEq, CtSelect, Limb, WrappingAdd, WrappingMul, WrappingNeg, WrappingShl,
342        WrappingShr, WrappingSub,
343    };
344
345    // FIXME Could use itertools combinations or an equivalent iterator
346    const INPUTS: &[(Limb, Limb)] = &[
347        (Limb::ZERO, Limb::ZERO),
348        (Limb::ZERO, Limb::ONE),
349        (Limb::ZERO, Limb::MAX),
350        (Limb::ONE, Limb::ZERO),
351        (Limb::ONE, Limb::ONE),
352        (Limb::ONE, Limb::MAX),
353        (Limb::MAX, Limb::ZERO),
354        (Limb::MAX, Limb::ONE),
355        (Limb::MAX, Limb::MAX),
356    ];
357
358    #[test]
359    fn wrapping_new() {
360        assert_eq!(Wrapping::<Limb>::default().0, Limb::default());
361        assert_eq!(<Wrapping<Limb> as crate::Zero>::zero().0, Limb::ZERO);
362        assert_eq!(<Wrapping<Limb> as crate::One>::one().0, Limb::ONE);
363        assert_eq!(<Wrapping<Limb> as num_traits::Zero>::zero().0, Limb::ZERO);
364        assert_eq!(<Wrapping<Limb> as num_traits::One>::one().0, Limb::ONE);
365    }
366
367    #[test]
368    #[cfg(feature = "alloc")]
369    fn wrapping_format() {
370        for a in [Limb::ZERO, Limb::ONE, Limb::MAX] {
371            assert_eq!(format!("{}", Wrapping(a)), format!("{}", a));
372            assert_eq!(format!("{:?}", Wrapping(a)), format!("Wrapping({:?})", a));
373            assert_eq!(format!("{:b}", Wrapping(a)), format!("{:b}", a));
374            assert_eq!(format!("{:o}", Wrapping(a)), format!("{:o}", a));
375            assert_eq!(format!("{:x}", Wrapping(a)), format!("{:x}", a));
376            assert_eq!(format!("{:X}", Wrapping(a)), format!("{:X}", a));
377        }
378    }
379    #[test]
380    fn wrapping_eq_select() {
381        let pairs: &[(Limb, Limb, bool)] = &[
382            (Limb::ZERO, Limb::ZERO, true),
383            (Limb::ZERO, Limb::ONE, false),
384            (Limb::ONE, Limb::ZERO, false),
385            (Limb::ONE, Limb::ONE, true),
386        ];
387
388        for (a, b, eq) in pairs {
389            assert_eq!(a.ct_eq(b).to_bool(), *eq);
390            assert!(a.ct_select(b, Choice::FALSE).ct_eq(a).to_bool());
391            assert!(a.ct_select(b, Choice::TRUE).ct_eq(b).to_bool());
392            #[cfg(feature = "subtle")]
393            assert_eq!(bool::from(subtle::ConstantTimeEq::ct_eq(a, b)), *eq);
394            #[cfg(feature = "subtle")]
395            assert!(
396                subtle::ConditionallySelectable::conditional_select(
397                    a,
398                    b,
399                    subtle::Choice::from(0u8)
400                )
401                .ct_eq(a)
402                .to_bool()
403            );
404            #[cfg(feature = "subtle")]
405            assert!(
406                subtle::ConditionallySelectable::conditional_select(
407                    a,
408                    b,
409                    subtle::Choice::from(1u8)
410                )
411                .ct_eq(b)
412                .to_bool()
413            );
414        }
415    }
416
417    #[allow(clippy::op_ref)]
418    #[test]
419    fn wrapping_add() {
420        for (a, b) in INPUTS {
421            let expect = WrappingAdd::wrapping_add(a, b);
422            assert_eq!((Wrapping(*a) + Wrapping(*b)).0, expect);
423            assert_eq!((&Wrapping(*a) + Wrapping(*b)).0, expect);
424            assert_eq!((Wrapping(*a) + &Wrapping(*b)).0, expect);
425            assert_eq!((&Wrapping(*a) + &Wrapping(*b)).0, expect);
426        }
427    }
428
429    #[allow(clippy::op_ref)]
430    #[test]
431    fn wrapping_sub() {
432        for (a, b) in INPUTS {
433            let expect = WrappingSub::wrapping_sub(a, b);
434            assert_eq!((Wrapping(*a) - Wrapping(*b)).0, expect);
435            assert_eq!((&Wrapping(*a) - Wrapping(*b)).0, expect);
436            assert_eq!((Wrapping(*a) - &Wrapping(*b)).0, expect);
437            assert_eq!((&Wrapping(*a) - &Wrapping(*b)).0, expect);
438        }
439    }
440
441    #[allow(clippy::op_ref)]
442    #[test]
443    fn wrapping_mul() {
444        for (a, b) in INPUTS {
445            let expect = WrappingMul::wrapping_mul(a, b);
446            assert_eq!((Wrapping(*a) * Wrapping(*b)).0, expect);
447            assert_eq!((&Wrapping(*a) * Wrapping(*b)).0, expect);
448            assert_eq!((Wrapping(*a) * &Wrapping(*b)).0, expect);
449            assert_eq!((&Wrapping(*a) * &Wrapping(*b)).0, expect);
450        }
451    }
452
453    #[allow(clippy::op_ref)]
454    #[test]
455    fn wrapping_neg() {
456        assert_eq!(
457            (-Wrapping(Limb::ZERO)).0,
458            WrappingNeg::wrapping_neg(&Limb::ZERO)
459        );
460        assert_eq!(
461            (-&Wrapping(Limb::ONE)).0,
462            WrappingNeg::wrapping_neg(&Limb::ONE)
463        );
464        assert_eq!(
465            (-Wrapping(Limb::MAX)).0,
466            WrappingNeg::wrapping_neg(&Limb::MAX)
467        );
468    }
469
470    #[allow(clippy::op_ref)]
471    #[test]
472    fn wrapping_shift() {
473        for a in [Limb::ZERO, Limb::ONE, Limb::MAX] {
474            assert_eq!((Wrapping(a) << 1).0, WrappingShl::wrapping_shl(&a, 1));
475            assert_eq!((&Wrapping(a) << 2).0, WrappingShl::wrapping_shl(&a, 2));
476            assert_eq!((Wrapping(a) >> 1).0, WrappingShr::wrapping_shr(&a, 1));
477            assert_eq!((&Wrapping(a) >> 2).0, WrappingShr::wrapping_shr(&a, 2));
478        }
479    }
480}