@@ -89,27 +89,104 @@ depending on the target pointer size.
89
89
} ;
90
90
}
91
91
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
+
92
165
#[ lang = "i8" ]
93
166
impl i8 {
167
+ widening_impl ! { i8 , i16 , 8 }
94
168
int_impl ! { i8 , i8 , u8 , 8 , 7 , -128 , 127 , 2 , "-0x7e" , "0xa" , "0x12" , "0x12" , "0x48" ,
95
169
"[0x12]" , "[0x12]" , "" , "" }
96
170
}
97
171
98
172
#[ lang = "i16" ]
99
173
impl i16 {
174
+ widening_impl ! { i16 , i32 , 16 }
100
175
int_impl ! { i16 , i16 , u16 , 16 , 15 , -32768 , 32767 , 4 , "-0x5ffd" , "0x3a" , "0x1234" , "0x3412" ,
101
176
"0x2c48" , "[0x34, 0x12]" , "[0x12, 0x34]" , "" , "" }
102
177
}
103
178
104
179
#[ lang = "i32" ]
105
180
impl i32 {
181
+ widening_impl ! { i32 , i64 , 32 }
106
182
int_impl ! { i32 , i32 , u32 , 32 , 31 , -2147483648 , 2147483647 , 8 , "0x10000b3" , "0xb301" ,
107
183
"0x12345678" , "0x78563412" , "0x1e6a2c48" , "[0x78, 0x56, 0x34, 0x12]" ,
108
184
"[0x12, 0x34, 0x56, 0x78]" , "" , "" }
109
185
}
110
186
111
187
#[ lang = "i64" ]
112
188
impl i64 {
189
+ widening_impl ! { i64 , i128 , 64 }
113
190
int_impl ! { i64 , i64 , u64 , 64 , 63 , -9223372036854775808 , 9223372036854775807 , 12 ,
114
191
"0xaa00000000006e1" , "0x6e10aa" , "0x1234567890123456" , "0x5634129078563412" ,
115
192
"0x6a2c48091e6a2c48" , "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" ,
@@ -131,6 +208,7 @@ impl i128 {
131
208
#[ cfg( target_pointer_width = "16" ) ]
132
209
#[ lang = "isize" ]
133
210
impl isize {
211
+ widening_impl ! { isize , i32 , 16 }
134
212
int_impl ! { isize , i16 , usize , 16 , 15 , -32768 , 32767 , 4 , "-0x5ffd" , "0x3a" , "0x1234" ,
135
213
"0x3412" , "0x2c48" , "[0x34, 0x12]" , "[0x12, 0x34]" ,
136
214
usize_isize_to_xe_bytes_doc!( ) , usize_isize_from_xe_bytes_doc!( ) }
@@ -139,6 +217,7 @@ impl isize {
139
217
#[ cfg( target_pointer_width = "32" ) ]
140
218
#[ lang = "isize" ]
141
219
impl isize {
220
+ widening_impl ! { isize , i64 , 32 }
142
221
int_impl ! { isize , i32 , usize , 32 , 31 , -2147483648 , 2147483647 , 8 , "0x10000b3" , "0xb301" ,
143
222
"0x12345678" , "0x78563412" , "0x1e6a2c48" , "[0x78, 0x56, 0x34, 0x12]" ,
144
223
"[0x12, 0x34, 0x56, 0x78]" ,
@@ -148,6 +227,7 @@ impl isize {
148
227
#[ cfg( target_pointer_width = "64" ) ]
149
228
#[ lang = "isize" ]
150
229
impl isize {
230
+ widening_impl ! { isize , i128 , 64 }
151
231
int_impl ! { isize , i64 , usize , 64 , 63 , -9223372036854775808 , 9223372036854775807 ,
152
232
12 , "0xaa00000000006e1" , "0x6e10aa" , "0x1234567890123456" , "0x5634129078563412" ,
153
233
"0x6a2c48091e6a2c48" , "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" ,
@@ -160,6 +240,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000;
160
240
161
241
#[ lang = "u8" ]
162
242
impl u8 {
243
+ widening_impl ! { u8 , u16 , 8 }
163
244
uint_impl ! { u8 , u8 , 8 , 255 , 2 , "0x82" , "0xa" , "0x12" , "0x12" , "0x48" , "[0x12]" ,
164
245
"[0x12]" , "" , "" }
165
246
@@ -693,18 +774,21 @@ impl u8 {
693
774
694
775
#[ lang = "u16" ]
695
776
impl u16 {
777
+ widening_impl ! { u16 , u32 , 16 }
696
778
uint_impl ! { u16 , u16 , 16 , 65535 , 4 , "0xa003" , "0x3a" , "0x1234" , "0x3412" , "0x2c48" ,
697
779
"[0x34, 0x12]" , "[0x12, 0x34]" , "" , "" }
698
780
}
699
781
700
782
#[ lang = "u32" ]
701
783
impl u32 {
784
+ widening_impl ! { u32 , u64 , 32 }
702
785
uint_impl ! { u32 , u32 , 32 , 4294967295 , 8 , "0x10000b3" , "0xb301" , "0x12345678" ,
703
786
"0x78563412" , "0x1e6a2c48" , "[0x78, 0x56, 0x34, 0x12]" , "[0x12, 0x34, 0x56, 0x78]" , "" , "" }
704
787
}
705
788
706
789
#[ lang = "u64" ]
707
790
impl u64 {
791
+ widening_impl ! { u64 , u128 , 64 }
708
792
uint_impl ! { u64 , u64 , 64 , 18446744073709551615 , 12 , "0xaa00000000006e1" , "0x6e10aa" ,
709
793
"0x1234567890123456" , "0x5634129078563412" , "0x6a2c48091e6a2c48" ,
710
794
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" ,
@@ -727,13 +811,15 @@ impl u128 {
727
811
#[ cfg( target_pointer_width = "16" ) ]
728
812
#[ lang = "usize" ]
729
813
impl usize {
814
+ widening_impl ! { usize , u32 , 16 }
730
815
uint_impl ! { usize , u16 , 16 , 65535 , 4 , "0xa003" , "0x3a" , "0x1234" , "0x3412" , "0x2c48" ,
731
816
"[0x34, 0x12]" , "[0x12, 0x34]" ,
732
817
usize_isize_to_xe_bytes_doc!( ) , usize_isize_from_xe_bytes_doc!( ) }
733
818
}
734
819
#[ cfg( target_pointer_width = "32" ) ]
735
820
#[ lang = "usize" ]
736
821
impl usize {
822
+ widening_impl ! { usize , u64 , 32 }
737
823
uint_impl ! { usize , u32 , 32 , 4294967295 , 8 , "0x10000b3" , "0xb301" , "0x12345678" ,
738
824
"0x78563412" , "0x1e6a2c48" , "[0x78, 0x56, 0x34, 0x12]" , "[0x12, 0x34, 0x56, 0x78]" ,
739
825
usize_isize_to_xe_bytes_doc!( ) , usize_isize_from_xe_bytes_doc!( ) }
@@ -742,6 +828,7 @@ impl usize {
742
828
#[ cfg( target_pointer_width = "64" ) ]
743
829
#[ lang = "usize" ]
744
830
impl usize {
831
+ widening_impl ! { usize , u128 , 64 }
745
832
uint_impl ! { usize , u64 , 64 , 18446744073709551615 , 12 , "0xaa00000000006e1" , "0x6e10aa" ,
746
833
"0x1234567890123456" , "0x5634129078563412" , "0x6a2c48091e6a2c48" ,
747
834
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]" ,
0 commit comments