@@ -124,6 +124,37 @@ macro_rules! midpoint_impl {
124
124
( ( self ^ rhs) >> 1 ) + ( self & rhs)
125
125
}
126
126
} ;
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
+ } ;
127
158
( $SelfT: ty, $WideT: ty, unsigned) => {
128
159
/// Calculates the middle point of `self` and `rhs`.
129
160
///
@@ -147,6 +178,32 @@ macro_rules! midpoint_impl {
147
178
( ( self as $WideT + rhs as $WideT) / 2 ) as $SelfT
148
179
}
149
180
} ;
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
+ } ;
150
207
}
151
208
152
209
macro_rules! widening_impl {
@@ -300,6 +357,7 @@ impl i8 {
300
357
from_xe_bytes_doc = "" ,
301
358
bound_condition = "" ,
302
359
}
360
+ midpoint_impl ! { i8 , i16 , signed }
303
361
}
304
362
305
363
impl i16 {
@@ -323,6 +381,7 @@ impl i16 {
323
381
from_xe_bytes_doc = "" ,
324
382
bound_condition = "" ,
325
383
}
384
+ midpoint_impl ! { i16 , i32 , signed }
326
385
}
327
386
328
387
impl i32 {
@@ -346,6 +405,7 @@ impl i32 {
346
405
from_xe_bytes_doc = "" ,
347
406
bound_condition = "" ,
348
407
}
408
+ midpoint_impl ! { i32 , i64 , signed }
349
409
}
350
410
351
411
impl i64 {
@@ -369,6 +429,7 @@ impl i64 {
369
429
from_xe_bytes_doc = "" ,
370
430
bound_condition = "" ,
371
431
}
432
+ midpoint_impl ! { i64 , i128 , signed }
372
433
}
373
434
374
435
impl i128 {
@@ -394,6 +455,7 @@ impl i128 {
394
455
from_xe_bytes_doc = "" ,
395
456
bound_condition = "" ,
396
457
}
458
+ midpoint_impl ! { i128 , signed }
397
459
}
398
460
399
461
#[ cfg( target_pointer_width = "16" ) ]
@@ -418,6 +480,7 @@ impl isize {
418
480
from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!( ) ,
419
481
bound_condition = " on 16-bit targets" ,
420
482
}
483
+ midpoint_impl ! { isize , i32 , signed }
421
484
}
422
485
423
486
#[ cfg( target_pointer_width = "32" ) ]
@@ -442,6 +505,7 @@ impl isize {
442
505
from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!( ) ,
443
506
bound_condition = " on 32-bit targets" ,
444
507
}
508
+ midpoint_impl ! { isize , i64 , signed }
445
509
}
446
510
447
511
#[ cfg( target_pointer_width = "64" ) ]
@@ -466,6 +530,7 @@ impl isize {
466
530
from_xe_bytes_doc = usize_isize_from_xe_bytes_doc!( ) ,
467
531
bound_condition = " on 64-bit targets" ,
468
532
}
533
+ midpoint_impl ! { isize , i128 , signed }
469
534
}
470
535
471
536
/// If the 6th bit is set ascii is lower case.
0 commit comments