@@ -203,134 +203,6 @@ macro_rules! midpoint_impl {
203203 } ;
204204}
205205
206- macro_rules! widening_impl {
207- ( $SelfT: ty, $WideT: ty, $BITS: literal, unsigned) => {
208- /// Calculates the complete product `self * rhs` without the possibility to overflow.
209- ///
210- /// This returns the low-order (wrapping) bits and the high-order (overflow) bits
211- /// of the result as two separate values, in that order.
212- ///
213- /// If you also need to add a carry to the wide result, then you want
214- /// [`Self::carrying_mul`] instead.
215- ///
216- /// # Examples
217- ///
218- /// Basic usage:
219- ///
220- /// Please note that this example is shared between integer types.
221- /// Which explains why `u32` is used here.
222- ///
223- /// ```
224- /// #![feature(bigint_helper_methods)]
225- /// assert_eq!(5u32.widening_mul(2), (10, 0));
226- /// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2));
227- /// ```
228- #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
229- #[ must_use = "this returns the result of the operation, \
230- without modifying the original"]
231- #[ inline]
232- pub const fn widening_mul( self , rhs: Self ) -> ( Self , Self ) {
233- // note: longer-term this should be done via an intrinsic,
234- // but for now we can deal without an impl for u128/i128
235- // SAFETY: overflow will be contained within the wider types
236- let wide = unsafe { ( self as $WideT) . unchecked_mul( rhs as $WideT) } ;
237- ( wide as $SelfT, ( wide >> $BITS) as $SelfT)
238- }
239-
240- /// Calculates the "full multiplication" `self * rhs + carry`
241- /// without the possibility to overflow.
242- ///
243- /// This returns the low-order (wrapping) bits and the high-order (overflow) bits
244- /// of the result as two separate values, in that order.
245- ///
246- /// Performs "long multiplication" which takes in an extra amount to add, and may return an
247- /// additional amount of overflow. This allows for chaining together multiple
248- /// multiplications to create "big integers" which represent larger values.
249- ///
250- /// If you don't need the `carry`, then you can use [`Self::widening_mul`] instead.
251- ///
252- /// # Examples
253- ///
254- /// Basic usage:
255- ///
256- /// Please note that this example is shared between integer types.
257- /// Which explains why `u32` is used here.
258- ///
259- /// ```
260- /// #![feature(bigint_helper_methods)]
261- /// assert_eq!(5u32.carrying_mul(2, 0), (10, 0));
262- /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0));
263- /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2));
264- /// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2));
265- #[ doc = concat!( "assert_eq!(" ,
266- stringify!( $SelfT) , "::MAX.carrying_mul(" , stringify!( $SelfT) , "::MAX, " , stringify!( $SelfT) , "::MAX), " ,
267- "(0, " , stringify!( $SelfT) , "::MAX));"
268- ) ]
269- /// ```
270- ///
271- /// This is the core operation needed for scalar multiplication when
272- /// implementing it for wider-than-native types.
273- ///
274- /// ```
275- /// #![feature(bigint_helper_methods)]
276- /// fn scalar_mul_eq(little_endian_digits: &mut Vec<u16>, multiplicand: u16) {
277- /// let mut carry = 0;
278- /// for d in little_endian_digits.iter_mut() {
279- /// (*d, carry) = d.carrying_mul(multiplicand, carry);
280- /// }
281- /// if carry != 0 {
282- /// little_endian_digits.push(carry);
283- /// }
284- /// }
285- ///
286- /// let mut v = vec![10, 20];
287- /// scalar_mul_eq(&mut v, 3);
288- /// assert_eq!(v, [30, 60]);
289- ///
290- /// assert_eq!(0x87654321_u64 * 0xFEED, 0x86D3D159E38D);
291- /// let mut v = vec![0x4321, 0x8765];
292- /// scalar_mul_eq(&mut v, 0xFEED);
293- /// assert_eq!(v, [0xE38D, 0xD159, 0x86D3]);
294- /// ```
295- ///
296- /// If `carry` is zero, this is similar to [`overflowing_mul`](Self::overflowing_mul),
297- /// except that it gives the value of the overflow instead of just whether one happened:
298- ///
299- /// ```
300- /// #![feature(bigint_helper_methods)]
301- /// let r = u8::carrying_mul(7, 13, 0);
302- /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(7, 13));
303- /// let r = u8::carrying_mul(13, 42, 0);
304- /// assert_eq!((r.0, r.1 != 0), u8::overflowing_mul(13, 42));
305- /// ```
306- ///
307- /// The value of the first field in the returned tuple matches what you'd get
308- /// by combining the [`wrapping_mul`](Self::wrapping_mul) and
309- /// [`wrapping_add`](Self::wrapping_add) methods:
310- ///
311- /// ```
312- /// #![feature(bigint_helper_methods)]
313- /// assert_eq!(
314- /// 789_u16.carrying_mul(456, 123).0,
315- /// 789_u16.wrapping_mul(456).wrapping_add(123),
316- /// );
317- /// ```
318- #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
319- #[ must_use = "this returns the result of the operation, \
320- without modifying the original"]
321- #[ inline]
322- pub const fn carrying_mul( self , rhs: Self , carry: Self ) -> ( Self , Self ) {
323- // note: longer-term this should be done via an intrinsic,
324- // but for now we can deal without an impl for u128/i128
325- // SAFETY: overflow will be contained within the wider types
326- let wide = unsafe {
327- ( self as $WideT) . unchecked_mul( rhs as $WideT) . unchecked_add( carry as $WideT)
328- } ;
329- ( wide as $SelfT, ( wide >> $BITS) as $SelfT)
330- }
331- } ;
332- }
333-
334206impl i8 {
335207 int_impl ! {
336208 Self = i8 ,
@@ -551,7 +423,6 @@ impl u8 {
551423 from_xe_bytes_doc = "" ,
552424 bound_condition = "" ,
553425 }
554- widening_impl ! { u8 , u16 , 8 , unsigned }
555426 midpoint_impl ! { u8 , u16 , unsigned }
556427
557428 /// Checks if the value is within the ASCII range.
@@ -1167,7 +1038,6 @@ impl u16 {
11671038 from_xe_bytes_doc = "" ,
11681039 bound_condition = "" ,
11691040 }
1170- widening_impl ! { u16 , u32 , 16 , unsigned }
11711041 midpoint_impl ! { u16 , u32 , unsigned }
11721042
11731043 /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`].
@@ -1215,7 +1085,6 @@ impl u32 {
12151085 from_xe_bytes_doc = "" ,
12161086 bound_condition = "" ,
12171087 }
1218- widening_impl ! { u32 , u64 , 32 , unsigned }
12191088 midpoint_impl ! { u32 , u64 , unsigned }
12201089}
12211090
@@ -1239,7 +1108,6 @@ impl u64 {
12391108 from_xe_bytes_doc = "" ,
12401109 bound_condition = "" ,
12411110 }
1242- widening_impl ! { u64 , u128 , 64 , unsigned }
12431111 midpoint_impl ! { u64 , u128 , unsigned }
12441112}
12451113
@@ -1289,7 +1157,6 @@ impl usize {
12891157 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!( ) ,
12901158 bound_condition = " on 16-bit targets" ,
12911159 }
1292- widening_impl ! { usize , u32 , 16 , unsigned }
12931160 midpoint_impl ! { usize , u32 , unsigned }
12941161}
12951162
@@ -1314,7 +1181,6 @@ impl usize {
13141181 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!( ) ,
13151182 bound_condition = " on 32-bit targets" ,
13161183 }
1317- widening_impl ! { usize , u64 , 32 , unsigned }
13181184 midpoint_impl ! { usize , u64 , unsigned }
13191185}
13201186
@@ -1339,7 +1205,6 @@ impl usize {
13391205 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!( ) ,
13401206 bound_condition = " on 64-bit targets" ,
13411207 }
1342- widening_impl ! { usize , u128 , 64 , unsigned }
13431208 midpoint_impl ! { usize , u128 , unsigned }
13441209}
13451210
0 commit comments