@@ -89,27 +89,104 @@ depending on the target pointer size.
8989 } ;
9090}
9191
92+ macro_rules! widening_impl {
93+ ( $SelfT: ty, $WideT: ty, $BITS: literal) => {
94+ /// Calculates the complete product `self * rhs` without the possibility to overflow.
95+ ///
96+ /// This returns the low-order (wrapping) bits and the high-order (overflow) bits
97+ /// of the result as two separate values, in that order.
98+ ///
99+ /// # Examples
100+ ///
101+ /// Basic usage:
102+ ///
103+ /// Please note that this example is shared between integer types.
104+ /// Which explains why `u32` is used here.
105+ ///
106+ /// ```
107+ /// #![feature(bigint_helper_methods)]
108+ /// assert_eq!(5u32.widening_mul(2), (10, 0));
109+ /// assert_eq!(1_000_000_000u32.widening_mul(10), (1410065408, 2));
110+ /// ```
111+ #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
112+ #[ rustc_const_unstable( feature = "const_bigint_helper_methods" , issue = "85532" ) ]
113+ #[ must_use = "this returns the result of the operation, \
114+ without modifying the original"]
115+ #[ inline]
116+ pub const fn widening_mul( self , rhs: Self ) -> ( Self , Self ) {
117+ // note: longer-term this should be done via an intrinsic,
118+ // but for now we can deal without an impl for u128/i128
119+ // SAFETY: overflow will be contained within the wider types
120+ let wide = unsafe { ( self as $WideT) . unchecked_mul( rhs as $WideT) } ;
121+ ( wide as $SelfT, ( wide >> $BITS) as $SelfT)
122+ }
123+
124+ /// Calculates the "full multiplication" `self * rhs + carry`
125+ /// without the possibility to overflow.
126+ ///
127+ /// This returns the low-order (wrapping) bits and the high-order (overflow) bits
128+ /// of the result as two separate values, in that order.
129+ ///
130+ /// Performs "long multiplication" which takes in an extra amount to add, and may return an
131+ /// additional amount of overflow. This allows for chaining together multiple
132+ /// multiplications to create "big integers" which represent larger values.
133+ ///
134+ /// # Examples
135+ ///
136+ /// Basic usage:
137+ ///
138+ /// Please note that this example is shared between integer types.
139+ /// Which explains why `u32` is used here.
140+ ///
141+ /// ```
142+ /// #![feature(bigint_helper_methods)]
143+ /// assert_eq!(5u32.carrying_mul(2, 0), (10, 0));
144+ /// assert_eq!(5u32.carrying_mul(2, 10), (20, 0));
145+ /// assert_eq!(1_000_000_000u32.carrying_mul(10, 0), (1410065408, 2));
146+ /// assert_eq!(1_000_000_000u32.carrying_mul(10, 10), (1410065418, 2));
147+ /// ```
148+ #[ unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
149+ #[ rustc_const_unstable( feature = "bigint_helper_methods" , issue = "85532" ) ]
150+ #[ must_use = "this returns the result of the operation, \
151+ without modifying the original"]
152+ #[ inline]
153+ pub const fn carrying_mul( self , rhs: Self , carry: Self ) -> ( Self , Self ) {
154+ // note: longer-term this should be done via an intrinsic,
155+ // but for now we can deal without an impl for u128/i128
156+ // SAFETY: overflow will be contained within the wider types
157+ let wide = unsafe {
158+ ( self as $WideT) . unchecked_mul( rhs as $WideT) . unchecked_add( carry as $WideT)
159+ } ;
160+ ( wide as $SelfT, ( wide >> $BITS) as $SelfT)
161+ }
162+ } ;
163+ }
164+
92165#[ lang = "i8" ]
93166impl i8 {
167+ widening_impl ! { i8 , i16 , 8 }
94168 int_impl ! { i8 , i8 , u8 , 8 , 7 , -128 , 127 , 2 , "-0x7e" , "0xa" , "0x12" , "0x12" , "0x48" ,
95169 "[0x12]" , "[0x12]" , "" , "" }
96170}
97171
98172#[ lang = "i16" ]
99173impl i16 {
174+ widening_impl ! { i16 , i32 , 16 }
100175 int_impl ! { i16 , i16 , u16 , 16 , 15 , -32768 , 32767 , 4 , "-0x5ffd" , "0x3a" , "0x1234" , "0x3412" ,
101176 "0x2c48" , "[0x34, 0x12]" , "[0x12, 0x34]" , "" , "" }
102177}
103178
104179#[ lang = "i32" ]
105180impl i32 {
181+ widening_impl ! { i32 , i64 , 32 }
106182 int_impl ! { i32 , i32 , u32 , 32 , 31 , -2147483648 , 2147483647 , 8 , "0x10000b3" , "0xb301" ,
107183 "0x12345678" , "0x78563412" , "0x1e6a2c48" , "[0x78, 0x56, 0x34, 0x12]" ,
108184 "[0x12, 0x34, 0x56, 0x78]" , "" , "" }
109185}
110186
111187#[ lang = "i64" ]
112188impl i64 {
189+ widening_impl ! { i64 , i128 , 64 }
113190 int_impl ! { i64 , i64 , u64 , 64 , 63 , -9223372036854775808 , 9223372036854775807 , 12 ,
114191 "0xaa00000000006e1" , "0x6e10aa" , "0x1234567890123456" , "0x5634129078563412" ,
115192 "0x6a2c48091e6a2c48" , "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" ,
@@ -131,6 +208,7 @@ impl i128 {
131208#[ cfg( target_pointer_width = "16" ) ]
132209#[ lang = "isize" ]
133210impl isize {
211+ widening_impl ! { isize , i32 , 16 }
134212 int_impl ! { isize , i16 , usize , 16 , 15 , -32768 , 32767 , 4 , "-0x5ffd" , "0x3a" , "0x1234" ,
135213 "0x3412" , "0x2c48" , "[0x34, 0x12]" , "[0x12, 0x34]" ,
136214 usize_isize_to_xe_bytes_doc!( ) , usize_isize_from_xe_bytes_doc!( ) }
@@ -139,6 +217,7 @@ impl isize {
139217#[ cfg( target_pointer_width = "32" ) ]
140218#[ lang = "isize" ]
141219impl isize {
220+ widening_impl ! { isize , i64 , 32 }
142221 int_impl ! { isize , i32 , usize , 32 , 31 , -2147483648 , 2147483647 , 8 , "0x10000b3" , "0xb301" ,
143222 "0x12345678" , "0x78563412" , "0x1e6a2c48" , "[0x78, 0x56, 0x34, 0x12]" ,
144223 "[0x12, 0x34, 0x56, 0x78]" ,
@@ -148,6 +227,7 @@ impl isize {
148227#[ cfg( target_pointer_width = "64" ) ]
149228#[ lang = "isize" ]
150229impl isize {
230+ widening_impl ! { isize , i128 , 64 }
151231 int_impl ! { isize , i64 , usize , 64 , 63 , -9223372036854775808 , 9223372036854775807 ,
152232 12 , "0xaa00000000006e1" , "0x6e10aa" , "0x1234567890123456" , "0x5634129078563412" ,
153233 "0x6a2c48091e6a2c48" , "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" ,
@@ -160,6 +240,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000;
160240
161241#[ lang = "u8" ]
162242impl u8 {
243+ widening_impl ! { u8 , u16 , 8 }
163244 uint_impl ! { u8 , u8 , 8 , 255 , 2 , "0x82" , "0xa" , "0x12" , "0x12" , "0x48" , "[0x12]" ,
164245 "[0x12]" , "" , "" }
165246
@@ -693,18 +774,21 @@ impl u8 {
693774
694775#[ lang = "u16" ]
695776impl u16 {
777+ widening_impl ! { u16 , u32 , 16 }
696778 uint_impl ! { u16 , u16 , 16 , 65535 , 4 , "0xa003" , "0x3a" , "0x1234" , "0x3412" , "0x2c48" ,
697779 "[0x34, 0x12]" , "[0x12, 0x34]" , "" , "" }
698780}
699781
700782#[ lang = "u32" ]
701783impl u32 {
784+ widening_impl ! { u32 , u64 , 32 }
702785 uint_impl ! { u32 , u32 , 32 , 4294967295 , 8 , "0x10000b3" , "0xb301" , "0x12345678" ,
703786 "0x78563412" , "0x1e6a2c48" , "[0x78, 0x56, 0x34, 0x12]" , "[0x12, 0x34, 0x56, 0x78]" , "" , "" }
704787}
705788
706789#[ lang = "u64" ]
707790impl u64 {
791+ widening_impl ! { u64 , u128 , 64 }
708792 uint_impl ! { u64 , u64 , 64 , 18446744073709551615 , 12 , "0xaa00000000006e1" , "0x6e10aa" ,
709793 "0x1234567890123456" , "0x5634129078563412" , "0x6a2c48091e6a2c48" ,
710794 "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" ,
@@ -727,13 +811,15 @@ impl u128 {
727811#[ cfg( target_pointer_width = "16" ) ]
728812#[ lang = "usize" ]
729813impl usize {
814+ widening_impl ! { usize , u32 , 16 }
730815 uint_impl ! { usize , u16 , 16 , 65535 , 4 , "0xa003" , "0x3a" , "0x1234" , "0x3412" , "0x2c48" ,
731816 "[0x34, 0x12]" , "[0x12, 0x34]" ,
732817 usize_isize_to_xe_bytes_doc!( ) , usize_isize_from_xe_bytes_doc!( ) }
733818}
734819#[ cfg( target_pointer_width = "32" ) ]
735820#[ lang = "usize" ]
736821impl usize {
822+ widening_impl ! { usize , u64 , 32 }
737823 uint_impl ! { usize , u32 , 32 , 4294967295 , 8 , "0x10000b3" , "0xb301" , "0x12345678" ,
738824 "0x78563412" , "0x1e6a2c48" , "[0x78, 0x56, 0x34, 0x12]" , "[0x12, 0x34, 0x56, 0x78]" ,
739825 usize_isize_to_xe_bytes_doc!( ) , usize_isize_from_xe_bytes_doc!( ) }
@@ -742,6 +828,7 @@ impl usize {
742828#[ cfg( target_pointer_width = "64" ) ]
743829#[ lang = "usize" ]
744830impl usize {
831+ widening_impl ! { usize , u128 , 64 }
745832 uint_impl ! { usize , u64 , 64 , 18446744073709551615 , 12 , "0xaa00000000006e1" , "0x6e10aa" ,
746833 "0x1234567890123456" , "0x5634129078563412" , "0x6a2c48091e6a2c48" ,
747834 "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" ,
0 commit comments