Skip to content

Commit 070591e

Browse files
committed
Tidy up bigint mul implementations
1 parent 5f5c243 commit 070591e

File tree

11 files changed

+567
-118
lines changed

11 files changed

+567
-118
lines changed

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
#![cfg_attr(bootstrap, feature(const_fmt_arguments_new))]
111111
#![feature(array_ptr_get)]
112112
#![feature(asm_experimental_arch)]
113+
#![feature(bigint_helper_methods)]
113114
#![feature(const_align_of_val)]
114115
#![feature(const_align_of_val_raw)]
115116
#![feature(const_align_offset)]

library/core/src/num/int_macros.rs

+111
Original file line numberDiff line numberDiff line change
@@ -2540,6 +2540,117 @@ macro_rules! int_impl {
25402540
(a as Self, b)
25412541
}
25422542

2543+
/// Calculates the complete product `self * rhs` without the possibility to overflow.
2544+
///
2545+
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
2546+
/// of the result as two separate values, in that order.
2547+
///
2548+
/// If you also need to add a carry to the wide result, then you want
2549+
/// [`Self::carrying_mul`] instead.
2550+
///
2551+
/// # Examples
2552+
///
2553+
/// Basic usage:
2554+
///
2555+
/// Please note that this example is shared between integer types.
2556+
/// Which explains why `i32` is used here.
2557+
///
2558+
/// ```
2559+
/// #![feature(bigint_helper_methods)]
2560+
/// assert_eq!(5i32.widening_mul(-2), (4294967286, -1));
2561+
/// assert_eq!(1_000_000_000i32.widening_mul(-10), (2884901888, -3));
2562+
/// ```
2563+
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
2564+
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
2565+
#[must_use = "this returns the result of the operation, \
2566+
without modifying the original"]
2567+
#[rustc_allow_const_fn_unstable(const_bigint_helper_methods)]
2568+
#[inline]
2569+
pub const fn widening_mul(self, rhs: Self) -> ($UnsignedT, Self) {
2570+
self.widening_mul_impl(rhs)
2571+
}
2572+
2573+
/// Calculates the "full multiplication" `self * rhs + carry`
2574+
/// without the possibility to overflow.
2575+
///
2576+
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
2577+
/// of the result as two separate values, in that order.
2578+
///
2579+
/// Performs "long multiplication" which takes in an extra amount to add, and may return an
2580+
/// additional amount of overflow. This allows for chaining together multiple
2581+
/// multiplications to create "big integers" which represent larger values.
2582+
///
2583+
/// If you don't need the `carry`, then you can use [`Self::widening_mul`] instead.
2584+
///
2585+
/// # Examples
2586+
///
2587+
/// Basic usage:
2588+
///
2589+
/// Please note that this example is shared between integer types.
2590+
/// Which explains why `i32` is used here.
2591+
///
2592+
/// ```
2593+
/// #![feature(bigint_helper_methods)]
2594+
/// assert_eq!(5i32.carrying_mul(-2, 0), (4294967286, -1));
2595+
/// assert_eq!(5i32.carrying_mul(-2, 10), (0, 0));
2596+
/// assert_eq!(1_000_000_000i32.carrying_mul(-10, 0), (2884901888, -3));
2597+
/// assert_eq!(1_000_000_000i32.carrying_mul(-10, 10), (2884901898, -3));
2598+
#[doc = concat!("assert_eq!(",
2599+
stringify!($SelfT), "::MAX.carrying_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ",
2600+
"(", stringify!($SelfT), "::MAX.unsigned_abs() + 1, ", stringify!($SelfT), "::MAX / 2));"
2601+
)]
2602+
/// ```
2603+
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
2604+
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
2605+
#[must_use = "this returns the result of the operation, \
2606+
without modifying the original"]
2607+
#[rustc_allow_const_fn_unstable(const_bigint_helper_methods)]
2608+
#[inline]
2609+
pub const fn carrying_mul(self, rhs: Self, carry: Self) -> ($UnsignedT, Self) {
2610+
self.carrying_mul_impl(rhs, carry)
2611+
}
2612+
2613+
/// Calculates the "full multiplication" `self * rhs + carry1 + carry2`
2614+
/// without the possibility to overflow.
2615+
///
2616+
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
2617+
/// of the result as two separate values, in that order.
2618+
///
2619+
/// Performs "long multiplication" which takes in an extra amount to add, and may return an
2620+
/// additional amount of overflow. This allows for chaining together multiple
2621+
/// multiplications to create "big integers" which represent larger values.
2622+
///
2623+
/// If you don't need either `carry`, then you can use [`Self::widening_mul`] instead,
2624+
/// and if you only need one `carry`, then you can use [`Self::carrying_mul`] instead.
2625+
///
2626+
/// # Examples
2627+
///
2628+
/// Basic usage:
2629+
///
2630+
/// Please note that this example is shared between integer types.
2631+
/// Which explains why `i32` is used here.
2632+
///
2633+
/// ```
2634+
/// #![feature(bigint_helper_methods)]
2635+
/// assert_eq!(5i32.carrying2_mul(-2, 0, 0), (4294967286, -1));
2636+
/// assert_eq!(5i32.carrying2_mul(-2, 10, 10), (10, 0));
2637+
/// assert_eq!(1_000_000_000i32.carrying2_mul(-10, 0, 0), (2884901888, -3));
2638+
/// assert_eq!(1_000_000_000i32.carrying2_mul(-10, 10, 10), (2884901908, -3));
2639+
#[doc = concat!("assert_eq!(",
2640+
stringify!($SelfT), "::MAX.carrying2_mul(", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX, ", stringify!($SelfT), "::MAX), ",
2641+
"(", stringify!($UnsignedT), "::MAX, ", stringify!($SelfT), "::MAX / 2));"
2642+
)]
2643+
/// ```
2644+
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
2645+
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
2646+
#[must_use = "this returns the result of the operation, \
2647+
without modifying the original"]
2648+
#[rustc_allow_const_fn_unstable(const_bigint_helper_methods)]
2649+
#[inline]
2650+
pub const fn carrying2_mul(self, rhs: Self, carry1: Self, carry2: Self) -> ($UnsignedT, Self) {
2651+
self.carrying2_mul_impl(rhs, carry1, carry2)
2652+
}
2653+
25432654
/// Calculates the divisor when `self` is divided by `rhs`.
25442655
///
25452656
/// Returns a tuple of the divisor along with a boolean indicating whether an arithmetic overflow would

0 commit comments

Comments
 (0)