9
9
//
10
10
//===----------------------------------------------------------------------===//
11
11
12
- /// The average of `a` and `b`, rounded to an integer according to `rule`.
13
- ///
14
- /// Unlike commonly seen expressions such as `(a+b)/2` or `(a+b) >> 1` or
15
- /// `a + (b-a)/2` (all of which may overflow for fixed-width integers),
16
- /// this function never overflows, and the result is guaranteed to be
17
- /// representable in the result type.
18
- ///
19
- /// The default rounding rule is `.down`, which matches the behavior of
20
- /// `(a + b) >> 1` when that expression does not overflow. Rounding
21
- /// `.towardZero` matches the behavior of `(a + b)/2` when that expression
22
- /// does not overflow. All other rounding modes are supported.
23
- ///
24
- /// Rounding `.down` is generally most efficient; if you do not have a
25
- /// reason to chose a specific other rounding rule, you should use the
26
- /// default.
27
- @inlinable
28
- public func midpoint< T: BinaryInteger > (
29
- _ a: T ,
30
- _ b: T ,
31
- rounding rule: RoundingRule = . down
32
- ) -> T {
33
- // Isolate bits in a + b with weight 2, and those with weight 1.
34
- let twos = a & b
35
- let ones = a ^ b
36
- let floor = twos + ones >> 1
37
- let frac = ones & 1
38
- switch rule {
39
- case . down:
40
- return floor
41
- case . up:
42
- return floor + frac
43
- case . towardZero:
44
- return floor + ( floor < 0 ? frac : 0 )
45
- case . toNearestOrAwayFromZero:
46
- fallthrough
47
- case . awayFromZero:
48
- return floor + ( floor >= 0 ? frac : 0 )
49
- case . toNearestOrEven:
50
- return floor + ( floor & frac)
51
- case . toOdd:
52
- return floor + ( ~ floor & frac)
53
- case . stochastically:
54
- return floor + ( Bool . random ( ) ? frac : 0 )
55
- case . requireExact:
56
- precondition ( frac == 0 )
57
- return floor
58
- }
59
- }
60
-
61
12
/// The average of `a` and `b`, rounded to an integer according to `rule`.
62
13
///
63
14
/// Unlike commonly seen expressions such as `(a+b)/2` or `(a+b) >> 1` or
@@ -84,13 +35,19 @@ public func midpoint<T: FixedWidthInteger>(
84
35
let floor = twos &+ ones >> 1
85
36
let frac = ones & 1
86
37
switch rule {
38
+ case . toNearestOrDown:
39
+ fallthrough
87
40
case . down:
88
41
return floor
42
+ case . toNearestOrUp:
43
+ fallthrough
89
44
case . up:
90
45
return floor &+ frac
46
+ case . toNearestOrZero:
47
+ fallthrough
91
48
case . towardZero:
92
49
return floor &+ ( floor < 0 ? frac : 0 )
93
- case . toNearestOrAwayFromZero :
50
+ case . toNearestOrAway :
94
51
fallthrough
95
52
case . awayFromZero:
96
53
return floor &+ ( floor >= 0 ? frac : 0 )
@@ -105,4 +62,3 @@ public func midpoint<T: FixedWidthInteger>(
105
62
return floor
106
63
}
107
64
}
108
-
0 commit comments