Skip to content

Commit 5b825d2

Browse files
committed
Tidy up bigint mul implementations
1 parent 20c909f commit 5b825d2

File tree

12 files changed

+579
-125
lines changed

12 files changed

+579
-125
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
@@ -2539,6 +2539,117 @@ macro_rules! int_impl {
25392539
(a as Self, b)
25402540
}
25412541

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

0 commit comments

Comments
 (0)