1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use crate::{Integer, Int};
macro_rules! impl_desc {
() => {
"Unchecked arithmetic methods which act on `self`: `self.unchecked_...`. Each method results in undefined behavior if overflow occurs (i.e. when the checked equivalent would return `None`). These methods should therefore only be used when it can be guaranteed that overflow will not occur. If you want to avoid panicking in arithmetic in debug mode, use the wrapping equivalents instead."
};
}
#[doc = impl_desc!()]
impl<const S: bool, const N: usize, const B: usize, const OM: u8> Integer<S, N, B, OM> {
/// Unchecked integer addition. Computes `self + rhs` without checking for overflow, resulting in undefined behavior if overflow occurs.
///
/// `a.unchecked_add(b)` is equivalent to `a.checked_add(b).unwrap_unchecked()`.
///
/// # Safety
///
/// This results in undefined behaviour if overflow occurs, i.e. when [`checked_add`](Self::checked_add) would return `None`.
#[must_use = doc::must_use_op!()]
#[inline]
pub const unsafe fn unchecked_add(self, rhs: Self) -> Self {
unsafe { self.checked_add(rhs).unwrap_unchecked() }
}
/// Unchecked integer subtraction. Computes `self - rhs` without checking for overflow, resulting in undefined behavior if overflow occurs.
///
/// `a.unchecked_sub(b)` is equivalent to `a.checked_sub(b).unwrap_unchecked()`.
///
/// # Safety
///
/// This results in undefined behaviour if overflow occurs, i.e. when [`checked_sub`](Self::checked_sub) would return `None`.
#[must_use = doc::must_use_op!()]
#[inline]
pub const unsafe fn unchecked_sub(self, rhs: Self) -> Self {
unsafe { self.checked_sub(rhs).unwrap_unchecked() }
}
/// Unchecked integer multiplication. Computes `self * rhs` without checking for overflow, resulting in undefined behavior if overflow occurs.
///
/// `a.unchecked_mul(b)` is equivalent to `a.checked_mul(b).unwrap_unchecked()`.
///
/// # Safety
///
/// This results in undefined behaviour if overflow occurs, i.e. when [`checked_mul`](Self::checked_mul) would return `None`.
#[must_use = doc::must_use_op!()]
#[inline]
pub const unsafe fn unchecked_mul(self, rhs: Self) -> Self {
unsafe { self.checked_mul(rhs).unwrap_unchecked() }
}
/// Unchecked left shift. Computes `self << rhs` without checking for overflow, resulting in undefined behavior if overflow occurs.
///
/// `a.unchecked_shl(b)` is equivalent to `a.checked_shl(b).unwrap_unchecked()`.
///
/// # Safety
///
/// This results in undefined behaviour if `rhs` is greater than or equal to `Self::BITS`, i.e. when [`checked_shl`](Self::checked_shl) would return `None`.
#[must_use = doc::must_use_op!()]
#[inline]
pub const unsafe fn unchecked_shl(self, rhs: crate::Exponent) -> Self {
unsafe { self.checked_shl(rhs).unwrap_unchecked() }
}
/// Unchecked right shift. Computes `self >> rhs` without checking for overflow, resulting in undefined behavior if overflow occurs.
///
/// `a.unchecked_shr(b)` is equivalent to `a.checked_shr(b).unwrap_unchecked()`.
///
/// # Safety
///
/// This results in undefined behaviour if `rhs` is greater than or equal to `Self::BITS`, i.e. when [`checked_shr`](Self::checked_shr) would return `None`.
#[must_use = doc::must_use_op!()]
#[inline]
pub const unsafe fn unchecked_shr(self, rhs: crate::Exponent) -> Self {
unsafe { self.checked_shr(rhs).unwrap_unchecked() }
}
}
#[doc = concat!("(Signed integers only.) ", impl_desc!())]
impl<const N: usize, const B: usize, const OM: u8> Int<N, B, OM> {
/// Unchecked integer negation. Computes `-self` without checking for overflow, resulting in undefined behavior if overflow occurs.
///
/// `a.unchecked_neg()` is equivalent to `a.checked_neg().unwrap_unchecked()`.
///
/// # Safety
///
/// This results in undefined behaviour if overflow occurs, i.e. when [`checked_neg`](Self::checked_neg) would return `None`. This can only occur if `self` is [`Self::MIN`].
#[must_use = doc::must_use_op!()]
#[inline]
pub const unsafe fn unchecked_neg(self) -> Self {
unsafe { self.checked_neg().unwrap_unchecked() }
}
}
#[cfg(test)]
mod tests {
use crate::test::test_bignum;
crate::test::test_all! {
testing integers;
test_bignum! {
function: unsafe <stest>::unchecked_add(a: stest, b: stest),
skip: a.checked_add(b).is_none()
}
test_bignum! {
function: unsafe <stest>::unchecked_sub(a: stest, b: stest),
skip: a.checked_sub(b).is_none()
}
test_bignum! {
function: unsafe <stest>::unchecked_mul(a: stest, b: stest),
skip: a.checked_mul(b).is_none()
}
#[cfg(nightly)] // since unchecked_shifts are not stable yet
test_bignum! {
function: unsafe <stest>::unchecked_shl(a: stest, b: u8),
skip: a.checked_shl(b as u32).is_none()
}
#[cfg(nightly)] // since unchecked_shifts are not stable yet
test_bignum! {
function: unsafe <stest>::unchecked_shr(a: stest, b: u8),
skip: a.checked_shr(b as u32).is_none()
}
}
crate::test::test_all! {
testing signed;
#[cfg(nightly)] // since unchecked_neg is not stable yet
test_bignum! {
function: unsafe <itest>::unchecked_neg(a: itest),
skip: a.checked_neg().is_none()
}
}
}
use crate::doc;