Skip to content

Commit 9c8317e

Browse files
committed
Add (checked_)norem_div methods for integer types
1 parent cabdf3a commit 9c8317e

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

library/core/src/num/int_macros.rs

+76
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,82 @@ macro_rules! int_impl {
10851085
if unlikely!(b) { overflow_panic::rem() } else { a }
10861086
}
10871087

1088+
/// Checked integer division without remainder. Computes `self / rhs`,
1089+
/// returning `None` if one `rhs == 0`, the division results in overflow,
1090+
/// or remainder is not zero.
1091+
///
1092+
/// # Examples
1093+
///
1094+
/// Basic usage:
1095+
///
1096+
/// ```
1097+
/// #![feature(norem_div)]
1098+
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_norem_div(-1), Some(", stringify!($Max), "));")]
1099+
#[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").checked_norem_div(2), None);")]
1100+
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_norem_div(-1), None);")]
1101+
#[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_norem_div(0), None);")]
1102+
/// ```
1103+
#[unstable(
1104+
feature = "norem_div",
1105+
issue = "1",
1106+
)]
1107+
#[must_use = "this returns the result of the operation, \
1108+
without modifying the original"]
1109+
#[inline]
1110+
pub const fn checked_norem_div(self, rhs: Self) -> Option<Self> {
1111+
if unlikely!(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) {
1112+
None
1113+
} else {
1114+
// SAFETY: div by zero and by INT_MIN have been checked above
1115+
unsafe {
1116+
if unlikely!(intrinsics::unchecked_rem(self, rhs) != 0) {
1117+
None
1118+
} else {
1119+
Some(intrinsics::unchecked_div(self, rhs))
1120+
}
1121+
}
1122+
}
1123+
}
1124+
1125+
/// Checked integer division without remainder. Computes `self / rhs`.
1126+
///
1127+
/// # Panics
1128+
///
1129+
/// This function will panic if `rhs == 0` or if division remainder is not zero.
1130+
///
1131+
/// # Examples
1132+
///
1133+
/// Basic usage:
1134+
///
1135+
/// ```
1136+
/// #![feature(norem_div)]
1137+
#[doc = concat!("assert_eq!(128", stringify!($SelfT), ".norem_div(2), 64);")]
1138+
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".norem_div(32), 2);")]
1139+
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).norem_div(-1), ", stringify!($Max), ");")]
1140+
/// ```
1141+
///
1142+
/// ```should_panic
1143+
/// #![feature(norem_div)]
1144+
#[doc = concat!("129", stringify!($SelfT), ".norem_div(2);")]
1145+
/// ```
1146+
/// ```should_panic
1147+
/// #![feature(norem_div)]
1148+
#[doc = concat!(stringify!($SelfT), "::MIN.norem_div(-1);")]
1149+
/// ```
1150+
#[unstable(
1151+
feature = "norem_div",
1152+
issue = "1",
1153+
)]
1154+
#[must_use = "this returns the result of the operation, \
1155+
without modifying the original"]
1156+
#[inline]
1157+
pub const fn norem_div(self, rhs: Self) -> Self {
1158+
match self.checked_norem_div(rhs) {
1159+
Some(v) => v,
1160+
None => panic!("Failed to divide {self} by {rhs} without remainder"),
1161+
}
1162+
}
1163+
10881164
/// Checked negation. Computes `-self`, returning `None` if `self == MIN`.
10891165
///
10901166
/// # Examples

library/core/src/num/uint_macros.rs

+70
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,76 @@ macro_rules! uint_impl {
996996
self % rhs
997997
}
998998

999+
/// Checked integer division without remainder. Computes `self / rhs`,
1000+
/// returning `None` if `rhs == 0` or if division remainder is not zero.
1001+
///
1002+
/// # Examples
1003+
///
1004+
/// Basic usage:
1005+
///
1006+
/// ```
1007+
/// #![feature(norem_div)]
1008+
#[doc = concat!("assert_eq!(128", stringify!($SelfT), ".checked_norem_div(2), Some(64));")]
1009+
#[doc = concat!("assert_eq!(129", stringify!($SelfT), ".checked_norem_div(2), None);")]
1010+
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_norem_div(0), None);")]
1011+
/// ```
1012+
#[unstable(
1013+
feature = "norem_div",
1014+
issue = "1",
1015+
)]
1016+
#[must_use = "this returns the result of the operation, \
1017+
without modifying the original"]
1018+
#[inline]
1019+
pub const fn checked_norem_div(self, rhs: Self) -> Option<Self> {
1020+
if unlikely!(rhs == 0) {
1021+
None
1022+
} else {
1023+
// SAFETY: div by zero has been checked above and unsigned types have no other
1024+
// failure modes for division
1025+
unsafe {
1026+
if unlikely!(intrinsics::unchecked_rem(self, rhs) != 0) {
1027+
None
1028+
} else {
1029+
Some(intrinsics::unchecked_div(self, rhs))
1030+
}
1031+
}
1032+
}
1033+
}
1034+
1035+
/// Checked integer division without remainder. Computes `self / rhs`.
1036+
///
1037+
/// # Panics
1038+
///
1039+
/// This function will panic if `rhs == 0` or if division remainder is not zero.
1040+
///
1041+
/// # Examples
1042+
///
1043+
/// Basic usage:
1044+
///
1045+
/// ```
1046+
/// #![feature(norem_div)]
1047+
#[doc = concat!("assert_eq!(128", stringify!($SelfT), ".norem_div(2), 64);")]
1048+
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".norem_div(32), 2);")]
1049+
/// ```
1050+
///
1051+
/// ```should_panic
1052+
/// #![feature(norem_div)]
1053+
#[doc = concat!("129", stringify!($SelfT), ".norem_div(2);")]
1054+
/// ```
1055+
#[unstable(
1056+
feature = "norem_div",
1057+
issue = "1",
1058+
)]
1059+
#[must_use = "this returns the result of the operation, \
1060+
without modifying the original"]
1061+
#[inline]
1062+
pub const fn norem_div(self, rhs: Self) -> Self {
1063+
match self.checked_norem_div(rhs) {
1064+
Some(v) => v,
1065+
None => panic!("Failed to divide {self} by {rhs} without remainder"),
1066+
}
1067+
}
1068+
9991069
/// Returns the logarithm of the number with respect to an arbitrary base,
10001070
/// rounded down.
10011071
///

0 commit comments

Comments
 (0)