Skip to main content

bnum/buint/
wrapping.rs

1use crate::errors::option_expect;
2use crate::ExpType;
3use crate::{doc, errors};
4
5macro_rules! wrapping {
6    ($BUint: ident, $BInt: ident, $Digit: ident) => {
7        #[doc = doc::wrapping::impl_desc!()]
8        impl<const N: usize> $BUint<N> {
9            #[doc = doc::wrapping::wrapping_add!(U)]
10            #[must_use = doc::must_use_op!()]
11            #[inline]
12            pub const fn wrapping_add(self, rhs: Self) -> Self {
13                self.overflowing_add(rhs).0
14            }
15
16            #[doc = doc::wrapping::wrapping_add_signed!(U)]
17            #[must_use = doc::must_use_op!()]
18            #[inline]
19            pub const fn wrapping_add_signed(self, rhs: $BInt<N>) -> Self {
20                self.overflowing_add_signed(rhs).0
21            }
22
23            #[doc = doc::wrapping::wrapping_sub!(U)]
24            #[must_use = doc::must_use_op!()]
25            #[inline]
26            pub const fn wrapping_sub(self, rhs: Self) -> Self {
27                self.overflowing_sub(rhs).0
28            }
29
30            #[doc = doc::wrapping::wrapping_mul!(U)]
31            #[must_use = doc::must_use_op!()]
32            #[inline]
33            pub const fn wrapping_mul(self, rhs: Self) -> Self {
34                self.overflowing_mul(rhs).0
35            }
36
37            #[doc = doc::wrapping::wrapping_div!(U)]
38            #[must_use = doc::must_use_op!()]
39            #[inline]
40            pub const fn wrapping_div(self, rhs: Self) -> Self {
41                option_expect!(self.checked_div(rhs), errors::err_msg!(errors::div_by_zero_message!()))
42            }
43
44            #[doc = doc::wrapping::wrapping_div_euclid!(U)]
45            #[must_use = doc::must_use_op!()]
46            #[inline]
47            pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
48                self.wrapping_div(rhs)
49            }
50
51            #[doc = doc::wrapping::wrapping_rem!(U)]
52            #[must_use = doc::must_use_op!()]
53            #[inline]
54            pub const fn wrapping_rem(self, rhs: Self) -> Self {
55                option_expect!(self.checked_rem(rhs), errors::err_msg!(errors::rem_by_zero_message!()))
56            }
57
58            #[doc = doc::wrapping::wrapping_rem_euclid!(U)]
59            #[must_use = doc::must_use_op!()]
60            #[inline]
61            pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
62                self.wrapping_rem(rhs)
63            }
64
65            #[doc = doc::wrapping::wrapping_neg!(U)]
66            #[must_use = doc::must_use_op!()]
67            #[inline]
68            pub const fn wrapping_neg(self) -> Self {
69                self.overflowing_neg().0
70            }
71
72            #[doc = doc::wrapping::wrapping_shl!(U)]
73            #[must_use = doc::must_use_op!()]
74            #[inline]
75            pub const fn wrapping_shl(self, rhs: ExpType) -> Self {
76                self.overflowing_shl(rhs).0
77            }
78
79            #[doc = doc::wrapping::wrapping_shr!(U)]
80            #[must_use = doc::must_use_op!()]
81            #[inline]
82            pub const fn wrapping_shr(self, rhs: ExpType) -> Self {
83                self.overflowing_shr(rhs).0
84            }
85
86            #[doc = doc::wrapping::wrapping_pow!(U)]
87            #[must_use = doc::must_use_op!()]
88            #[inline]
89            pub const fn wrapping_pow(mut self, mut pow: ExpType) -> Self {
90                // https://en.wikipedia.org/wiki/Exponentiation_by_squaring#Basic_method
91                if pow == 0 {
92                    return Self::ONE;
93                }
94                let mut y = Self::ONE;
95                while pow > 1 {
96                    if pow & 1 == 1 {
97                        y = self.wrapping_mul(y);
98                    }
99                    self = self.wrapping_mul(self);
100                    pow >>= 1;
101                }
102                self.wrapping_mul(y)
103            }
104
105            #[doc = doc::wrapping::wrapping_next_power_of_two!(U 256)]
106            #[must_use = doc::must_use_op!()]
107            #[inline]
108            pub const fn wrapping_next_power_of_two(self) -> Self {
109                match self.checked_next_power_of_two() {
110                    Some(int) => int,
111                    None => Self::ZERO,
112                }
113            }
114        }
115    };
116}
117
118#[cfg(test)]
119crate::test::all_digit_tests! {
120    use crate::test::{test_bignum, types::{utest, itest}};
121
122    #[test]
123    #[should_panic(expected = "attempt to divide by zero")]
124    fn div_by_zero_panic() {
125        let a = UTEST::MAX;
126        let b = UTEST::ZERO;
127        let _ = a.wrapping_div(b);
128    }
129
130    #[test]
131    #[should_panic(expected = "attempt to calculate the remainder with a divisor of zero")]
132    fn rem_by_zero_panic() {
133        let a = UTEST::MAX;
134        let b = UTEST::ZERO;
135        let _ = a.wrapping_rem(b);
136    }
137
138    test_bignum! {
139        function: <utest>::wrapping_add(a: utest, b: utest)
140    }
141    test_bignum! {
142        function: <utest>::wrapping_add_signed(a: utest, b: itest)
143    }
144    test_bignum! {
145        function: <utest>::wrapping_sub(a: utest, b: utest)
146    }
147    test_bignum! {
148        function: <utest>::wrapping_mul(a: utest, b: utest)
149    }
150    test_bignum! {
151        function: <utest>::wrapping_div(a: utest, b: utest),
152        skip: b == 0
153    }
154    test_bignum! {
155        function: <utest>::wrapping_div_euclid(a: utest, b: utest),
156        skip: b == 0
157    }
158    test_bignum! {
159        function: <utest>::wrapping_rem(a: utest, b: utest),
160        skip: b == 0
161    }
162    test_bignum! {
163        function: <utest>::wrapping_rem_euclid(a: utest, b: utest),
164        skip: b == 0
165    }
166    test_bignum! {
167        function: <utest>::wrapping_neg(a: utest)
168    }
169    test_bignum! {
170        function: <utest>::wrapping_shl(a: utest, b: u16)
171    }
172    test_bignum! {
173        function: <utest>::wrapping_shr(a: utest, b: u16)
174    }
175    test_bignum! {
176        function: <utest>::wrapping_pow(a: utest, b: u16)
177    }
178    test_bignum! {
179        function: <utest>::wrapping_next_power_of_two(a: utest),
180        cases: [
181            (utest::MAX)
182        ]
183    }
184}
185
186crate::macro_impl!(wrapping);