]>
Commit | Line | Data |
---|---|---|
1b1a35ee XL |
1 | //! Definitions of integer that is known not to equal zero. |
2 | ||
3 | use crate::fmt; | |
5869c6ff | 4 | use crate::ops::{BitOr, BitOrAssign, Div, Rem}; |
1b1a35ee XL |
5 | use crate::str::FromStr; |
6 | ||
7 | use super::from_str_radix; | |
8 | use super::{IntErrorKind, ParseIntError}; | |
fc512014 | 9 | use crate::intrinsics; |
1b1a35ee | 10 | |
1b1a35ee XL |
11 | macro_rules! impl_nonzero_fmt { |
12 | ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { | |
13 | $( | |
14 | #[$stability] | |
15 | impl fmt::$Trait for $Ty { | |
16 | #[inline] | |
17 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
18 | self.get().fmt(f) | |
19 | } | |
20 | } | |
21 | )+ | |
22 | } | |
23 | } | |
24 | ||
25 | macro_rules! nonzero_integers { | |
cdc7bbd5 | 26 | ( $( #[$stability: meta] #[$const_new_unchecked_stability: meta] $Ty: ident($Int: ty); )+ ) => { |
1b1a35ee | 27 | $( |
5869c6ff XL |
28 | /// An integer that is known not to equal zero. |
29 | /// | |
30 | /// This enables some memory layout optimization. | |
31 | #[doc = concat!("For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:")] | |
32 | /// | |
33 | /// ```rust | |
34 | /// use std::mem::size_of; | |
35 | #[doc = concat!("assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int), ">());")] | |
36 | /// ``` | |
37 | #[$stability] | |
38 | #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] | |
39 | #[repr(transparent)] | |
40 | #[rustc_layout_scalar_valid_range_start(1)] | |
41 | #[rustc_nonnull_optimization_guaranteed] | |
064997fb | 42 | #[rustc_diagnostic_item = stringify!($Ty)] |
5869c6ff | 43 | pub struct $Ty($Int); |
1b1a35ee XL |
44 | |
45 | impl $Ty { | |
136023e0 XL |
46 | /// Creates a non-zero without checking whether the value is non-zero. |
47 | /// This results in undefined behaviour if the value is zero. | |
1b1a35ee XL |
48 | /// |
49 | /// # Safety | |
50 | /// | |
51 | /// The value must not be zero. | |
52 | #[$stability] | |
cdc7bbd5 | 53 | #[$const_new_unchecked_stability] |
c295e0f8 | 54 | #[must_use] |
1b1a35ee XL |
55 | #[inline] |
56 | pub const unsafe fn new_unchecked(n: $Int) -> Self { | |
57 | // SAFETY: this is guaranteed to be safe by the caller. | |
5e7ed085 | 58 | unsafe { |
2b03887a FG |
59 | core::intrinsics::assert_unsafe_precondition!( |
60 | concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument"), | |
61 | (n: $Int) => n != 0 | |
62 | ); | |
5e7ed085 FG |
63 | Self(n) |
64 | } | |
1b1a35ee XL |
65 | } |
66 | ||
67 | /// Creates a non-zero if the given value is not zero. | |
68 | #[$stability] | |
69 | #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] | |
c295e0f8 | 70 | #[must_use] |
1b1a35ee XL |
71 | #[inline] |
72 | pub const fn new(n: $Int) -> Option<Self> { | |
73 | if n != 0 { | |
74 | // SAFETY: we just checked that there's no `0` | |
75 | Some(unsafe { Self(n) }) | |
76 | } else { | |
77 | None | |
78 | } | |
79 | } | |
80 | ||
81 | /// Returns the value as a primitive type. | |
82 | #[$stability] | |
83 | #[inline] | |
5e7ed085 | 84 | #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] |
1b1a35ee XL |
85 | pub const fn get(self) -> $Int { |
86 | self.0 | |
87 | } | |
88 | ||
89 | } | |
90 | ||
91 | #[stable(feature = "from_nonzero", since = "1.31.0")] | |
3c0e092e XL |
92 | #[rustc_const_unstable(feature = "const_num_from_num", issue = "87852")] |
93 | impl const From<$Ty> for $Int { | |
5869c6ff XL |
94 | #[doc = concat!("Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`")] |
95 | #[inline] | |
96 | fn from(nonzero: $Ty) -> Self { | |
97 | nonzero.0 | |
1b1a35ee XL |
98 | } |
99 | } | |
100 | ||
101 | #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
3c0e092e XL |
102 | #[rustc_const_unstable(feature = "const_ops", issue = "90080")] |
103 | impl const BitOr for $Ty { | |
1b1a35ee XL |
104 | type Output = Self; |
105 | #[inline] | |
106 | fn bitor(self, rhs: Self) -> Self::Output { | |
107 | // SAFETY: since `self` and `rhs` are both nonzero, the | |
108 | // result of the bitwise-or will be nonzero. | |
109 | unsafe { $Ty::new_unchecked(self.get() | rhs.get()) } | |
110 | } | |
111 | } | |
112 | ||
113 | #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
3c0e092e XL |
114 | #[rustc_const_unstable(feature = "const_ops", issue = "90080")] |
115 | impl const BitOr<$Int> for $Ty { | |
1b1a35ee XL |
116 | type Output = Self; |
117 | #[inline] | |
118 | fn bitor(self, rhs: $Int) -> Self::Output { | |
119 | // SAFETY: since `self` is nonzero, the result of the | |
120 | // bitwise-or will be nonzero regardless of the value of | |
121 | // `rhs`. | |
122 | unsafe { $Ty::new_unchecked(self.get() | rhs) } | |
123 | } | |
124 | } | |
125 | ||
126 | #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
3c0e092e XL |
127 | #[rustc_const_unstable(feature = "const_ops", issue = "90080")] |
128 | impl const BitOr<$Ty> for $Int { | |
1b1a35ee XL |
129 | type Output = $Ty; |
130 | #[inline] | |
131 | fn bitor(self, rhs: $Ty) -> Self::Output { | |
132 | // SAFETY: since `rhs` is nonzero, the result of the | |
133 | // bitwise-or will be nonzero regardless of the value of | |
134 | // `self`. | |
135 | unsafe { $Ty::new_unchecked(self | rhs.get()) } | |
136 | } | |
137 | } | |
138 | ||
139 | #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
3c0e092e XL |
140 | #[rustc_const_unstable(feature = "const_ops", issue = "90080")] |
141 | impl const BitOrAssign for $Ty { | |
1b1a35ee XL |
142 | #[inline] |
143 | fn bitor_assign(&mut self, rhs: Self) { | |
144 | *self = *self | rhs; | |
145 | } | |
146 | } | |
147 | ||
148 | #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
3c0e092e XL |
149 | #[rustc_const_unstable(feature = "const_ops", issue = "90080")] |
150 | impl const BitOrAssign<$Int> for $Ty { | |
1b1a35ee XL |
151 | #[inline] |
152 | fn bitor_assign(&mut self, rhs: $Int) { | |
153 | *self = *self | rhs; | |
154 | } | |
155 | } | |
156 | ||
157 | impl_nonzero_fmt! { | |
158 | #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty | |
159 | } | |
160 | )+ | |
161 | } | |
162 | } | |
163 | ||
164 | nonzero_integers! { | |
cdc7bbd5 XL |
165 | #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); |
166 | #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); | |
167 | #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); | |
168 | #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); | |
169 | #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); | |
170 | #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); | |
171 | #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); | |
172 | #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); | |
173 | #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); | |
174 | #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); | |
175 | #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); | |
176 | #[stable(feature = "signed_nonzero", since = "1.34.0")] #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); | |
1b1a35ee XL |
177 | } |
178 | ||
179 | macro_rules! from_str_radix_nzint_impl { | |
180 | ($($t:ty)*) => {$( | |
181 | #[stable(feature = "nonzero_parse", since = "1.35.0")] | |
182 | impl FromStr for $t { | |
183 | type Err = ParseIntError; | |
184 | fn from_str(src: &str) -> Result<Self, Self::Err> { | |
185 | Self::new(from_str_radix(src, 10)?) | |
186 | .ok_or(ParseIntError { | |
187 | kind: IntErrorKind::Zero | |
188 | }) | |
189 | } | |
190 | } | |
191 | )*} | |
192 | } | |
193 | ||
194 | from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize | |
195 | NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } | |
fc512014 XL |
196 | |
197 | macro_rules! nonzero_leading_trailing_zeros { | |
198 | ( $( $Ty: ident($Uint: ty) , $LeadingTestExpr:expr ;)+ ) => { | |
199 | $( | |
200 | impl $Ty { | |
5869c6ff XL |
201 | /// Returns the number of leading zeros in the binary representation of `self`. |
202 | /// | |
203 | /// On many architectures, this function can perform better than `leading_zeros()` on the underlying integer type, as special handling of zero can be avoided. | |
204 | /// | |
205 | /// # Examples | |
206 | /// | |
207 | /// Basic usage: | |
208 | /// | |
209 | /// ``` | |
5869c6ff XL |
210 | #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(", stringify!($LeadingTestExpr), ").unwrap();")] |
211 | /// | |
212 | /// assert_eq!(n.leading_zeros(), 0); | |
213 | /// ``` | |
cdc7bbd5 XL |
214 | #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] |
215 | #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] | |
c295e0f8 XL |
216 | #[must_use = "this returns the result of the operation, \ |
217 | without modifying the original"] | |
5869c6ff XL |
218 | #[inline] |
219 | pub const fn leading_zeros(self) -> u32 { | |
064997fb | 220 | // SAFETY: since `self` cannot be zero, it is safe to call `ctlz_nonzero`. |
5869c6ff | 221 | unsafe { intrinsics::ctlz_nonzero(self.0 as $Uint) as u32 } |
fc512014 XL |
222 | } |
223 | ||
5869c6ff XL |
224 | /// Returns the number of trailing zeros in the binary representation |
225 | /// of `self`. | |
226 | /// | |
227 | /// On many architectures, this function can perform better than `trailing_zeros()` on the underlying integer type, as special handling of zero can be avoided. | |
228 | /// | |
229 | /// # Examples | |
230 | /// | |
231 | /// Basic usage: | |
232 | /// | |
233 | /// ``` | |
5869c6ff XL |
234 | #[doc = concat!("let n = std::num::", stringify!($Ty), "::new(0b0101000).unwrap();")] |
235 | /// | |
236 | /// assert_eq!(n.trailing_zeros(), 3); | |
237 | /// ``` | |
cdc7bbd5 XL |
238 | #[stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] |
239 | #[rustc_const_stable(feature = "nonzero_leading_trailing_zeros", since = "1.53.0")] | |
c295e0f8 XL |
240 | #[must_use = "this returns the result of the operation, \ |
241 | without modifying the original"] | |
5869c6ff XL |
242 | #[inline] |
243 | pub const fn trailing_zeros(self) -> u32 { | |
064997fb | 244 | // SAFETY: since `self` cannot be zero, it is safe to call `cttz_nonzero`. |
5869c6ff | 245 | unsafe { intrinsics::cttz_nonzero(self.0 as $Uint) as u32 } |
fc512014 XL |
246 | } |
247 | ||
248 | } | |
249 | )+ | |
250 | } | |
251 | } | |
252 | ||
253 | nonzero_leading_trailing_zeros! { | |
254 | NonZeroU8(u8), u8::MAX; | |
255 | NonZeroU16(u16), u16::MAX; | |
256 | NonZeroU32(u32), u32::MAX; | |
257 | NonZeroU64(u64), u64::MAX; | |
258 | NonZeroU128(u128), u128::MAX; | |
259 | NonZeroUsize(usize), usize::MAX; | |
260 | NonZeroI8(u8), -1i8; | |
261 | NonZeroI16(u16), -1i16; | |
262 | NonZeroI32(u32), -1i32; | |
263 | NonZeroI64(u64), -1i64; | |
264 | NonZeroI128(u128), -1i128; | |
265 | NonZeroIsize(usize), -1isize; | |
266 | } | |
5869c6ff XL |
267 | |
268 | macro_rules! nonzero_integers_div { | |
269 | ( $( $Ty: ident($Int: ty); )+ ) => { | |
270 | $( | |
271 | #[stable(feature = "nonzero_div", since = "1.51.0")] | |
3c0e092e XL |
272 | #[rustc_const_unstable(feature = "const_ops", issue = "90080")] |
273 | impl const Div<$Ty> for $Int { | |
5869c6ff XL |
274 | type Output = $Int; |
275 | /// This operation rounds towards zero, | |
276 | /// truncating any fractional part of the exact result, and cannot panic. | |
277 | #[inline] | |
278 | fn div(self, other: $Ty) -> $Int { | |
279 | // SAFETY: div by zero is checked because `other` is a nonzero, | |
280 | // and MIN/-1 is checked because `self` is an unsigned int. | |
281 | unsafe { crate::intrinsics::unchecked_div(self, other.get()) } | |
282 | } | |
283 | } | |
284 | ||
285 | #[stable(feature = "nonzero_div", since = "1.51.0")] | |
3c0e092e XL |
286 | #[rustc_const_unstable(feature = "const_ops", issue = "90080")] |
287 | impl const Rem<$Ty> for $Int { | |
5869c6ff XL |
288 | type Output = $Int; |
289 | /// This operation satisfies `n % d == n - (n / d) * d`, and cannot panic. | |
290 | #[inline] | |
291 | fn rem(self, other: $Ty) -> $Int { | |
292 | // SAFETY: rem by zero is checked because `other` is a nonzero, | |
293 | // and MIN/-1 is checked because `self` is an unsigned int. | |
294 | unsafe { crate::intrinsics::unchecked_rem(self, other.get()) } | |
295 | } | |
296 | } | |
297 | )+ | |
298 | } | |
299 | } | |
300 | ||
301 | nonzero_integers_div! { | |
302 | NonZeroU8(u8); | |
303 | NonZeroU16(u16); | |
304 | NonZeroU32(u32); | |
305 | NonZeroU64(u64); | |
306 | NonZeroU128(u128); | |
307 | NonZeroUsize(usize); | |
308 | } | |
309 | ||
136023e0 XL |
310 | // A bunch of methods for unsigned nonzero types only. |
311 | macro_rules! nonzero_unsigned_operations { | |
5099ac24 | 312 | ( $( $Ty: ident($Int: ident); )+ ) => { |
136023e0 XL |
313 | $( |
314 | impl $Ty { | |
f2b60f7d FG |
315 | /// Adds an unsigned integer to a non-zero value. |
316 | /// Checks for overflow and returns [`None`] on overflow. | |
136023e0 XL |
317 | /// As a consequence, the result cannot wrap to zero. |
318 | /// | |
319 | /// | |
320 | /// # Examples | |
321 | /// | |
322 | /// ``` | |
136023e0 | 323 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
324 | /// # fn main() { test().unwrap(); } |
325 | /// # fn test() -> Option<()> { | |
326 | #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] | |
327 | #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] | |
328 | #[doc = concat!("let max = ", stringify!($Ty), "::new(", | |
329 | stringify!($Int), "::MAX)?;")] | |
330 | /// | |
331 | /// assert_eq!(Some(two), one.checked_add(1)); | |
332 | /// assert_eq!(None, max.checked_add(1)); | |
333 | /// # Some(()) | |
334 | /// # } | |
335 | /// ``` | |
064997fb FG |
336 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
337 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
338 | #[must_use = "this returns the result of the operation, \ |
339 | without modifying the original"] | |
136023e0 XL |
340 | #[inline] |
341 | pub const fn checked_add(self, other: $Int) -> Option<$Ty> { | |
342 | if let Some(result) = self.get().checked_add(other) { | |
343 | // SAFETY: $Int::checked_add returns None on overflow | |
344 | // so the result cannot be zero. | |
345 | Some(unsafe { $Ty::new_unchecked(result) }) | |
346 | } else { | |
347 | None | |
348 | } | |
349 | } | |
350 | ||
f2b60f7d | 351 | /// Adds an unsigned integer to a non-zero value. |
136023e0 XL |
352 | #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")] |
353 | /// | |
354 | /// # Examples | |
355 | /// | |
356 | /// ``` | |
136023e0 | 357 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
358 | /// # fn main() { test().unwrap(); } |
359 | /// # fn test() -> Option<()> { | |
360 | #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] | |
361 | #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] | |
362 | #[doc = concat!("let max = ", stringify!($Ty), "::new(", | |
363 | stringify!($Int), "::MAX)?;")] | |
364 | /// | |
365 | /// assert_eq!(two, one.saturating_add(1)); | |
366 | /// assert_eq!(max, max.saturating_add(1)); | |
367 | /// # Some(()) | |
368 | /// # } | |
369 | /// ``` | |
064997fb FG |
370 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
371 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
372 | #[must_use = "this returns the result of the operation, \ |
373 | without modifying the original"] | |
136023e0 XL |
374 | #[inline] |
375 | pub const fn saturating_add(self, other: $Int) -> $Ty { | |
376 | // SAFETY: $Int::saturating_add returns $Int::MAX on overflow | |
377 | // so the result cannot be zero. | |
378 | unsafe { $Ty::new_unchecked(self.get().saturating_add(other)) } | |
379 | } | |
380 | ||
f2b60f7d | 381 | /// Adds an unsigned integer to a non-zero value, |
136023e0 XL |
382 | /// assuming overflow cannot occur. |
383 | /// Overflow is unchecked, and it is undefined behaviour to overflow | |
384 | /// *even if the result would wrap to a non-zero value*. | |
385 | /// The behaviour is undefined as soon as | |
386 | #[doc = concat!("`self + rhs > ", stringify!($Int), "::MAX`.")] | |
387 | /// | |
388 | /// # Examples | |
389 | /// | |
390 | /// ``` | |
391 | /// #![feature(nonzero_ops)] | |
136023e0 | 392 | /// |
487cf647 | 393 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
394 | /// # fn main() { test().unwrap(); } |
395 | /// # fn test() -> Option<()> { | |
396 | #[doc = concat!("let one = ", stringify!($Ty), "::new(1)?;")] | |
397 | #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] | |
398 | /// | |
399 | /// assert_eq!(two, unsafe { one.unchecked_add(1) }); | |
400 | /// # Some(()) | |
401 | /// # } | |
402 | /// ``` | |
403 | #[unstable(feature = "nonzero_ops", issue = "84186")] | |
c295e0f8 XL |
404 | #[must_use = "this returns the result of the operation, \ |
405 | without modifying the original"] | |
136023e0 | 406 | #[inline] |
c295e0f8 | 407 | pub const unsafe fn unchecked_add(self, other: $Int) -> $Ty { |
136023e0 XL |
408 | // SAFETY: The caller ensures there is no overflow. |
409 | unsafe { $Ty::new_unchecked(self.get().unchecked_add(other)) } | |
410 | } | |
411 | ||
412 | /// Returns the smallest power of two greater than or equal to n. | |
f2b60f7d | 413 | /// Checks for overflow and returns [`None`] |
136023e0 XL |
414 | /// if the next power of two is greater than the type’s maximum value. |
415 | /// As a consequence, the result cannot wrap to zero. | |
416 | /// | |
417 | /// # Examples | |
418 | /// | |
419 | /// ``` | |
136023e0 | 420 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
421 | /// # fn main() { test().unwrap(); } |
422 | /// # fn test() -> Option<()> { | |
423 | #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] | |
424 | #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] | |
425 | #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] | |
426 | #[doc = concat!("let max = ", stringify!($Ty), "::new(", | |
427 | stringify!($Int), "::MAX)?;")] | |
428 | /// | |
429 | /// assert_eq!(Some(two), two.checked_next_power_of_two() ); | |
430 | /// assert_eq!(Some(four), three.checked_next_power_of_two() ); | |
431 | /// assert_eq!(None, max.checked_next_power_of_two() ); | |
432 | /// # Some(()) | |
433 | /// # } | |
434 | /// ``` | |
064997fb FG |
435 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
436 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
437 | #[must_use = "this returns the result of the operation, \ |
438 | without modifying the original"] | |
136023e0 XL |
439 | #[inline] |
440 | pub const fn checked_next_power_of_two(self) -> Option<$Ty> { | |
441 | if let Some(nz) = self.get().checked_next_power_of_two() { | |
442 | // SAFETY: The next power of two is positive | |
443 | // and overflow is checked. | |
444 | Some(unsafe { $Ty::new_unchecked(nz) }) | |
445 | } else { | |
446 | None | |
447 | } | |
448 | } | |
5099ac24 FG |
449 | |
450 | /// Returns the base 2 logarithm of the number, rounded down. | |
451 | /// | |
452 | /// This is the same operation as | |
f2b60f7d | 453 | #[doc = concat!("[`", stringify!($Int), "::ilog2`],")] |
5099ac24 FG |
454 | /// except that it has no failure cases to worry about |
455 | /// since this value can never be zero. | |
456 | /// | |
457 | /// # Examples | |
458 | /// | |
459 | /// ``` | |
5099ac24 | 460 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
f2b60f7d FG |
461 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().ilog2(), 2);")] |
462 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().ilog2(), 3);")] | |
463 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().ilog2(), 3);")] | |
5099ac24 | 464 | /// ``` |
487cf647 FG |
465 | #[stable(feature = "int_log", since = "1.67.0")] |
466 | #[rustc_const_stable(feature = "int_log", since = "1.67.0")] | |
5099ac24 FG |
467 | #[must_use = "this returns the result of the operation, \ |
468 | without modifying the original"] | |
469 | #[inline] | |
f2b60f7d | 470 | pub const fn ilog2(self) -> u32 { |
5e7ed085 | 471 | Self::BITS - 1 - self.leading_zeros() |
5099ac24 FG |
472 | } |
473 | ||
474 | /// Returns the base 10 logarithm of the number, rounded down. | |
475 | /// | |
476 | /// This is the same operation as | |
f2b60f7d | 477 | #[doc = concat!("[`", stringify!($Int), "::ilog10`],")] |
5099ac24 FG |
478 | /// except that it has no failure cases to worry about |
479 | /// since this value can never be zero. | |
480 | /// | |
481 | /// # Examples | |
482 | /// | |
483 | /// ``` | |
5099ac24 | 484 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
f2b60f7d FG |
485 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().ilog10(), 1);")] |
486 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().ilog10(), 2);")] | |
487 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().ilog10(), 2);")] | |
5099ac24 | 488 | /// ``` |
487cf647 FG |
489 | #[stable(feature = "int_log", since = "1.67.0")] |
490 | #[rustc_const_stable(feature = "int_log", since = "1.67.0")] | |
5099ac24 FG |
491 | #[must_use = "this returns the result of the operation, \ |
492 | without modifying the original"] | |
493 | #[inline] | |
f2b60f7d | 494 | pub const fn ilog10(self) -> u32 { |
5099ac24 FG |
495 | super::int_log10::$Int(self.0) |
496 | } | |
136023e0 XL |
497 | } |
498 | )+ | |
499 | } | |
500 | } | |
501 | ||
502 | nonzero_unsigned_operations! { | |
503 | NonZeroU8(u8); | |
504 | NonZeroU16(u16); | |
505 | NonZeroU32(u32); | |
506 | NonZeroU64(u64); | |
507 | NonZeroU128(u128); | |
508 | NonZeroUsize(usize); | |
509 | } | |
510 | ||
511 | // A bunch of methods for signed nonzero types only. | |
512 | macro_rules! nonzero_signed_operations { | |
513 | ( $( $Ty: ident($Int: ty) -> $Uty: ident($Uint: ty); )+ ) => { | |
514 | $( | |
515 | impl $Ty { | |
516 | /// Computes the absolute value of self. | |
517 | #[doc = concat!("See [`", stringify!($Int), "::abs`]")] | |
518 | /// for documentation on overflow behaviour. | |
519 | /// | |
520 | /// # Example | |
521 | /// | |
522 | /// ``` | |
136023e0 | 523 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
524 | /// # fn main() { test().unwrap(); } |
525 | /// # fn test() -> Option<()> { | |
526 | #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] | |
527 | #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] | |
528 | /// | |
529 | /// assert_eq!(pos, pos.abs()); | |
530 | /// assert_eq!(pos, neg.abs()); | |
531 | /// # Some(()) | |
532 | /// # } | |
533 | /// ``` | |
064997fb FG |
534 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
535 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
536 | #[must_use = "this returns the result of the operation, \ |
537 | without modifying the original"] | |
136023e0 XL |
538 | #[inline] |
539 | pub const fn abs(self) -> $Ty { | |
540 | // SAFETY: This cannot overflow to zero. | |
541 | unsafe { $Ty::new_unchecked(self.get().abs()) } | |
542 | } | |
543 | ||
544 | /// Checked absolute value. | |
f2b60f7d | 545 | /// Checks for overflow and returns [`None`] if |
136023e0 XL |
546 | #[doc = concat!("`self == ", stringify!($Int), "::MIN`.")] |
547 | /// The result cannot be zero. | |
548 | /// | |
549 | /// # Example | |
550 | /// | |
551 | /// ``` | |
136023e0 | 552 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
553 | /// # fn main() { test().unwrap(); } |
554 | /// # fn test() -> Option<()> { | |
555 | #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] | |
556 | #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] | |
557 | #[doc = concat!("let min = ", stringify!($Ty), "::new(", | |
558 | stringify!($Int), "::MIN)?;")] | |
559 | /// | |
560 | /// assert_eq!(Some(pos), neg.checked_abs()); | |
561 | /// assert_eq!(None, min.checked_abs()); | |
562 | /// # Some(()) | |
563 | /// # } | |
564 | /// ``` | |
064997fb FG |
565 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
566 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
567 | #[must_use = "this returns the result of the operation, \ |
568 | without modifying the original"] | |
136023e0 XL |
569 | #[inline] |
570 | pub const fn checked_abs(self) -> Option<$Ty> { | |
571 | if let Some(nz) = self.get().checked_abs() { | |
572 | // SAFETY: absolute value of nonzero cannot yield zero values. | |
573 | Some(unsafe { $Ty::new_unchecked(nz) }) | |
574 | } else { | |
575 | None | |
576 | } | |
577 | } | |
578 | ||
579 | /// Computes the absolute value of self, | |
580 | /// with overflow information, see | |
581 | #[doc = concat!("[`", stringify!($Int), "::overflowing_abs`].")] | |
582 | /// | |
583 | /// # Example | |
584 | /// | |
585 | /// ``` | |
136023e0 | 586 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
587 | /// # fn main() { test().unwrap(); } |
588 | /// # fn test() -> Option<()> { | |
589 | #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] | |
590 | #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] | |
591 | #[doc = concat!("let min = ", stringify!($Ty), "::new(", | |
592 | stringify!($Int), "::MIN)?;")] | |
593 | /// | |
594 | /// assert_eq!((pos, false), pos.overflowing_abs()); | |
595 | /// assert_eq!((pos, false), neg.overflowing_abs()); | |
596 | /// assert_eq!((min, true), min.overflowing_abs()); | |
597 | /// # Some(()) | |
598 | /// # } | |
599 | /// ``` | |
064997fb FG |
600 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
601 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
602 | #[must_use = "this returns the result of the operation, \ |
603 | without modifying the original"] | |
136023e0 XL |
604 | #[inline] |
605 | pub const fn overflowing_abs(self) -> ($Ty, bool) { | |
606 | let (nz, flag) = self.get().overflowing_abs(); | |
607 | ( | |
608 | // SAFETY: absolute value of nonzero cannot yield zero values. | |
609 | unsafe { $Ty::new_unchecked(nz) }, | |
610 | flag, | |
611 | ) | |
612 | } | |
613 | ||
614 | /// Saturating absolute value, see | |
615 | #[doc = concat!("[`", stringify!($Int), "::saturating_abs`].")] | |
616 | /// | |
617 | /// # Example | |
618 | /// | |
619 | /// ``` | |
136023e0 | 620 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
621 | /// # fn main() { test().unwrap(); } |
622 | /// # fn test() -> Option<()> { | |
623 | #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] | |
624 | #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] | |
625 | #[doc = concat!("let min = ", stringify!($Ty), "::new(", | |
626 | stringify!($Int), "::MIN)?;")] | |
627 | #[doc = concat!("let min_plus = ", stringify!($Ty), "::new(", | |
628 | stringify!($Int), "::MIN + 1)?;")] | |
629 | #[doc = concat!("let max = ", stringify!($Ty), "::new(", | |
630 | stringify!($Int), "::MAX)?;")] | |
631 | /// | |
632 | /// assert_eq!(pos, pos.saturating_abs()); | |
633 | /// assert_eq!(pos, neg.saturating_abs()); | |
634 | /// assert_eq!(max, min.saturating_abs()); | |
635 | /// assert_eq!(max, min_plus.saturating_abs()); | |
636 | /// # Some(()) | |
637 | /// # } | |
638 | /// ``` | |
064997fb FG |
639 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
640 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
641 | #[must_use = "this returns the result of the operation, \ |
642 | without modifying the original"] | |
136023e0 XL |
643 | #[inline] |
644 | pub const fn saturating_abs(self) -> $Ty { | |
645 | // SAFETY: absolute value of nonzero cannot yield zero values. | |
646 | unsafe { $Ty::new_unchecked(self.get().saturating_abs()) } | |
647 | } | |
648 | ||
649 | /// Wrapping absolute value, see | |
650 | #[doc = concat!("[`", stringify!($Int), "::wrapping_abs`].")] | |
651 | /// | |
652 | /// # Example | |
653 | /// | |
654 | /// ``` | |
136023e0 | 655 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
656 | /// # fn main() { test().unwrap(); } |
657 | /// # fn test() -> Option<()> { | |
658 | #[doc = concat!("let pos = ", stringify!($Ty), "::new(1)?;")] | |
659 | #[doc = concat!("let neg = ", stringify!($Ty), "::new(-1)?;")] | |
660 | #[doc = concat!("let min = ", stringify!($Ty), "::new(", | |
661 | stringify!($Int), "::MIN)?;")] | |
487cf647 | 662 | #[doc = concat!("# let max = ", stringify!($Ty), "::new(", |
136023e0 XL |
663 | stringify!($Int), "::MAX)?;")] |
664 | /// | |
665 | /// assert_eq!(pos, pos.wrapping_abs()); | |
666 | /// assert_eq!(pos, neg.wrapping_abs()); | |
667 | /// assert_eq!(min, min.wrapping_abs()); | |
668 | /// # // FIXME: add once Neg is implemented? | |
669 | /// # // assert_eq!(max, (-max).wrapping_abs()); | |
670 | /// # Some(()) | |
671 | /// # } | |
672 | /// ``` | |
064997fb FG |
673 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
674 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
675 | #[must_use = "this returns the result of the operation, \ |
676 | without modifying the original"] | |
136023e0 XL |
677 | #[inline] |
678 | pub const fn wrapping_abs(self) -> $Ty { | |
679 | // SAFETY: absolute value of nonzero cannot yield zero values. | |
680 | unsafe { $Ty::new_unchecked(self.get().wrapping_abs()) } | |
681 | } | |
682 | ||
683 | /// Computes the absolute value of self | |
684 | /// without any wrapping or panicking. | |
685 | /// | |
686 | /// # Example | |
687 | /// | |
688 | /// ``` | |
136023e0 XL |
689 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
690 | #[doc = concat!("# use std::num::", stringify!($Uty), ";")] | |
691 | /// | |
692 | /// # fn main() { test().unwrap(); } | |
693 | /// # fn test() -> Option<()> { | |
694 | #[doc = concat!("let u_pos = ", stringify!($Uty), "::new(1)?;")] | |
695 | #[doc = concat!("let i_pos = ", stringify!($Ty), "::new(1)?;")] | |
696 | #[doc = concat!("let i_neg = ", stringify!($Ty), "::new(-1)?;")] | |
697 | #[doc = concat!("let i_min = ", stringify!($Ty), "::new(", | |
698 | stringify!($Int), "::MIN)?;")] | |
699 | #[doc = concat!("let u_max = ", stringify!($Uty), "::new(", | |
700 | stringify!($Uint), "::MAX / 2 + 1)?;")] | |
701 | /// | |
702 | /// assert_eq!(u_pos, i_pos.unsigned_abs()); | |
703 | /// assert_eq!(u_pos, i_neg.unsigned_abs()); | |
704 | /// assert_eq!(u_max, i_min.unsigned_abs()); | |
705 | /// # Some(()) | |
706 | /// # } | |
707 | /// ``` | |
064997fb FG |
708 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
709 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
710 | #[must_use = "this returns the result of the operation, \ |
711 | without modifying the original"] | |
136023e0 XL |
712 | #[inline] |
713 | pub const fn unsigned_abs(self) -> $Uty { | |
714 | // SAFETY: absolute value of nonzero cannot yield zero values. | |
715 | unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) } | |
716 | } | |
2b03887a FG |
717 | |
718 | /// Returns `true` if `self` is negative and `false` if the | |
719 | /// number is positive. | |
720 | /// | |
721 | /// # Example | |
722 | /// | |
723 | /// ``` | |
724 | /// #![feature(nonzero_negation_ops)] | |
725 | /// | |
726 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] | |
727 | /// # fn main() { test().unwrap(); } | |
728 | /// # fn test() -> Option<()> { | |
729 | #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] | |
730 | #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] | |
731 | /// | |
732 | /// assert!(neg_five.is_negative()); | |
733 | /// assert!(!pos_five.is_negative()); | |
734 | /// # Some(()) | |
735 | /// # } | |
736 | /// ``` | |
737 | #[must_use] | |
738 | #[inline] | |
739 | #[unstable(feature = "nonzero_negation_ops", issue = "102443")] | |
740 | pub const fn is_negative(self) -> bool { | |
741 | self.get().is_negative() | |
742 | } | |
743 | ||
744 | /// Checked negation. Computes `-self`, returning `None` if `self == i32::MIN`. | |
745 | /// | |
746 | /// # Example | |
747 | /// | |
748 | /// ``` | |
749 | /// #![feature(nonzero_negation_ops)] | |
750 | /// | |
751 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] | |
752 | /// # fn main() { test().unwrap(); } | |
753 | /// # fn test() -> Option<()> { | |
754 | #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] | |
755 | #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] | |
756 | #[doc = concat!("let min = ", stringify!($Ty), "::new(", | |
757 | stringify!($Int), "::MIN)?;")] | |
758 | /// | |
759 | /// assert_eq!(pos_five.checked_neg(), Some(neg_five)); | |
760 | /// assert_eq!(min.checked_neg(), None); | |
761 | /// # Some(()) | |
762 | /// # } | |
763 | /// ``` | |
764 | #[inline] | |
765 | #[unstable(feature = "nonzero_negation_ops", issue = "102443")] | |
766 | pub const fn checked_neg(self) -> Option<$Ty> { | |
767 | if let Some(result) = self.get().checked_neg() { | |
768 | // SAFETY: negation of nonzero cannot yield zero values. | |
769 | return Some(unsafe { $Ty::new_unchecked(result) }); | |
770 | } | |
771 | None | |
772 | } | |
773 | ||
774 | /// Negates self, overflowing if this is equal to the minimum value. | |
775 | /// | |
776 | #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")] | |
777 | /// for documentation on overflow behaviour. | |
778 | /// | |
779 | /// # Example | |
780 | /// | |
781 | /// ``` | |
782 | /// #![feature(nonzero_negation_ops)] | |
783 | /// | |
784 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] | |
785 | /// # fn main() { test().unwrap(); } | |
786 | /// # fn test() -> Option<()> { | |
787 | #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] | |
788 | #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] | |
789 | #[doc = concat!("let min = ", stringify!($Ty), "::new(", | |
790 | stringify!($Int), "::MIN)?;")] | |
791 | /// | |
792 | /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false)); | |
793 | /// assert_eq!(min.overflowing_neg(), (min, true)); | |
794 | /// # Some(()) | |
795 | /// # } | |
796 | /// ``` | |
797 | #[inline] | |
798 | #[unstable(feature = "nonzero_negation_ops", issue = "102443")] | |
799 | pub const fn overflowing_neg(self) -> ($Ty, bool) { | |
800 | let (result, overflow) = self.get().overflowing_neg(); | |
801 | // SAFETY: negation of nonzero cannot yield zero values. | |
802 | ((unsafe { $Ty::new_unchecked(result) }), overflow) | |
803 | } | |
804 | ||
805 | /// Saturating negation. Computes `-self`, returning `MAX` if | |
806 | /// `self == i32::MIN` instead of overflowing. | |
807 | /// | |
808 | /// # Example | |
809 | /// | |
810 | /// ``` | |
811 | /// #![feature(nonzero_negation_ops)] | |
812 | /// | |
813 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] | |
814 | /// # fn main() { test().unwrap(); } | |
815 | /// # fn test() -> Option<()> { | |
816 | #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] | |
817 | #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] | |
818 | #[doc = concat!("let min = ", stringify!($Ty), "::new(", | |
819 | stringify!($Int), "::MIN)?;")] | |
820 | #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(", | |
821 | stringify!($Int), "::MIN + 1)?;")] | |
822 | #[doc = concat!("let max = ", stringify!($Ty), "::new(", | |
823 | stringify!($Int), "::MAX)?;")] | |
824 | /// | |
825 | /// assert_eq!(pos_five.saturating_neg(), neg_five); | |
826 | /// assert_eq!(min.saturating_neg(), max); | |
827 | /// assert_eq!(max.saturating_neg(), min_plus_one); | |
828 | /// # Some(()) | |
829 | /// # } | |
830 | /// ``` | |
831 | #[inline] | |
832 | #[unstable(feature = "nonzero_negation_ops", issue = "102443")] | |
833 | pub const fn saturating_neg(self) -> $Ty { | |
834 | if let Some(result) = self.checked_neg() { | |
835 | return result; | |
836 | } | |
837 | $Ty::MAX | |
838 | } | |
839 | ||
840 | /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary | |
841 | /// of the type. | |
842 | /// | |
843 | #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")] | |
844 | /// for documentation on overflow behaviour. | |
845 | /// | |
846 | /// # Example | |
847 | /// | |
848 | /// ``` | |
849 | /// #![feature(nonzero_negation_ops)] | |
850 | /// | |
851 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] | |
852 | /// # fn main() { test().unwrap(); } | |
853 | /// # fn test() -> Option<()> { | |
854 | #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")] | |
855 | #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")] | |
856 | #[doc = concat!("let min = ", stringify!($Ty), "::new(", | |
857 | stringify!($Int), "::MIN)?;")] | |
858 | /// | |
859 | /// assert_eq!(pos_five.wrapping_neg(), neg_five); | |
860 | /// assert_eq!(min.wrapping_neg(), min); | |
861 | /// # Some(()) | |
862 | /// # } | |
863 | /// ``` | |
864 | #[inline] | |
865 | #[unstable(feature = "nonzero_negation_ops", issue = "102443")] | |
866 | pub const fn wrapping_neg(self) -> $Ty { | |
867 | let result = self.get().wrapping_neg(); | |
868 | // SAFETY: negation of nonzero cannot yield zero values. | |
869 | unsafe { $Ty::new_unchecked(result) } | |
870 | } | |
136023e0 XL |
871 | } |
872 | )+ | |
873 | } | |
874 | } | |
875 | ||
876 | nonzero_signed_operations! { | |
877 | NonZeroI8(i8) -> NonZeroU8(u8); | |
878 | NonZeroI16(i16) -> NonZeroU16(u16); | |
879 | NonZeroI32(i32) -> NonZeroU32(u32); | |
880 | NonZeroI64(i64) -> NonZeroU64(u64); | |
881 | NonZeroI128(i128) -> NonZeroU128(u128); | |
882 | NonZeroIsize(isize) -> NonZeroUsize(usize); | |
883 | } | |
884 | ||
885 | // A bunch of methods for both signed and unsigned nonzero types. | |
886 | macro_rules! nonzero_unsigned_signed_operations { | |
887 | ( $( $signedness:ident $Ty: ident($Int: ty); )+ ) => { | |
888 | $( | |
889 | impl $Ty { | |
f2b60f7d FG |
890 | /// Multiplies two non-zero integers together. |
891 | /// Checks for overflow and returns [`None`] on overflow. | |
136023e0 XL |
892 | /// As a consequence, the result cannot wrap to zero. |
893 | /// | |
894 | /// # Examples | |
895 | /// | |
896 | /// ``` | |
136023e0 | 897 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
898 | /// # fn main() { test().unwrap(); } |
899 | /// # fn test() -> Option<()> { | |
900 | #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] | |
901 | #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] | |
902 | #[doc = concat!("let max = ", stringify!($Ty), "::new(", | |
903 | stringify!($Int), "::MAX)?;")] | |
904 | /// | |
905 | /// assert_eq!(Some(four), two.checked_mul(two)); | |
906 | /// assert_eq!(None, max.checked_mul(two)); | |
907 | /// # Some(()) | |
908 | /// # } | |
909 | /// ``` | |
064997fb FG |
910 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
911 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
912 | #[must_use = "this returns the result of the operation, \ |
913 | without modifying the original"] | |
136023e0 XL |
914 | #[inline] |
915 | pub const fn checked_mul(self, other: $Ty) -> Option<$Ty> { | |
916 | if let Some(result) = self.get().checked_mul(other.get()) { | |
917 | // SAFETY: checked_mul returns None on overflow | |
918 | // and `other` is also non-null | |
919 | // so the result cannot be zero. | |
920 | Some(unsafe { $Ty::new_unchecked(result) }) | |
921 | } else { | |
922 | None | |
923 | } | |
924 | } | |
925 | ||
f2b60f7d | 926 | /// Multiplies two non-zero integers together. |
136023e0 XL |
927 | #[doc = concat!("Return [`", stringify!($Int), "::MAX`] on overflow.")] |
928 | /// | |
929 | /// # Examples | |
930 | /// | |
931 | /// ``` | |
136023e0 | 932 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
933 | /// # fn main() { test().unwrap(); } |
934 | /// # fn test() -> Option<()> { | |
935 | #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] | |
936 | #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] | |
937 | #[doc = concat!("let max = ", stringify!($Ty), "::new(", | |
938 | stringify!($Int), "::MAX)?;")] | |
939 | /// | |
940 | /// assert_eq!(four, two.saturating_mul(two)); | |
941 | /// assert_eq!(max, four.saturating_mul(max)); | |
942 | /// # Some(()) | |
943 | /// # } | |
944 | /// ``` | |
064997fb FG |
945 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
946 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
947 | #[must_use = "this returns the result of the operation, \ |
948 | without modifying the original"] | |
136023e0 XL |
949 | #[inline] |
950 | pub const fn saturating_mul(self, other: $Ty) -> $Ty { | |
951 | // SAFETY: saturating_mul returns u*::MAX on overflow | |
952 | // and `other` is also non-null | |
953 | // so the result cannot be zero. | |
954 | unsafe { $Ty::new_unchecked(self.get().saturating_mul(other.get())) } | |
955 | } | |
956 | ||
f2b60f7d | 957 | /// Multiplies two non-zero integers together, |
136023e0 XL |
958 | /// assuming overflow cannot occur. |
959 | /// Overflow is unchecked, and it is undefined behaviour to overflow | |
960 | /// *even if the result would wrap to a non-zero value*. | |
961 | /// The behaviour is undefined as soon as | |
962 | #[doc = sign_dependent_expr!{ | |
963 | $signedness ? | |
964 | if signed { | |
965 | concat!("`self * rhs > ", stringify!($Int), "::MAX`, ", | |
966 | "or `self * rhs < ", stringify!($Int), "::MIN`.") | |
967 | } | |
968 | if unsigned { | |
969 | concat!("`self * rhs > ", stringify!($Int), "::MAX`.") | |
970 | } | |
971 | }] | |
972 | /// | |
973 | /// # Examples | |
974 | /// | |
975 | /// ``` | |
976 | /// #![feature(nonzero_ops)] | |
136023e0 | 977 | /// |
487cf647 | 978 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
979 | /// # fn main() { test().unwrap(); } |
980 | /// # fn test() -> Option<()> { | |
981 | #[doc = concat!("let two = ", stringify!($Ty), "::new(2)?;")] | |
982 | #[doc = concat!("let four = ", stringify!($Ty), "::new(4)?;")] | |
983 | /// | |
984 | /// assert_eq!(four, unsafe { two.unchecked_mul(two) }); | |
985 | /// # Some(()) | |
986 | /// # } | |
987 | /// ``` | |
988 | #[unstable(feature = "nonzero_ops", issue = "84186")] | |
c295e0f8 XL |
989 | #[must_use = "this returns the result of the operation, \ |
990 | without modifying the original"] | |
136023e0 | 991 | #[inline] |
c295e0f8 | 992 | pub const unsafe fn unchecked_mul(self, other: $Ty) -> $Ty { |
136023e0 XL |
993 | // SAFETY: The caller ensures there is no overflow. |
994 | unsafe { $Ty::new_unchecked(self.get().unchecked_mul(other.get())) } | |
995 | } | |
996 | ||
f2b60f7d FG |
997 | /// Raises non-zero value to an integer power. |
998 | /// Checks for overflow and returns [`None`] on overflow. | |
136023e0 XL |
999 | /// As a consequence, the result cannot wrap to zero. |
1000 | /// | |
1001 | /// # Examples | |
1002 | /// | |
1003 | /// ``` | |
136023e0 | 1004 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
1005 | /// # fn main() { test().unwrap(); } |
1006 | /// # fn test() -> Option<()> { | |
1007 | #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] | |
1008 | #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] | |
1009 | #[doc = concat!("let half_max = ", stringify!($Ty), "::new(", | |
1010 | stringify!($Int), "::MAX / 2)?;")] | |
1011 | /// | |
1012 | /// assert_eq!(Some(twenty_seven), three.checked_pow(3)); | |
1013 | /// assert_eq!(None, half_max.checked_pow(3)); | |
1014 | /// # Some(()) | |
1015 | /// # } | |
1016 | /// ``` | |
064997fb FG |
1017 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
1018 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
1019 | #[must_use = "this returns the result of the operation, \ |
1020 | without modifying the original"] | |
136023e0 XL |
1021 | #[inline] |
1022 | pub const fn checked_pow(self, other: u32) -> Option<$Ty> { | |
1023 | if let Some(result) = self.get().checked_pow(other) { | |
1024 | // SAFETY: checked_pow returns None on overflow | |
1025 | // so the result cannot be zero. | |
1026 | Some(unsafe { $Ty::new_unchecked(result) }) | |
1027 | } else { | |
1028 | None | |
1029 | } | |
1030 | } | |
1031 | ||
1032 | /// Raise non-zero value to an integer power. | |
1033 | #[doc = sign_dependent_expr!{ | |
1034 | $signedness ? | |
1035 | if signed { | |
1036 | concat!("Return [`", stringify!($Int), "::MIN`] ", | |
1037 | "or [`", stringify!($Int), "::MAX`] on overflow.") | |
1038 | } | |
1039 | if unsigned { | |
1040 | concat!("Return [`", stringify!($Int), "::MAX`] on overflow.") | |
1041 | } | |
1042 | }] | |
1043 | /// | |
1044 | /// # Examples | |
1045 | /// | |
1046 | /// ``` | |
136023e0 | 1047 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
136023e0 XL |
1048 | /// # fn main() { test().unwrap(); } |
1049 | /// # fn test() -> Option<()> { | |
1050 | #[doc = concat!("let three = ", stringify!($Ty), "::new(3)?;")] | |
1051 | #[doc = concat!("let twenty_seven = ", stringify!($Ty), "::new(27)?;")] | |
1052 | #[doc = concat!("let max = ", stringify!($Ty), "::new(", | |
1053 | stringify!($Int), "::MAX)?;")] | |
1054 | /// | |
1055 | /// assert_eq!(twenty_seven, three.saturating_pow(3)); | |
1056 | /// assert_eq!(max, max.saturating_pow(3)); | |
1057 | /// # Some(()) | |
1058 | /// # } | |
1059 | /// ``` | |
064997fb FG |
1060 | #[stable(feature = "nonzero_checked_ops", since = "1.64.0")] |
1061 | #[rustc_const_stable(feature = "const_nonzero_checked_ops", since = "1.64.0")] | |
c295e0f8 XL |
1062 | #[must_use = "this returns the result of the operation, \ |
1063 | without modifying the original"] | |
136023e0 XL |
1064 | #[inline] |
1065 | pub const fn saturating_pow(self, other: u32) -> $Ty { | |
1066 | // SAFETY: saturating_pow returns u*::MAX on overflow | |
1067 | // so the result cannot be zero. | |
1068 | unsafe { $Ty::new_unchecked(self.get().saturating_pow(other)) } | |
1069 | } | |
1070 | } | |
1071 | )+ | |
1072 | } | |
1073 | } | |
1074 | ||
1075 | // Use this when the generated code should differ between signed and unsigned types. | |
1076 | macro_rules! sign_dependent_expr { | |
1077 | (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { | |
1078 | $signed_case | |
1079 | }; | |
1080 | (unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => { | |
1081 | $unsigned_case | |
1082 | }; | |
1083 | } | |
1084 | ||
1085 | nonzero_unsigned_signed_operations! { | |
1086 | unsigned NonZeroU8(u8); | |
1087 | unsigned NonZeroU16(u16); | |
1088 | unsigned NonZeroU32(u32); | |
1089 | unsigned NonZeroU64(u64); | |
1090 | unsigned NonZeroU128(u128); | |
1091 | unsigned NonZeroUsize(usize); | |
1092 | signed NonZeroI8(i8); | |
1093 | signed NonZeroI16(i16); | |
1094 | signed NonZeroI32(i32); | |
1095 | signed NonZeroI64(i64); | |
1096 | signed NonZeroI128(i128); | |
1097 | signed NonZeroIsize(isize); | |
1098 | } | |
1099 | ||
5869c6ff XL |
1100 | macro_rules! nonzero_unsigned_is_power_of_two { |
1101 | ( $( $Ty: ident )+ ) => { | |
1102 | $( | |
1103 | impl $Ty { | |
1104 | ||
1105 | /// Returns `true` if and only if `self == (1 << k)` for some `k`. | |
1106 | /// | |
1107 | /// On many architectures, this function can perform better than `is_power_of_two()` | |
1108 | /// on the underlying integer type, as special handling of zero can be avoided. | |
1109 | /// | |
1110 | /// # Examples | |
1111 | /// | |
1112 | /// Basic usage: | |
1113 | /// | |
1114 | /// ``` | |
5869c6ff XL |
1115 | #[doc = concat!("let eight = std::num::", stringify!($Ty), "::new(8).unwrap();")] |
1116 | /// assert!(eight.is_power_of_two()); | |
1117 | #[doc = concat!("let ten = std::num::", stringify!($Ty), "::new(10).unwrap();")] | |
1118 | /// assert!(!ten.is_power_of_two()); | |
1119 | /// ``` | |
c295e0f8 | 1120 | #[must_use] |
a2a8927a | 1121 | #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] |
5099ac24 | 1122 | #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] |
5869c6ff XL |
1123 | #[inline] |
1124 | pub const fn is_power_of_two(self) -> bool { | |
1125 | // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. | |
1126 | // On the basic x86-64 target, this saves 3 instructions for the zero check. | |
1127 | // On x86_64 with BMI1, being nonzero lets it codegen to `BLSR`, which saves an instruction | |
1128 | // compared to the `POPCNT` implementation on the underlying integer type. | |
1129 | ||
1130 | intrinsics::ctpop(self.get()) < 2 | |
1131 | } | |
1132 | ||
1133 | } | |
1134 | )+ | |
1135 | } | |
1136 | } | |
1137 | ||
1138 | nonzero_unsigned_is_power_of_two! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize } | |
5e7ed085 FG |
1139 | |
1140 | macro_rules! nonzero_min_max_unsigned { | |
1141 | ( $( $Ty: ident($Int: ident); )+ ) => { | |
1142 | $( | |
1143 | impl $Ty { | |
1144 | /// The smallest value that can be represented by this non-zero | |
1145 | /// integer type, 1. | |
1146 | /// | |
1147 | /// # Examples | |
1148 | /// | |
1149 | /// ``` | |
1150 | /// #![feature(nonzero_min_max)] | |
5e7ed085 | 1151 | /// |
487cf647 | 1152 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
5e7ed085 FG |
1153 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), 1", stringify!($Int), ");")] |
1154 | /// ``` | |
1155 | #[unstable(feature = "nonzero_min_max", issue = "89065")] | |
1156 | pub const MIN: Self = Self::new(1).unwrap(); | |
1157 | ||
1158 | /// The largest value that can be represented by this non-zero | |
1159 | /// integer type, | |
1160 | #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] | |
1161 | /// | |
1162 | /// # Examples | |
1163 | /// | |
1164 | /// ``` | |
1165 | /// #![feature(nonzero_min_max)] | |
5e7ed085 | 1166 | /// |
487cf647 | 1167 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
5e7ed085 FG |
1168 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] |
1169 | /// ``` | |
1170 | #[unstable(feature = "nonzero_min_max", issue = "89065")] | |
1171 | pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); | |
1172 | } | |
1173 | )+ | |
1174 | } | |
1175 | } | |
1176 | ||
1177 | macro_rules! nonzero_min_max_signed { | |
1178 | ( $( $Ty: ident($Int: ident); )+ ) => { | |
1179 | $( | |
1180 | impl $Ty { | |
1181 | /// The smallest value that can be represented by this non-zero | |
1182 | /// integer type, | |
1183 | #[doc = concat!("equal to [`", stringify!($Int), "::MIN`].")] | |
1184 | /// | |
1185 | /// Note: While most integer types are defined for every whole | |
1186 | /// number between `MIN` and `MAX`, signed non-zero integers are | |
1187 | /// a special case. They have a "gap" at 0. | |
1188 | /// | |
1189 | /// # Examples | |
1190 | /// | |
1191 | /// ``` | |
1192 | /// #![feature(nonzero_min_max)] | |
5e7ed085 | 1193 | /// |
487cf647 | 1194 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
5e7ed085 FG |
1195 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::MIN.get(), ", stringify!($Int), "::MIN);")] |
1196 | /// ``` | |
1197 | #[unstable(feature = "nonzero_min_max", issue = "89065")] | |
1198 | pub const MIN: Self = Self::new(<$Int>::MIN).unwrap(); | |
1199 | ||
1200 | /// The largest value that can be represented by this non-zero | |
1201 | /// integer type, | |
1202 | #[doc = concat!("equal to [`", stringify!($Int), "::MAX`].")] | |
1203 | /// | |
1204 | /// Note: While most integer types are defined for every whole | |
1205 | /// number between `MIN` and `MAX`, signed non-zero integers are | |
1206 | /// a special case. They have a "gap" at 0. | |
1207 | /// | |
1208 | /// # Examples | |
1209 | /// | |
1210 | /// ``` | |
1211 | /// #![feature(nonzero_min_max)] | |
5e7ed085 | 1212 | /// |
487cf647 | 1213 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
5e7ed085 FG |
1214 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::MAX.get(), ", stringify!($Int), "::MAX);")] |
1215 | /// ``` | |
1216 | #[unstable(feature = "nonzero_min_max", issue = "89065")] | |
1217 | pub const MAX: Self = Self::new(<$Int>::MAX).unwrap(); | |
1218 | } | |
1219 | )+ | |
1220 | } | |
1221 | } | |
1222 | ||
1223 | nonzero_min_max_unsigned! { | |
1224 | NonZeroU8(u8); | |
1225 | NonZeroU16(u16); | |
1226 | NonZeroU32(u32); | |
1227 | NonZeroU64(u64); | |
1228 | NonZeroU128(u128); | |
1229 | NonZeroUsize(usize); | |
1230 | } | |
1231 | ||
1232 | nonzero_min_max_signed! { | |
1233 | NonZeroI8(i8); | |
1234 | NonZeroI16(i16); | |
1235 | NonZeroI32(i32); | |
1236 | NonZeroI64(i64); | |
1237 | NonZeroI128(i128); | |
1238 | NonZeroIsize(isize); | |
1239 | } | |
1240 | ||
1241 | macro_rules! nonzero_bits { | |
1242 | ( $( $Ty: ident($Int: ty); )+ ) => { | |
1243 | $( | |
1244 | impl $Ty { | |
1245 | /// The size of this non-zero integer type in bits. | |
1246 | /// | |
1247 | #[doc = concat!("This value is equal to [`", stringify!($Int), "::BITS`].")] | |
1248 | /// | |
1249 | /// # Examples | |
1250 | /// | |
1251 | /// ``` | |
5e7ed085 FG |
1252 | #[doc = concat!("# use std::num::", stringify!($Ty), ";")] |
1253 | /// | |
1254 | #[doc = concat!("assert_eq!(", stringify!($Ty), "::BITS, ", stringify!($Int), "::BITS);")] | |
1255 | /// ``` | |
487cf647 | 1256 | #[stable(feature = "nonzero_bits", since = "1.67.0")] |
5e7ed085 FG |
1257 | pub const BITS: u32 = <$Int>::BITS; |
1258 | } | |
1259 | )+ | |
1260 | } | |
1261 | } | |
1262 | ||
1263 | nonzero_bits! { | |
1264 | NonZeroU8(u8); | |
1265 | NonZeroI8(i8); | |
1266 | NonZeroU16(u16); | |
1267 | NonZeroI16(i16); | |
1268 | NonZeroU32(u32); | |
1269 | NonZeroI32(i32); | |
1270 | NonZeroU64(u64); | |
1271 | NonZeroI64(i64); | |
1272 | NonZeroU128(u128); | |
1273 | NonZeroI128(i128); | |
1274 | NonZeroUsize(usize); | |
1275 | NonZeroIsize(isize); | |
1276 | } |