i256/uint/checked.rs
1//! Arithematic operations which only return a value if no overflow occurs.
2
3#[rustfmt::skip]
4macro_rules! define {
5 (
6 signed_type => $s_t:ty,
7 wide_type => $wide_t:ty,
8 see_type => $see_t:ty $(,)?
9 ) => {
10 $crate::shared::checked::define!(
11 type => $s_t,
12 wide_type => $wide_t,
13 see_type => $see_t,
14 );
15
16 /// Checked addition with a signed integer. Computes `self + rhs`,
17 /// returning `None` if overflow occurred.
18 #[doc = $crate::shared::docs::primitive_doc!($see_t, checked_add_signed)]
19 #[inline(always)]
20 #[must_use = $crate::shared::docs::must_use_copy_doc!()]
21 pub const fn checked_add_signed(self, rhs: $s_t) -> Option<Self> {
22 let (value, overflowed) = self.overflowing_add_signed(rhs);
23 if !overflowed {
24 Some(value)
25 } else {
26 None
27 }
28 }
29
30 /// Checked negation. Computes `-self`, returning `None` unless `self ==
31 /// 0`.
32 ///
33 /// Note that negating any positive integer will overflow.
34 #[doc = $crate::shared::docs::primitive_doc!($see_t, checked_neg)]
35 #[inline(always)]
36 #[must_use = $crate::shared::docs::must_use_copy_doc!()]
37 pub const fn checked_neg(self) -> Option<Self> {
38 if self.eq_const(Self::MIN) {
39 Some(self)
40 } else {
41 None
42 }
43 }
44
45 /// Returns the logarithm of the number with respect to an arbitrary base,
46 /// rounded down.
47 ///
48 /// Returns `None` if the number is zero, or if the base is not at least 2.
49 ///
50 /// This method might not be optimized owing to implementation details;
51 /// `checked_ilog2` can produce results more efficiently for base 2, and
52 /// `checked_ilog10` can produce results more efficiently for base 10.
53 #[doc = $crate::shared::docs::primitive_doc!($see_t, checked_ilog)]
54 #[inline(always)]
55 pub fn checked_ilog(self, base: Self) -> Option<u32> {
56 let zero = Self::from_u8(0);
57 if self == zero || base <= zero || self < base {
58 return None;
59 }
60
61 // Since base >= self, n >= 1
62 let mut n = 1;
63 let mut r = base;
64
65 // Optimization for 128+ bit wide integers.
66 if Self::BITS >= $crate::UWide::BITS {
67 // The following is a correct lower bound for ⌊log(base,self)⌋ because
68 //
69 // log(base,self) = log(2,self) / log(2,base)
70 // ≥ ⌊log(2,self)⌋ / (⌊log(2,base)⌋ + 1)
71 //
72 // hence
73 //
74 // ⌊log(base,self)⌋ ≥ ⌊ ⌊log(2,self)⌋ / (⌊log(2,base)⌋ + 1) ⌋ .
75 n = self.ilog2() / (base.ilog2() + 1);
76 r = base.pow(n);
77 }
78
79 while r <= self / base {
80 n += 1;
81 r *= base;
82 }
83 Some(n)
84 }
85
86 // FIXME: Stabilize when our MSRV goes to `1.67.0+`.
87 // /// Returns the base 10 logarithm of the number, rounded down.
88 // ///
89 // /// Returns `None` if the number is zero.
90 // #[inline(always)]
91 // pub fn checked_ilog10(self) -> Option<u32> {
92 // match self.eq_const(Self::from_u8(0)) {
93 // true => None,
94 // false => {
95 // // NOTE: The `ilog10` implementations for small
96 // // numbers are quite efficient, so we use those
97 // // when available. We want to get this to
98 // // a 128-bit integer in as few multiplications
99 // // as we can.
100 // let mut log = 0;
101 // let mut value = self;
102 // const E16: u64 = 10_000_000_000_000_000;
103 // while value.high() > 0 {
104 // value = value.div_wide(E16);
105 // log += 16;
106 // }
107 // let value: u128 = value.as_u128();
108 // Some(value.ilog10() + log)
109 // },
110 // }
111 // }
112
113 /// Calculates the smallest value greater than or equal to `self` that
114 /// is a multiple of `rhs`. Returns `None` if `rhs` is zero or the
115 /// operation would result in overflow.
116 #[doc = $crate::shared::docs::primitive_doc!($see_t, checked_next_multiple_of)]
117 #[inline]
118 #[must_use = $crate::shared::docs::must_use_copy_doc!()]
119 pub fn checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
120 match self.checked_rem(rhs) {
121 None => None,
122 Some(Self::MIN) => Some(self),
123 // rhs - r cannot overflow because r is smaller than rhs
124 Some(r) => self.checked_add(rhs.wrapping_sub(r)),
125 }
126 }
127
128 /// Checked subtraction with a signed integer. Computes `self - rhs`,
129 /// returning `None` if overflow occurred.
130 #[inline]
131 #[must_use = $crate::shared::docs::must_use_copy_doc!()]
132 pub const fn checked_signed_diff(self, rhs: Self) -> Option<$s_t> {
133 let res = self.wrapping_sub(rhs).as_signed();
134 let overflow = self.ge_const(rhs) == res.lt_const(<$s_t>::from_u8(0));
135
136 if !overflow {
137 Some(res)
138 } else {
139 None
140 }
141 }
142
143 /// Returns the smallest power of two greater than or equal to `self`. If
144 /// the next power of two is greater than the type's maximum value,
145 /// `None` is returned, otherwise the power of two is wrapped in `Some`.
146 #[doc = $crate::shared::docs::primitive_doc!($see_t, checked_next_power_of_two)]
147 #[inline]
148 #[must_use = $crate::shared::docs::must_use_copy_doc!()]
149 pub const fn checked_next_power_of_two(self) -> Option<Self> {
150 self.one_less_than_next_power_of_two().checked_add(Self::from_u8(1))
151 }
152 };
153}
154
155pub(crate) use define;