@@ -95,6 +95,57 @@ depending on the target pointer size.
9595 } ;
9696}
9797
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+
98149macro_rules! widening_impl {
99150 ( $SelfT: ty, $WideT: ty, $BITS: literal, unsigned) => {
100151 /// Calculates the complete product `self * rhs` without the possibility to overflow.
@@ -455,6 +506,7 @@ impl u8 {
455506 bound_condition = "" ,
456507 }
457508 widening_impl ! { u8 , u16 , 8 , unsigned }
509+ midpoint_impl ! { u8 , u16 , unsigned }
458510
459511 /// Checks if the value is within the ASCII range.
460512 ///
@@ -1057,6 +1109,7 @@ impl u16 {
10571109 bound_condition = "" ,
10581110 }
10591111 widening_impl ! { u16 , u32 , 16 , unsigned }
1112+ midpoint_impl ! { u16 , u32 , unsigned }
10601113
10611114 /// Checks if the value is a Unicode surrogate code point, which are disallowed values for [`char`].
10621115 ///
@@ -1105,6 +1158,7 @@ impl u32 {
11051158 bound_condition = "" ,
11061159 }
11071160 widening_impl ! { u32 , u64 , 32 , unsigned }
1161+ midpoint_impl ! { u32 , u64 , unsigned }
11081162}
11091163
11101164impl u64 {
@@ -1128,6 +1182,7 @@ impl u64 {
11281182 bound_condition = "" ,
11291183 }
11301184 widening_impl ! { u64 , u128 , 64 , unsigned }
1185+ midpoint_impl ! { u64 , u128 , unsigned }
11311186}
11321187
11331188impl u128 {
@@ -1152,6 +1207,7 @@ impl u128 {
11521207 from_xe_bytes_doc = "" ,
11531208 bound_condition = "" ,
11541209 }
1210+ midpoint_impl ! { u128 , unsigned }
11551211}
11561212
11571213#[ cfg( target_pointer_width = "16" ) ]
@@ -1176,6 +1232,7 @@ impl usize {
11761232 bound_condition = " on 16-bit targets" ,
11771233 }
11781234 widening_impl ! { usize , u32 , 16 , unsigned }
1235+ midpoint_impl ! { usize , u32 , unsigned }
11791236}
11801237
11811238#[ cfg( target_pointer_width = "32" ) ]
@@ -1200,6 +1257,7 @@ impl usize {
12001257 bound_condition = " on 32-bit targets" ,
12011258 }
12021259 widening_impl ! { usize , u64 , 32 , unsigned }
1260+ midpoint_impl ! { usize , u64 , unsigned }
12031261}
12041262
12051263#[ cfg( target_pointer_width = "64" ) ]
@@ -1224,6 +1282,7 @@ impl usize {
12241282 bound_condition = " on 64-bit targets" ,
12251283 }
12261284 widening_impl ! { usize , u128 , 64 , unsigned }
1285+ midpoint_impl ! { usize , u128 , unsigned }
12271286}
12281287
12291288impl usize {
0 commit comments