@@ -124,6 +124,37 @@ macro_rules! midpoint_impl {
124124 ( ( self ^ rhs) >> 1 ) + ( self & rhs)
125125 }
126126 } ;
127+ ( $SelfT: ty, signed) => {
128+ /// Calculates the middle point of `self` and `rhs`.
129+ ///
130+ /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
131+ /// sufficiently-large signed integral type. This implies that the result is
132+ /// always rounded towards zero and that no overflow will ever occur.
133+ ///
134+ /// # Examples
135+ ///
136+ /// ```
137+ /// #![feature(num_midpoint)]
138+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".midpoint(4), 2);" ) ]
139+ #[ doc = concat!( "assert_eq!((-1" , stringify!( $SelfT) , ").midpoint(2), 0);" ) ]
140+ #[ doc = concat!( "assert_eq!((-7" , stringify!( $SelfT) , ").midpoint(0), -3);" ) ]
141+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".midpoint(-7), -3);" ) ]
142+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".midpoint(7), 3);" ) ]
143+ /// ```
144+ #[ unstable( feature = "num_midpoint" , issue = "110840" ) ]
145+ #[ rustc_const_unstable( feature = "const_num_midpoint" , issue = "110840" ) ]
146+ #[ must_use = "this returns the result of the operation, \
147+ without modifying the original"]
148+ #[ inline]
149+ pub const fn midpoint( self , rhs: Self ) -> Self {
150+ // Use the well known branchless algorithm from Hacker's Delight to compute
151+ // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`.
152+ let t = ( ( self ^ rhs) >> 1 ) + ( self & rhs) ;
153+ // Except that it fails for integers whose sum is an odd negative number as
154+ // their floor is one less than their average. So we adjust the result.
155+ t + ( if t < 0 { 1 } else { 0 } & ( self ^ rhs) )
156+ }
157+ } ;
127158 ( $SelfT: ty, $WideT: ty, unsigned) => {
128159 /// Calculates the middle point of `self` and `rhs`.
129160 ///
@@ -147,6 +178,32 @@ macro_rules! midpoint_impl {
147178 ( ( self as $WideT + rhs as $WideT) / 2 ) as $SelfT
148179 }
149180 } ;
181+ ( $SelfT: ty, $WideT: ty, signed) => {
182+ /// Calculates the middle point of `self` and `rhs`.
183+ ///
184+ /// `midpoint(a, b)` is `(a + b) / 2` as if it were performed in a
185+ /// sufficiently-large signed integral type. This implies that the result is
186+ /// always rounded towards zero and that no overflow will ever occur.
187+ ///
188+ /// # Examples
189+ ///
190+ /// ```
191+ /// #![feature(num_midpoint)]
192+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".midpoint(4), 2);" ) ]
193+ #[ doc = concat!( "assert_eq!((-1" , stringify!( $SelfT) , ").midpoint(2), 0);" ) ]
194+ #[ doc = concat!( "assert_eq!((-7" , stringify!( $SelfT) , ").midpoint(0), -3);" ) ]
195+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".midpoint(-7), -3);" ) ]
196+ #[ doc = concat!( "assert_eq!(0" , stringify!( $SelfT) , ".midpoint(7), 3);" ) ]
197+ /// ```
198+ #[ unstable( feature = "num_midpoint" , issue = "110840" ) ]
199+ #[ rustc_const_unstable( feature = "const_num_midpoint" , issue = "110840" ) ]
200+ #[ must_use = "this returns the result of the operation, \
201+ without modifying the original"]
202+ #[ inline]
203+ pub const fn midpoint( self , rhs: $SelfT) -> $SelfT {
204+ ( ( self as $WideT + rhs as $WideT) / 2 ) as $SelfT
205+ }
206+ } ;
150207}
151208
152209macro_rules! widening_impl {
@@ -300,6 +357,7 @@ impl i8 {
300357 from_xe_bytes_doc = "" ,
301358 bound_condition = "" ,
302359 }
360+ midpoint_impl ! { i8 , i16 , signed }
303361}
304362
305363impl i16 {
@@ -323,6 +381,7 @@ impl i16 {
323381 from_xe_bytes_doc = "" ,
324382 bound_condition = "" ,
325383 }
384+ midpoint_impl ! { i16 , i32 , signed }
326385}
327386
328387impl i32 {
@@ -346,6 +405,7 @@ impl i32 {
346405 from_xe_bytes_doc = "" ,
347406 bound_condition = "" ,
348407 }
408+ midpoint_impl ! { i32 , i64 , signed }
349409}
350410
351411impl i64 {
@@ -369,6 +429,7 @@ impl i64 {
369429 from_xe_bytes_doc = "" ,
370430 bound_condition = "" ,
371431 }
432+ midpoint_impl ! { i64 , i128 , signed }
372433}
373434
374435impl i128 {
@@ -394,6 +455,7 @@ impl i128 {
394455 from_xe_bytes_doc = "" ,
395456 bound_condition = "" ,
396457 }
458+ midpoint_impl ! { i128 , signed }
397459}
398460
399461#[ cfg( target_pointer_width = "16" ) ]
@@ -418,6 +480,7 @@ impl isize {
418480 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!( ) ,
419481 bound_condition = " on 16-bit targets" ,
420482 }
483+ midpoint_impl ! { isize , i32 , signed }
421484}
422485
423486#[ cfg( target_pointer_width = "32" ) ]
@@ -442,6 +505,7 @@ impl isize {
442505 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!( ) ,
443506 bound_condition = " on 32-bit targets" ,
444507 }
508+ midpoint_impl ! { isize , i64 , signed }
445509}
446510
447511#[ cfg( target_pointer_width = "64" ) ]
@@ -466,6 +530,7 @@ impl isize {
466530 from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!( ) ,
467531 bound_condition = " on 64-bit targets" ,
468532 }
533+ midpoint_impl ! { isize , i128 , signed }
469534}
470535
471536/// If the 6th bit is set ascii is lower case.
0 commit comments