Skip to content

Commit 3605c1f

Browse files
Rollup merge of #156644 - bjoernager:widening-mul, r=clarfonthey
Widen the result of `widening_mul`. Tracking issue: #152016 This PR implements <#152016 (comment)>, which mandates that `widening_mul` return a single, scalar value rather than a low/high tuple. Consequently, this method is removed from `u128` and `i128` as they are the widest integral types. It has also been removed from `usize` and `isize` due to portability concerns. Existing `widening_mul` usage has been replaced by equivalent calls to `carrying_mul` (which is logically identical to the old behaviour.) Existing &ndash; generic &ndash; non-doc tests have been removed. # Public API ```rust impl u8 { pub const fn widening_mul(self, rhs: Self) -> u16; } impl u16 { pub const fn widening_mul(self, rhs: Self) -> u32; } impl u32 { pub const fn widening_mul(self, rhs: Self) -> u64; } impl u64 { pub const fn widening_mul(self, rhs: Self) -> u128; } impl i8 { pub const fn widening_mul(self, rhs: Self) -> i16; } impl i16 { pub const fn widening_mul(self, rhs: Self) -> i32; } impl i32 { pub const fn widening_mul(self, rhs: Self) -> i64; } impl i64 { pub const fn widening_mul(self, rhs: Self) -> i128; } ```
2 parents a26a652 + 0a07235 commit 3605c1f

8 files changed

Lines changed: 44 additions & 91 deletions

File tree

library/core/src/fmt/num.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ fn div_rem_1e16(n: u128) -> (u128, u64) {
868868
const M_HIGH: u128 = 76624777043294442917917351357515459181;
869869
const SH_POST: u8 = 51;
870870

871-
let quot = n.widening_mul(M_HIGH).1 >> SH_POST;
871+
let quot = n.carrying_mul(M_HIGH, 0).1 >> SH_POST;
872872
let rem = n - quot * D;
873873
(quot, rem as u64)
874874
}

library/core/src/num/imp/diy_float.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub struct Fp {
2222
impl Fp {
2323
/// Returns a correctly rounded product of itself and `other`.
2424
pub fn mul(self, other: Self) -> Self {
25-
let (lo, hi) = self.f.widening_mul(other.f);
25+
let (lo, hi) = self.f.carrying_mul(other.f, 0);
2626
let f = hi + (lo >> 63) /* round */;
2727
let e = self.e + other.e + 64;
2828
Self { f, e }

library/core/src/num/int_macros.rs

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2777,32 +2777,6 @@ macro_rules! int_impl {
27772777
(a as Self, b)
27782778
}
27792779

2780-
/// Calculates the complete product `self * rhs` without the possibility to overflow.
2781-
///
2782-
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
2783-
/// of the result as two separate values, in that order.
2784-
///
2785-
/// If you also need to add a carry to the wide result, then you want
2786-
/// [`Self::carrying_mul`] instead.
2787-
///
2788-
/// # Examples
2789-
///
2790-
/// Please note that this example is shared among integer types, which is why `i32` is used.
2791-
///
2792-
/// ```
2793-
/// #![feature(widening_mul)]
2794-
/// assert_eq!(5i32.widening_mul(-2), (4294967286, -1));
2795-
/// assert_eq!(1_000_000_000i32.widening_mul(-10), (2884901888, -3));
2796-
/// ```
2797-
#[unstable(feature = "widening_mul", issue = "152016")]
2798-
#[rustc_const_unstable(feature = "widening_mul", issue = "152016")]
2799-
#[must_use = "this returns the result of the operation, \
2800-
without modifying the original"]
2801-
#[inline]
2802-
pub const fn widening_mul(self, rhs: Self) -> ($UnsignedT, Self) {
2803-
Self::carrying_mul_add(self, rhs, 0, 0)
2804-
}
2805-
28062780
/// Calculates the "full multiplication" `self * rhs + carry`
28072781
/// without the possibility to overflow.
28082782
///
@@ -2813,8 +2787,6 @@ macro_rules! int_impl {
28132787
/// additional amount of overflow. This allows for chaining together multiple
28142788
/// multiplications to create "big integers" which represent larger values.
28152789
///
2816-
/// If you don't need the `carry`, then you can use [`Self::widening_mul`] instead.
2817-
///
28182790
/// # Examples
28192791
///
28202792
/// Please note that this example is shared among integer types, which is why `i32` is used.
@@ -2849,8 +2821,7 @@ macro_rules! int_impl {
28492821
/// additional amount of overflow. This allows for chaining together multiple
28502822
/// multiplications to create "big integers" which represent larger values.
28512823
///
2852-
/// If you don't need either `carry`, then you can use [`Self::widening_mul`] instead,
2853-
/// and if you only need one `carry`, then you can use [`Self::carrying_mul`] instead.
2824+
/// If you only need one `carry`, then you can use [`Self::carrying_mul`] instead.
28542825
///
28552826
/// # Examples
28562827
///

library/core/src/num/mod.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,39 @@ macro_rules! midpoint_impl {
240240
};
241241
}
242242

243+
macro_rules! widening_mul_impl {
244+
($SelfT:ty, $WideT:ty) => {
245+
/// Widening multiplication. Computes `self * rhs`, widening to a larger integer.
246+
///
247+
/// The returned value is always exact and can never overflow.
248+
///
249+
/// Note that this method is semantically equivalent to [`carrying_mul`] with a
250+
/// carry of zero, with the latter instead returning a tuple denoting the low and
251+
/// high parts of the result. Consider using it instead if you need
252+
/// interoperability with other big int helper functions, or if this method isn't
253+
/// available for a given type.
254+
///
255+
/// [`carrying_mul`]: Self::carrying_mul
256+
///
257+
/// # Examples
258+
///
259+
/// ```
260+
/// #![feature(widening_mul)]
261+
///
262+
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(0_", stringify!($SelfT), "), 0);")]
263+
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), ", stringify!($SelfT), "::MAX as ", stringify!($WideT), " * ", stringify!($SelfT), "::MAX as ", stringify!($WideT), ");")]
264+
/// ```
265+
#[unstable(feature = "widening_mul", issue = "152016")]
266+
#[rustc_const_unstable(feature = "widening_mul", issue = "152016")]
267+
#[must_use = "this returns the result of the operation, \
268+
without modifying the original"]
269+
#[inline]
270+
pub const fn widening_mul(self, rhs: Self) -> $WideT {
271+
self as $WideT * rhs as $WideT
272+
}
273+
}
274+
}
275+
243276
macro_rules! widening_carryless_mul_impl {
244277
($SelfT:ty, $WideT:ty) => {
245278
/// Performs a widening carry-less multiplication.
@@ -360,6 +393,7 @@ impl i8 {
360393
bound_condition = "",
361394
}
362395
midpoint_impl! { i8, i16, signed }
396+
widening_mul_impl! { i8, i16 }
363397
}
364398

365399
impl i16 {
@@ -384,6 +418,7 @@ impl i16 {
384418
bound_condition = "",
385419
}
386420
midpoint_impl! { i16, i32, signed }
421+
widening_mul_impl! { i16, i32 }
387422
}
388423

389424
impl i32 {
@@ -408,6 +443,7 @@ impl i32 {
408443
bound_condition = "",
409444
}
410445
midpoint_impl! { i32, i64, signed }
446+
widening_mul_impl! { i32, i64 }
411447
}
412448

413449
impl i64 {
@@ -432,6 +468,7 @@ impl i64 {
432468
bound_condition = "",
433469
}
434470
midpoint_impl! { i64, signed }
471+
widening_mul_impl! { i64, i128 }
435472
}
436473

437474
impl i128 {
@@ -568,6 +605,7 @@ impl u8 {
568605
bound_condition = "",
569606
}
570607
midpoint_impl! { u8, u16, unsigned }
608+
widening_mul_impl! { u8, u16 }
571609
widening_carryless_mul_impl! { u8, u16 }
572610
carrying_carryless_mul_impl! { u8, u16 }
573611

@@ -1215,6 +1253,7 @@ impl u16 {
12151253
bound_condition = "",
12161254
}
12171255
midpoint_impl! { u16, u32, unsigned }
1256+
widening_mul_impl! { u16, u32 }
12181257
widening_carryless_mul_impl! { u16, u32 }
12191258
carrying_carryless_mul_impl! { u16, u32 }
12201259

@@ -1270,6 +1309,7 @@ impl u32 {
12701309
bound_condition = "",
12711310
}
12721311
midpoint_impl! { u32, u64, unsigned }
1312+
widening_mul_impl! { u32, u64 }
12731313
widening_carryless_mul_impl! { u32, u64 }
12741314
carrying_carryless_mul_impl! { u32, u64 }
12751315
}
@@ -1301,6 +1341,7 @@ impl u64 {
13011341
bound_condition = "",
13021342
}
13031343
midpoint_impl! { u64, u128, unsigned }
1344+
widening_mul_impl! { u64, u128 }
13041345
widening_carryless_mul_impl! { u64, u128 }
13051346
carrying_carryless_mul_impl! { u64, u128 }
13061347
}

library/core/src/num/uint_macros.rs

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3179,54 +3179,6 @@ macro_rules! uint_impl {
31793179
(a as Self, b)
31803180
}
31813181

3182-
/// Calculates the complete double-width product `self * rhs`.
3183-
///
3184-
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
3185-
/// of the result as two separate values, in that order. As such,
3186-
/// `a.widening_mul(b).0` produces the same result as `a.wrapping_mul(b)`.
3187-
///
3188-
/// If you also need to add a value and carry to the wide result, then you want
3189-
/// [`Self::carrying_mul_add`] instead.
3190-
///
3191-
/// If you also need to add a carry to the wide result, then you want
3192-
/// [`Self::carrying_mul`] instead.
3193-
///
3194-
/// If you just want to know *whether* the multiplication overflowed, then you
3195-
/// want [`Self::overflowing_mul`] instead.
3196-
///
3197-
/// # Examples
3198-
///
3199-
/// ```
3200-
/// #![feature(widening_mul)]
3201-
#[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".widening_mul(7), (35, 0));")]
3202-
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.widening_mul(", stringify!($SelfT), "::MAX), (1, ", stringify!($SelfT), "::MAX - 1));")]
3203-
/// ```
3204-
///
3205-
/// Compared to other `*_mul` methods:
3206-
/// ```
3207-
/// #![feature(widening_mul)]
3208-
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::widening_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, 3));")]
3209-
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::overflowing_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), (0, true));")]
3210-
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::wrapping_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), 0);")]
3211-
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::checked_mul(1 << ", stringify!($BITS_MINUS_ONE), ", 6), None);")]
3212-
/// ```
3213-
///
3214-
/// Please note that this example is shared among integer types, which is why `u32` is used.
3215-
///
3216-
/// ```
3217-
/// #![feature(widening_mul)]
3218-
/// assert_eq!(5u32.widening_mul(2), (10, 0));
3219-
/// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2));
3220-
/// ```
3221-
#[unstable(feature = "widening_mul", issue = "152016")]
3222-
#[rustc_const_unstable(feature = "widening_mul", issue = "152016")]
3223-
#[must_use = "this returns the result of the operation, \
3224-
without modifying the original"]
3225-
#[inline]
3226-
pub const fn widening_mul(self, rhs: Self) -> (Self, Self) {
3227-
Self::carrying_mul_add(self, rhs, 0, 0)
3228-
}
3229-
32303182
/// Calculates the "full multiplication" `self * rhs + carry`
32313183
/// without the possibility to overflow.
32323184
///

library/coretests/tests/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@
126126
#![feature(unicode_internals)]
127127
#![feature(unsize)]
128128
#![feature(unwrap_infallible)]
129-
#![feature(widening_mul)]
130129
// tidy-alphabetical-end
131130
#![allow(internal_features)]
132131
#![deny(fuzzy_provenance_casts)]

library/coretests/tests/num/int_macros.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -433,12 +433,6 @@ macro_rules! int_module {
433433
assert_eq_const_safe!(($T, bool): (0 as $T).borrowing_sub(MIN, true), (MAX, false));
434434
}
435435

436-
fn test_widening_mul() {
437-
assert_eq_const_safe!(($U, $T): MAX.widening_mul(MAX), (1, MAX / 2));
438-
assert_eq_const_safe!(($U, $T): MIN.widening_mul(MAX), (MIN as $U, MIN / 2));
439-
assert_eq_const_safe!(($U, $T): MIN.widening_mul(MIN), (0, MAX / 2 + 1));
440-
}
441-
442436
fn test_carrying_mul() {
443437
assert_eq_const_safe!(($U, $T): MAX.carrying_mul(MAX, 0), (1, MAX / 2));
444438
assert_eq_const_safe!(($U, $T):

library/coretests/tests/num/uint_macros.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -504,10 +504,6 @@ macro_rules! uint_module {
504504
assert_eq_const_safe!(($T, bool): $T::MAX.borrowing_sub($T::MAX, true), ($T::MAX, true));
505505
}
506506

507-
fn test_widening_mul() {
508-
assert_eq_const_safe!(($T, $T): $T::MAX.widening_mul($T::MAX), (1, $T::MAX - 1));
509-
}
510-
511507
fn test_carrying_mul() {
512508
assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, 0), (1, $T::MAX - 1));
513509
assert_eq_const_safe!(($T, $T): $T::MAX.carrying_mul($T::MAX, $T::MAX), (0, $T::MAX));

0 commit comments

Comments
 (0)