Widen 'widening_mul' result; Remove 'widening_mul' from 'u128' and 'i128';

This commit is contained in:
Gabriel Bjørnager Jensen
2026-05-16 19:12:50 +02:00
parent 3514361554
commit 0a07235472
8 changed files with 44 additions and 91 deletions
+1 -1
View File
@@ -868,7 +868,7 @@ fn div_rem_1e16(n: u128) -> (u128, u64) {
const M_HIGH: u128 = 76624777043294442917917351357515459181;
const SH_POST: u8 = 51;
let quot = n.widening_mul(M_HIGH).1 >> SH_POST;
let quot = n.carrying_mul(M_HIGH, 0).1 >> SH_POST;
let rem = n - quot * D;
(quot, rem as u64)
}
+1 -1
View File
@@ -22,7 +22,7 @@ pub struct Fp {
impl Fp {
/// Returns a correctly rounded product of itself and `other`.
pub fn mul(self, other: Self) -> Self {
let (lo, hi) = self.f.widening_mul(other.f);
let (lo, hi) = self.f.carrying_mul(other.f, 0);
let f = hi + (lo >> 63) /* round */;
let e = self.e + other.e + 64;
Self { f, e }
+1 -30
View File
@@ -2777,32 +2777,6 @@ pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
(a as Self, b)
}
/// Calculates the complete product `self * rhs` without the possibility to overflow.
///
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
/// of the result as two separate values, in that order.
///
/// If you also need to add a carry to the wide result, then you want
/// [`Self::carrying_mul`] instead.
///
/// # Examples
///
/// Please note that this example is shared among integer types, which is why `i32` is used.
///
/// ```
/// #![feature(widening_mul)]
/// assert_eq!(5i32.widening_mul(-2), (4294967286, -1));
/// assert_eq!(1_000_000_000i32.widening_mul(-10), (2884901888, -3));
/// ```
#[unstable(feature = "widening_mul", issue = "152016")]
#[rustc_const_unstable(feature = "widening_mul", issue = "152016")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn widening_mul(self, rhs: Self) -> ($UnsignedT, Self) {
Self::carrying_mul_add(self, rhs, 0, 0)
}
/// Calculates the "full multiplication" `self * rhs + carry`
/// without the possibility to overflow.
///
@@ -2813,8 +2787,6 @@ pub const fn widening_mul(self, rhs: Self) -> ($UnsignedT, Self) {
/// additional amount of overflow. This allows for chaining together multiple
/// multiplications to create "big integers" which represent larger values.
///
/// If you don't need the `carry`, then you can use [`Self::widening_mul`] instead.
///
/// # Examples
///
/// Please note that this example is shared among integer types, which is why `i32` is used.
@@ -2849,8 +2821,7 @@ pub const fn carrying_mul(self, rhs: Self, carry: Self) -> ($UnsignedT, Self) {
/// additional amount of overflow. This allows for chaining together multiple
/// multiplications to create "big integers" which represent larger values.
///
/// If you don't need either `carry`, then you can use [`Self::widening_mul`] instead,
/// and if you only need one `carry`, then you can use [`Self::carrying_mul`] instead.
/// If you only need one `carry`, then you can use [`Self::carrying_mul`] instead.
///
/// # Examples
///
+41
View File
@@ -240,6 +240,39 @@ pub const fn midpoint(self, rhs: $SelfT) -> $SelfT {
};
}
macro_rules! widening_mul_impl {
($SelfT:ty, $WideT:ty) => {
/// Widening multiplication. Computes `self * rhs`, widening to a larger integer.
///
/// The returned value is always exact and can never overflow.
///
/// Note that this method is semantically equivalent to [`carrying_mul`] with a
/// carry of zero, with the latter instead returning a tuple denoting the low and
/// high parts of the result. Consider using it instead if you need
/// interoperability with other big int helper functions, or if this method isn't
/// available for a given type.
///
/// [`carrying_mul`]: Self::carrying_mul
///
/// # Examples
///
/// ```
/// #![feature(widening_mul)]
///
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(0_", stringify!($SelfT), "), 0);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), ", stringify!($SelfT), "::MAX as ", stringify!($WideT), " * ", stringify!($SelfT), "::MAX as ", stringify!($WideT), ");")]
/// ```
#[unstable(feature = "widening_mul", issue = "152016")]
#[rustc_const_unstable(feature = "widening_mul", issue = "152016")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn widening_mul(self, rhs: Self) -> $WideT {
self as $WideT * rhs as $WideT
}
}
}
macro_rules! widening_carryless_mul_impl {
($SelfT:ty, $WideT:ty) => {
/// Performs a widening carry-less multiplication.
@@ -360,6 +393,7 @@ impl i8 {
bound_condition = "",
}
midpoint_impl! { i8, i16, signed }
widening_mul_impl! { i8, i16 }
}
impl i16 {
@@ -384,6 +418,7 @@ impl i16 {
bound_condition = "",
}
midpoint_impl! { i16, i32, signed }
widening_mul_impl! { i16, i32 }
}
impl i32 {
@@ -408,6 +443,7 @@ impl i32 {
bound_condition = "",
}
midpoint_impl! { i32, i64, signed }
widening_mul_impl! { i32, i64 }
}
impl i64 {
@@ -432,6 +468,7 @@ impl i64 {
bound_condition = "",
}
midpoint_impl! { i64, signed }
widening_mul_impl! { i64, i128 }
}
impl i128 {
@@ -568,6 +605,7 @@ impl u8 {
bound_condition = "",
}
midpoint_impl! { u8, u16, unsigned }
widening_mul_impl! { u8, u16 }
widening_carryless_mul_impl! { u8, u16 }
carrying_carryless_mul_impl! { u8, u16 }
@@ -1215,6 +1253,7 @@ impl u16 {
bound_condition = "",
}
midpoint_impl! { u16, u32, unsigned }
widening_mul_impl! { u16, u32 }
widening_carryless_mul_impl! { u16, u32 }
carrying_carryless_mul_impl! { u16, u32 }
@@ -1270,6 +1309,7 @@ impl u32 {
bound_condition = "",
}
midpoint_impl! { u32, u64, unsigned }
widening_mul_impl! { u32, u64 }
widening_carryless_mul_impl! { u32, u64 }
carrying_carryless_mul_impl! { u32, u64 }
}
@@ -1301,6 +1341,7 @@ impl u64 {
bound_condition = "",
}
midpoint_impl! { u64, u128, unsigned }
widening_mul_impl! { u64, u128 }
widening_carryless_mul_impl! { u64, u128 }
carrying_carryless_mul_impl! { u64, u128 }
}
-48
View File
@@ -3177,54 +3177,6 @@ pub const fn overflowing_mul(self, rhs: Self) -> (Self, bool) {
(a as Self, b)
}
/// Calculates the complete double-width product `self * rhs`.
///
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
/// of the result as two separate values, in that order. As such,
/// `a.widening_mul(b).0` produces the same result as `a.wrapping_mul(b)`.
///
/// If you also need to add a value and carry to the wide result, then you want
/// [`Self::carrying_mul_add`] instead.
///
/// If you also need to add a carry to the wide result, then you want
/// [`Self::carrying_mul`] instead.
///
/// If you just want to know *whether* the multiplication overflowed, then you
/// want [`Self::overflowing_mul`] instead.
///
/// # Examples
///
/// ```
/// #![feature(widening_mul)]
#[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".widening_mul(7), (35, 0));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), (1, ", stringify!($SelfT), "::MAX - 1));")]
/// ```
///
/// Compared to other `*_mul` methods:
/// ```
/// #![feature(widening_mul)]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::widening_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, 3));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::overflowing_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, true));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::wrapping_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), 0);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::checked_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), None);")]
/// ```
///
/// Please note that this example is shared among integer types, which is why `u32` is used.
///
/// ```
/// #![feature(widening_mul)]
/// assert_eq!(5u32.widening_mul(2), (10, 0));
/// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2));
/// ```
#[unstable(feature = "widening_mul", issue = "152016")]
#[rustc_const_unstable(feature = "widening_mul", issue = "152016")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
pub const fn widening_mul(self, rhs: Self) -> (Self, Self) {
Self::carrying_mul_add(self, rhs, 0, 0)
}
/// Calculates the "full multiplication" `self * rhs + carry`
/// without the possibility to overflow.
///
-1
View File
@@ -126,7 +126,6 @@
#![feature(unicode_internals)]
#![feature(unsize)]
#![feature(unwrap_infallible)]
#![feature(widening_mul)]
// tidy-alphabetical-end
#![allow(internal_features)]
#![deny(fuzzy_provenance_casts)]
@@ -433,12 +433,6 @@ fn test_borrowing_sub() {
assert_eq_const_safe!(($T, bool): (0 as $T).borrowing_sub(MIN, true), (MAX, false));
}
fn test_widening_mul() {
assert_eq_const_safe!(($U, $T): MAX.widening_mul(MAX), (1, MAX / 2));
assert_eq_const_safe!(($U, $T): MIN.widening_mul(MAX), (MIN as $U, MIN / 2));
assert_eq_const_safe!(($U, $T): MIN.widening_mul(MIN), (0, MAX / 2 + 1));
}
fn test_carrying_mul() {
assert_eq_const_safe!(($U, $T): MAX.carrying_mul(MAX, 0), (1, MAX / 2));
assert_eq_const_safe!(($U, $T):
@@ -504,10 +504,6 @@ fn test_borrowing_sub() {
assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true));
}
fn test_widening_mul() {
assert_eq_const_safe!(($T, $T): $T::MAX.widening_mul($T::MAX), (1, $T::MAX - 1));
}
fn test_carrying_mul() {
assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, 0), (1, $T::MAX - 1));
assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, $T::MAX), (0, $T::MAX));