bnum/integer/saturating.rs
1use super::Uint;
2use crate::{Integer, Int};
3use crate::Exponent;
4use crate::doc;
5
6macro_rules! impl_desc {
7 () => {
8 "Saturating arithmetic methods which act on `self`: `self.saturating_...`. For each method, if overflow occurs, the largest or smallest value that can be represented by `Self` is returned instead."
9 };
10}
11
12#[doc = impl_desc!()]
13impl<const S: bool, const N: usize, const B: usize, const OM: u8> Integer<S, N, B, OM> {
14 /// Saturating integer addition. Computes `self + rhs`, returning `Self::MAX` if the result is too large to be represented by `Self`, or `Self::MIN` if the result is too small to be represented by `Self`.
15 ///
16 /// # Examples
17 ///
18 /// Basic usage:
19 ///
20 /// ```
21 /// use bnum::prelude::*;
22 /// use bnum::types::{U1024, I1024};
23 ///
24 /// assert_eq!(n!(1U1024).saturating_add(n!(1)), n!(2));
25 /// assert_eq!(U1024::MAX.saturating_add(U1024::MAX), U1024::MAX);
26 ///
27 /// assert_eq!(I1024::MIN.saturating_add(n!(-1)), I1024::MIN);
28 /// assert_eq!(I1024::MAX.saturating_add(n!(1)), I1024::MAX);
29 /// ```
30 #[must_use = doc::must_use_op!()]
31 #[inline]
32 pub const fn saturating_add(self, rhs: Self) -> Self {
33 match self.checked_add(rhs) {
34 Some(add) => add,
35 None => {
36 if self.is_negative_internal() {
37 Self::MIN
38 } else {
39 Self::MAX
40 }
41 }
42 }
43 }
44
45 /// Saturating integer subtraction. Computes `self - rhs`, returning `Self::MAX` if the result is too large to be represented by `Self`, or `Self::MIN` if the result is too small to be represented by `Self`.
46 ///
47 /// # Examples
48 ///
49 /// Basic usage:
50 ///
51 /// ```
52 /// use bnum::prelude::*;
53 /// use bnum::types::{U256, I256};
54 ///
55 /// assert_eq!(n!(1U256).saturating_sub(n!(1)), n!(0));
56 /// assert_eq!(n!(1U256).saturating_sub(n!(2)), n!(0));
57 ///
58 /// assert_eq!(I256::MIN.saturating_sub(I256::MAX), I256::MIN);
59 /// assert_eq!(I256::MAX.saturating_sub(n!(-1)), I256::MAX);
60 /// ```
61 #[must_use = doc::must_use_op!()]
62 #[inline]
63 pub const fn saturating_sub(self, rhs: Self) -> Self {
64 match self.checked_sub(rhs) {
65 Some(sub) => sub,
66 None => {
67 if rhs.is_negative_internal() {
68 Self::MAX
69 } else {
70 Self::MIN
71 }
72 }
73 }
74 }
75
76 /// Saturating integer multiplication. Computes `self * rhs`, returning `Self::MAX` if the result is too large to be represented by `Self`, or `Self::MIN` if the result is too small to be represented by `Self`.
77 ///
78 /// # Examples
79 ///
80 /// Basic usage:
81 ///
82 /// ```
83 /// use bnum::prelude::*;
84 /// use bnum::types::{U1024, I1024};
85 ///
86 /// assert_eq!(n!(1U1024).saturating_mul(n!(1)), n!(1));
87 /// assert_eq!(U1024::MAX.saturating_mul(n!(2)), U1024::MAX);
88 ///
89 /// assert_eq!(I1024::MIN.saturating_mul(n!(2)), I1024::MIN);
90 /// assert_eq!(I1024::MAX.saturating_mul(n!(3)), I1024::MAX);
91 /// ```
92 #[must_use = doc::must_use_op!()]
93 #[inline]
94 pub const fn saturating_mul(self, rhs: Self) -> Self {
95 match self.checked_mul(rhs) {
96 Some(mul) => mul,
97 None => {
98 if self.is_negative_internal() == rhs.is_negative_internal() {
99 Self::MAX
100 } else {
101 Self::MIN
102 }
103 }
104 }
105 }
106
107 /// Saturating integer division. The only time the result can saturate is if the integer is signed, and `self` is [`Self::MIN`] and `rhs` is `-1`, in which case the result is [`Self::MAX`].
108 ///
109 /// # Panics
110 ///
111 /// This function will panic if `rhs` is zero.
112 ///
113 /// # Examples
114 ///
115 /// Basic usage:
116 ///
117 /// ```
118 /// use bnum::prelude::*;
119 /// use bnum::types::I512;
120 ///
121 /// assert_eq!(n!(5U512).saturating_div(n!(2)), n!(2));
122 /// assert_eq!(I512::MIN.saturating_div(n!(-1)), I512::MAX);
123 /// ```
124 #[must_use = doc::must_use_op!()]
125 #[inline]
126 pub const fn saturating_div(self, rhs: Self) -> Self {
127 let (div, overflow) = self.overflowing_div(rhs);
128 if overflow { Self::MAX } else { div }
129 }
130
131 /// Saturating Euclidean integer division. The only time the result can saturate is if the integer is signed, and `self` is [`Self::MIN`] and `rhs` is `-1`, in which case the result is [`Self::MAX`].
132 ///
133 /// # Panics
134 ///
135 /// This function will panic if `rhs` is zero.
136 ///
137 /// # Examples
138 ///
139 /// Basic usage:
140 ///
141 /// ```
142 /// use bnum::prelude::*;
143 /// use bnum::types::I512;
144 ///
145 /// assert_eq!(n!(19U512).saturating_div_euclid(n!(5)), n!(3));
146 /// assert_eq!(I512::MIN.saturating_div_euclid(n!(-1)), I512::MAX);
147 /// ```
148 #[must_use = doc::must_use_op!()]
149 #[inline]
150 pub const fn saturating_div_euclid(self, rhs: Self) -> Self {
151 let (div, overflow) = self.overflowing_div_euclid(rhs);
152 if overflow { Self::MAX } else { div }
153 }
154
155 // these are not exported from the crate since the Rust primitives do not define them
156 #[must_use = doc::must_use_op!()]
157 #[inline]
158 pub(crate) const fn saturating_rem(self, rhs: Self) -> Self {
159 self.rem(rhs)
160 }
161
162 #[must_use = doc::must_use_op!()]
163 #[inline]
164 pub(crate) const fn saturating_rem_euclid(self, rhs: Self) -> Self {
165 self.rem_euclid(rhs)
166 }
167
168 /// Saturating exponentiation. Computes `self.pow(exp)`, returning `Self::MAX` if the result is too large to be represented by `Self`, or `Self::MIN` if the result is too small to be represented by `Self`.
169 ///
170 /// # Examples
171 ///
172 /// Basic usage:
173 ///
174 /// ```
175 /// use bnum::prelude::*;
176 /// use bnum::types::{U256, I256};
177 ///
178 /// assert_eq!(n!(2U256).saturating_pow(8), n!(256));
179 /// assert_eq!(n!(2U256).saturating_pow(256), U256::MAX);
180 ///
181 /// assert_eq!(n!(-2I256).saturating_pow(257), I256::MIN);
182 /// assert_eq!(n!(-2I256).saturating_pow(256), I256::MAX);
183 /// ```
184 #[must_use = doc::must_use_op!()]
185 #[inline]
186 pub const fn saturating_pow(self, exp: Exponent) -> Self {
187 match self.checked_pow(exp) {
188 Some(pow) => pow,
189 None => {
190 if self.is_negative_internal() && exp % 2 != 0 {
191 Self::MIN
192 } else {
193 Self::MAX
194 }
195 }
196 }
197 }
198}
199
200#[doc = concat!("(Unsigned integers only.) ", impl_desc!())]
201impl<const N: usize, const B: usize, const OM: u8> Uint<N, B, OM> {
202 #[inline]
203 const fn saturate_up(o: Option<Self>) -> Self {
204 match o {
205 Some(int) => int,
206 None => Self::MAX,
207 }
208 }
209
210 #[inline]
211 const fn saturate_down(o: Option<Self>) -> Self {
212 match o {
213 Some(int) => int,
214 None => Self::MIN,
215 }
216 }
217
218 /// Saturating addition with a signed integer of the same bit width. Computes `self + rhs`, returning `Self::MAX` if the result is too large to be represented by `Self`, or `Self::MIN` if the result is negative.
219 ///
220 /// # Examples
221 ///
222 /// Basic usage:
223 ///
224 /// ```
225 /// use bnum::prelude::*;
226 /// use bnum::types::U512;
227 ///
228 /// assert_eq!(n!(1U512).saturating_add_signed(n!(-1)), n!(0));
229 /// assert_eq!(U512::MAX.saturating_add_signed(n!(1)), U512::MAX);
230 /// assert_eq!(n!(1U512).saturating_add_signed(n!(-2)), n!(0));
231 /// ```
232 #[must_use = doc::must_use_op!()]
233 #[inline]
234 pub const fn saturating_add_signed(self, rhs: Int<N, B, OM>) -> Self {
235 if rhs.is_negative() {
236 Self::saturate_down(self.checked_add_signed(rhs))
237 } else {
238 Self::saturate_up(self.checked_add_signed(rhs))
239 }
240 }
241
242 /// Saturating subtraction with a signed integer of the same bit width. Computes `self - rhs`, returning `Self::MIN` if the result is negative, or `Self::MAX` if the result is too large to be represented by `Self`.
243 ///
244 /// # Examples
245 ///
246 /// Basic usage:
247 ///
248 /// ```
249 /// use bnum::prelude::*;
250 /// use bnum::types::U2048;
251 ///
252 /// assert_eq!(n!(1U2048).saturating_sub_signed(n!(-1)), n!(2));
253 /// assert_eq!(U2048::MAX.saturating_sub_signed(n!(-4)), U2048::MAX);
254 /// assert_eq!(n!(1U2048).saturating_sub_signed(n!(3)), n!(0));
255 /// ```
256 #[must_use = doc::must_use_op!()]
257 #[inline]
258 pub const fn saturating_sub_signed(self, rhs: Int<N, B, OM>) -> Self
259 {
260 if rhs.is_negative() {
261 Self::saturate_up(self.checked_sub_signed(rhs))
262 } else {
263 Self::saturate_down(self.checked_sub_signed(rhs))
264 }
265 }
266
267 // not exported from the crate since the Rust primitives do not define it
268 #[must_use = doc::must_use_op!()]
269 #[inline]
270 pub(crate) const fn saturating_next_power_of_two(self) -> Self {
271 match self.checked_next_power_of_two() {
272 Some(int) => int,
273 None => Self::MAX,
274 }
275 }
276}
277
278#[doc = concat!("(Signed integers only.) ", impl_desc!())]
279impl<const N: usize, const B: usize, const OM: u8> Int<N, B, OM> {
280 /// Saturating addition with an unsigned integer of the same bit width. Computes `self + rhs`, returning `Self::MAX` if the result is too large to be represented by `Self`.
281 ///
282 /// # Examples
283 ///
284 /// Basic usage:
285 ///
286 /// ```
287 /// use bnum::prelude::*;
288 /// use bnum::types::{I512, U512};
289 ///
290 /// assert_eq!(n!(-1I512).saturating_add_unsigned(n!(1)), n!(0));
291 /// assert_eq!(n!(0I512).saturating_add_unsigned(U512::MAX), I512::MAX);
292 /// ```
293 #[must_use = doc::must_use_op!()]
294 #[inline]
295 pub const fn saturating_add_unsigned(self, rhs: Uint<N, B, OM>) -> Self {
296 match self.checked_add_unsigned(rhs) {
297 Some(i) => i,
298 None => Self::MAX,
299 }
300 }
301
302 /// Saturating subtraction with an unsigned integer of the same bit width. Computes `self + rhs`, returning `Self::MIN` if the result is too small to be represented by `Self`.
303 ///
304 /// # Examples
305 ///
306 /// Basic usage:
307 ///
308 /// ```
309 /// use bnum::prelude::*;
310 /// use bnum::types::I1024;
311 ///
312 /// assert_eq!(n!(1I1024).saturating_sub_unsigned(n!(1)), n!(0));
313 /// assert_eq!(I1024::MIN.saturating_sub_unsigned(n!(1)), I1024::MIN);
314 /// ```
315 #[must_use = doc::must_use_op!()]
316 #[inline]
317 pub const fn saturating_sub_unsigned(self, rhs: Uint<N, B, OM>) -> Self {
318 match self.checked_sub_unsigned(rhs) {
319 Some(i) => i,
320 None => Self::MIN,
321 }
322 }
323
324 /// Computes the absolute value of `self`, returning [`Self::MAX`] if the result is too large to be represented by `Self`. The only time this can happen is if `self` is [`Self::MIN`].
325 ///
326 /// # Examples
327 ///
328 /// ```
329 /// use bnum::prelude::*;
330 /// use bnum::types::I2048;
331 ///
332 /// assert_eq!(n!(-7I2048).saturating_abs(), n!(7));
333 /// assert_eq!(n!(22I2048).saturating_abs(), n!(22));
334 /// assert_eq!(I2048::MIN.saturating_abs(), I2048::MAX);
335 /// ```
336 #[must_use = doc::must_use_op!()]
337 #[inline]
338 pub const fn saturating_abs(self) -> Self {
339 match self.checked_abs() {
340 Some(abs) => abs,
341 None => Self::MAX,
342 }
343 }
344
345 /// Saturating negation. Computes `-self`, returning [`Self::MAX`] if the result is too large to be represented by `Self`. The only time this can happen is if `self` is [`Self::MIN`].
346 ///
347 /// # Examples
348 ///
349 /// ```
350 /// use bnum::prelude::*;
351 /// use bnum::types::I256;
352 ///
353 /// assert_eq!(n!(7I256).saturating_neg(), n!(-7));
354 /// assert_eq!(n!(-22I256).saturating_neg(), n!(22));
355 /// assert_eq!(I256::MIN.saturating_neg(), I256::MAX);
356 /// ```
357 #[must_use = doc::must_use_op!()]
358 #[inline]
359 pub const fn saturating_neg(self) -> Self {
360 match self.checked_neg() {
361 Some(abs) => abs,
362 None => Self::MAX,
363 }
364 }
365}
366
367#[cfg(test)]
368mod tests {
369 use crate::test::test_bignum;
370
371 crate::test::test_all! {
372 testing unsigned;
373
374 test_bignum! {
375 function: <utest>::saturating_add_signed(a: utest, b: itest)
376 }
377 test_bignum! {
378 function: <utest>::saturating_sub_signed(a: utest, b: itest)
379 }
380 }
381 crate::test::test_all! {
382 testing signed;
383
384 test_bignum! {
385 function: <itest>::saturating_add_unsigned(a: itest, b: utest)
386 }
387 test_bignum! {
388 function: <itest>::saturating_sub_unsigned(a: itest, b: utest)
389 }
390 test_bignum! {
391 function: <itest>::saturating_neg(a: itest),
392 cases: [
393 (itest::MIN)
394 ]
395 }
396 test_bignum! {
397 function: <itest>::saturating_abs(a: itest),
398 cases: [
399 (itest::MIN)
400 ]
401 }
402 }
403 crate::test::test_all! {
404 testing integers;
405
406 test_bignum! {
407 function: <stest>::saturating_add(a: stest, b: stest)
408 }
409 test_bignum! {
410 function: <stest>::saturating_sub(a: stest, b: stest)
411 }
412 test_bignum! {
413 function: <stest>::saturating_mul(a: stest, b: stest)
414 }
415 test_bignum! {
416 function: <stest>::saturating_div(a: stest, b: stest),
417 skip: b == 0
418 }
419 test_bignum! {
420 function: <stest>::saturating_pow(a: stest, b: u16)
421 }
422 }
423}