@@ -95,6 +95,57 @@ depending on the target pointer size.
95
95
} ;
96
96
}
97
97
98
+ macro_rules! midpoint_impl {
99
+ ( $SelfT: ty, unsigned) => {
100
+ /// Calculates the middle point of `self` and `rhs`.
101
+ ///
102
+ /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
103
+ /// sufficiently-large signed integral type. This implies that the result is
104
+ /// always rounded towards negative infinity and that no overflow will ever occur.
105
+ ///
106
+ /// # Examples
107
+ ///
108
+ /// ```
109
+ /// #![feature(num_midpoint)]
110
+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".midpoint(4), 2);" ) ]
111
+ #[ doc = concat!( "assert_eq!(1" , stringify!( $SelfT) , ".midpoint(4), 2);" ) ]
112
+ /// ```
113
+ #[ unstable( feature = "num_midpoint" , issue = "110840" ) ]
114
+ #[ rustc_const_unstable( feature = "const_num_midpoint" , issue = "110840" ) ]
115
+ #[ must_use = "this returns the result of the operation, \
116
+ without modifying the original"]
117
+ #[ inline]
118
+ pub const fn midpoint( self , rhs: $SelfT) -> $SelfT {
119
+ // Use the well known branchless algorthim from Hacker's Delight to compute
120
+ // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`.
121
+ ( ( self ^ rhs) >> 1 ) + ( self & rhs)
122
+ }
123
+ } ;
124
+ ( $SelfT: ty, $WideT: ty, unsigned) => {
125
+ /// Calculates the middle point of `self` and `rhs`.
126
+ ///
127
+ /// `midpoint(a, b)` is `(a + b) >> 1` as if it were performed in a
128
+ /// sufficiently-large signed integral type. This implies that the result is
129
+ /// always rounded towards negative infinity and that no overflow will ever occur.
130
+ ///
131
+ /// # Examples
132
+ ///
133
+ /// ```
134
+ /// #![feature(num_midpoint)]
135
+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".midpoint(4), 2);" ) ]
136
+ #[ doc = concat!( "assert_eq!(1" , stringify!( $SelfT) , ".midpoint(4), 2);" ) ]
137
+ /// ```
138
+ #[ unstable( feature = "num_midpoint" , issue = "110840" ) ]
139
+ #[ rustc_const_unstable( feature = "const_num_midpoint" , issue = "110840" ) ]
140
+ #[ must_use = "this returns the result of the operation, \
141
+ without modifying the original"]
142
+ #[ inline]
143
+ pub const fn midpoint( self , rhs: $SelfT) -> $SelfT {
144
+ ( ( self as $WideT + rhs as $WideT) / 2 ) as $SelfT
145
+ }
146
+ } ;
147
+ }
148
+
98
149
macro_rules! widening_impl {
99
150
( $SelfT: ty, $WideT: ty, $BITS: literal, unsigned) => {
100
151
/// Calculates the complete product `self * rhs` without the possibility to overflow.
@@ -455,6 +506,7 @@ impl u8 {
455
506
bound_condition = "" ,
456
507
}
457
508
widening_impl ! { u8 , u16 , 8 , unsigned }
509
+ midpoint_impl ! { u8 , u16 , unsigned }
458
510
459
511
/// Checks if the value is within the ASCII range.
460
512
///
@@ -1057,6 +1109,7 @@ impl u16 {
1057
1109
bound_condition = "" ,
1058
1110
}
1059
1111
widening_impl ! { u16 , u32 , 16 , unsigned }
1112
+ midpoint_impl ! { u16 , u32 , unsigned }
1060
1113
1061
1114
/// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`].
1062
1115
///
@@ -1105,6 +1158,7 @@ impl u32 {
1105
1158
bound_condition = "" ,
1106
1159
}
1107
1160
widening_impl ! { u32 , u64 , 32 , unsigned }
1161
+ midpoint_impl ! { u32 , u64 , unsigned }
1108
1162
}
1109
1163
1110
1164
impl u64 {
@@ -1128,6 +1182,7 @@ impl u64 {
1128
1182
bound_condition = "" ,
1129
1183
}
1130
1184
widening_impl ! { u64 , u128 , 64 , unsigned }
1185
+ midpoint_impl ! { u64 , u128 , unsigned }
1131
1186
}
1132
1187
1133
1188
impl u128 {
@@ -1152,6 +1207,7 @@ impl u128 {
1152
1207
from_xe_bytes_doc = "" ,
1153
1208
bound_condition = "" ,
1154
1209
}
1210
+ midpoint_impl ! { u128 , unsigned }
1155
1211
}
1156
1212
1157
1213
#[ cfg( target_pointer_width = "16" ) ]
@@ -1176,6 +1232,7 @@ impl usize {
1176
1232
bound_condition = " on 16-bit targets" ,
1177
1233
}
1178
1234
widening_impl ! { usize , u32 , 16 , unsigned }
1235
+ midpoint_impl ! { usize , u32 , unsigned }
1179
1236
}
1180
1237
1181
1238
#[ cfg( target_pointer_width = "32" ) ]
@@ -1200,6 +1257,7 @@ impl usize {
1200
1257
bound_condition = " on 32-bit targets" ,
1201
1258
}
1202
1259
widening_impl ! { usize , u64 , 32 , unsigned }
1260
+ midpoint_impl ! { usize , u64 , unsigned }
1203
1261
}
1204
1262
1205
1263
#[ cfg( target_pointer_width = "64" ) ]
@@ -1224,6 +1282,7 @@ impl usize {
1224
1282
bound_condition = " on 64-bit targets" ,
1225
1283
}
1226
1284
widening_impl ! { usize , u128 , 64 , unsigned }
1285
+ midpoint_impl ! { usize , u128 , unsigned }
1227
1286
}
1228
1287
1229
1288
impl usize {
0 commit comments