Skip to content

Commit 4f011f3

Browse files
committed
add exact_div functions
1 parent 4d051fb commit 4f011f3

File tree

2 files changed

+207
-1
lines changed

2 files changed

+207
-1
lines changed

library/core/src/num/int_macros.rs

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ macro_rules! int_impl {
44
ActualT = $ActualT:ident,
55
UnsignedT = $UnsignedT:ty,
66

7-
// There are all for use *only* in doc comments.
7+
// These are all for use *only* in doc comments.
88
// As such, they're all passed as literals -- passing them as a string
99
// literal is fine if they need to be multiple code tokens.
1010
// In non-comments, use the associated constants rather than these.
@@ -1018,6 +1018,110 @@ macro_rules! int_impl {
10181018
if b { overflow_panic::div() } else { a }
10191019
}
10201020

1021+
/// Checked integer division without remainder. Computes `self / rhs`,
1022+
/// returning `None` if `rhs == 0`, the division results in overflow,
1023+
/// or `self % rhs != 0`.
1024+
///
1025+
/// # Examples
1026+
///
1027+
/// Basic usage:
1028+
///
1029+
/// ```
1030+
/// #![feature(exact_div)]
1031+
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).checked_exact_div(-1), Some(", stringify!($Max), "));")]
1032+
#[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").checked_exact_div(2), None);")]
1033+
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_exact_div(-1), None);")]
1034+
#[doc = concat!("assert_eq!((1", stringify!($SelfT), ").checked_exact_div(0), None);")]
1035+
/// ```
1036+
#[unstable(
1037+
feature = "exact_div",
1038+
issue = "139911",
1039+
)]
1040+
#[must_use = "this returns the result of the operation, \
1041+
without modifying the original"]
1042+
#[inline]
1043+
pub const fn checked_exact_div(self, rhs: Self) -> Option<Self> {
1044+
if intrinsics::unlikely(rhs == 0 || ((self == Self::MIN) && (rhs == -1))) {
1045+
None
1046+
} else {
1047+
// SAFETY: division by zero and overflow are checked above
1048+
unsafe {
1049+
if intrinsics::unlikely(intrinsics::unchecked_rem(self, rhs) != 0) {
1050+
None
1051+
} else {
1052+
Some(intrinsics::exact_div(self, rhs))
1053+
}
1054+
}
1055+
}
1056+
}
1057+
1058+
/// Checked integer division without remainder. Computes `self / rhs`.
1059+
///
1060+
/// # Panics
1061+
///
1062+
/// This function will panic if `rhs == 0`, the division results in overflow,
1063+
/// or `self % rhs != 0`.
1064+
///
1065+
/// # Examples
1066+
///
1067+
/// Basic usage:
1068+
///
1069+
/// ```
1070+
/// #![feature(exact_div)]
1071+
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")]
1072+
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")]
1073+
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 1).exact_div(-1), ", stringify!($Max), ");")]
1074+
/// ```
1075+
///
1076+
/// ```should_panic
1077+
/// #![feature(exact_div)]
1078+
#[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")]
1079+
/// ```
1080+
/// ```should_panic
1081+
/// #![feature(exact_div)]
1082+
#[doc = concat!("let _ = ", stringify!($SelfT), "::MIN.exact_div(-1);")]
1083+
/// ```
1084+
#[unstable(
1085+
feature = "exact_div",
1086+
issue = "139911",
1087+
)]
1088+
#[must_use = "this returns the result of the operation, \
1089+
without modifying the original"]
1090+
#[inline]
1091+
pub const fn exact_div(self, rhs: Self) -> Self {
1092+
match self.checked_exact_div(rhs) {
1093+
Some(x) => x,
1094+
None => panic!("Failed to divide without remainder"),
1095+
}
1096+
}
1097+
1098+
/// Unchecked integer division without remainder. Computes `self / rhs`.
1099+
///
1100+
/// # Safety
1101+
///
1102+
/// This results in undefined behavior when `rhs == 0`, `self % rhs != 0`, or
1103+
#[doc = concat!("`self == ", stringify!($SelfT), "::MIN && rhs == -1`,")]
1104+
/// i.e. when [`checked_exact_div`] would return None.
1105+
#[unstable(
1106+
feature = "exact_div",
1107+
issue = "139911",
1108+
)]
1109+
#[must_use = "this returns the result of the operation, \
1110+
without modifying the original"]
1111+
#[inline]
1112+
pub const unsafe fn unchecked_exact_div(self, rhs: Self) -> Self {
1113+
assert_unsafe_precondition!(
1114+
check_language_ub,
1115+
concat!(stringify!($SelfT), "::unchecked_exact_div cannot overflow, divide by zero, or leave a remainder"),
1116+
(
1117+
lhs: $SelfT = self,
1118+
rhs: $SelfT = rhs,
1119+
) => rhs > 0 && lhs % rhs == 0 && (lhs != <$SelfT>::MIN || rhs != -1),
1120+
);
1121+
// SAFETY: Same precondition
1122+
unsafe { intrinsics::exact_div(self, rhs) }
1123+
}
1124+
10211125
/// Checked integer remainder. Computes `self % rhs`, returning `None` if
10221126
/// `rhs == 0` or the division results in overflow.
10231127
///

library/core/src/num/uint_macros.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,108 @@ macro_rules! uint_impl {
11101110
self / rhs
11111111
}
11121112

1113+
/// Checked integer division without remainder. Computes `self / rhs`.
1114+
///
1115+
/// # Panics
1116+
///
1117+
/// This function will panic if `rhs == 0` or `self % rhs != 0`.
1118+
///
1119+
/// # Examples
1120+
///
1121+
/// Basic usage:
1122+
///
1123+
/// ```
1124+
/// #![feature(exact_div)]
1125+
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")]
1126+
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")]
1127+
/// ```
1128+
///
1129+
/// ```should_panic
1130+
/// #![feature(exact_div)]
1131+
#[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")]
1132+
/// ```
1133+
#[unstable(
1134+
feature = "exact_div",
1135+
issue = "139911",
1136+
)]
1137+
#[must_use = "this returns the result of the operation, \
1138+
without modifying the original"]
1139+
#[inline]
1140+
pub const fn checked_exact_div(self, rhs: Self) -> Option<Self> {
1141+
if intrinsics::unlikely(rhs == 0) {
1142+
None
1143+
} else {
1144+
// SAFETY: division by zero is checked above
1145+
unsafe {
1146+
if intrinsics::unlikely(intrinsics::unchecked_rem(self, rhs) != 0) {
1147+
None
1148+
} else {
1149+
Some(intrinsics::exact_div(self, rhs))
1150+
}
1151+
}
1152+
}
1153+
}
1154+
1155+
/// Checked integer division without remainder. Computes `self / rhs`.
1156+
///
1157+
/// # Panics
1158+
///
1159+
/// This function will panic if `rhs == 0` or `self % rhs != 0`.
1160+
///
1161+
/// # Examples
1162+
///
1163+
/// Basic usage:
1164+
///
1165+
/// ```
1166+
/// #![feature(exact_div)]
1167+
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(2), 32);")]
1168+
#[doc = concat!("assert_eq!(64", stringify!($SelfT), ".exact_div(32), 2);")]
1169+
/// ```
1170+
///
1171+
/// ```should_panic
1172+
/// #![feature(exact_div)]
1173+
#[doc = concat!("let _ = 65", stringify!($SelfT), ".exact_div(2);")]
1174+
/// ```
1175+
#[unstable(
1176+
feature = "exact_div",
1177+
issue = "139911",
1178+
)]
1179+
#[must_use = "this returns the result of the operation, \
1180+
without modifying the original"]
1181+
#[inline]
1182+
pub const fn exact_div(self, rhs: Self) -> Self {
1183+
match self.checked_exact_div(rhs) {
1184+
Some(x) => x,
1185+
None => panic!("Failed to divide without remainder"),
1186+
}
1187+
}
1188+
1189+
/// Unchecked integer division without remainder. Computes `self / rhs`.
1190+
///
1191+
/// # Safety
1192+
///
1193+
/// This results in undefined behavior when `rhs == 0` or `self % rhs != 0`,
1194+
/// i.e. when [`checked_exact_div`] would return None.
1195+
#[unstable(
1196+
feature = "exact_div",
1197+
issue = "139911",
1198+
)]
1199+
#[must_use = "this returns the result of the operation, \
1200+
without modifying the original"]
1201+
#[inline]
1202+
pub const unsafe fn unchecked_exact_div(self, rhs: Self) -> Self {
1203+
assert_unsafe_precondition!(
1204+
check_language_ub,
1205+
concat!(stringify!($SelfT), "::unchecked_exact_div divide by zero or leave a remainder"),
1206+
(
1207+
lhs: $SelfT = self,
1208+
rhs: $SelfT = rhs,
1209+
) => rhs > 0 && lhs % rhs == 0,
1210+
);
1211+
// SAFETY: Same precondition
1212+
unsafe { intrinsics::exact_div(self, rhs) }
1213+
}
1214+
11131215
/// Checked integer remainder. Computes `self % rhs`, returning `None`
11141216
/// if `rhs == 0`.
11151217
///

0 commit comments

Comments
 (0)