mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-22 18:15:07 +03:00
Widen 'widening_mul' result; Remove 'widening_mul' from 'u128' and 'i128';
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
///
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
///
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user