@@ -64,7 +64,7 @@ extension Augmented {
64
64
/// never underflow. However, it may not be exactly representable when
65
65
/// `a` and `b` differ widely in magnitude.
66
66
///
67
- /// This operation is sometimes called "fastTwoSum".
67
+ /// This operation is sometimes called [ "fastTwoSum"] .
68
68
///
69
69
/// - Parameters:
70
70
/// - a: The summand with larger magnitude.
@@ -86,11 +86,60 @@ extension Augmented {
86
86
/// -
87
87
/// - If `head` is normal, then `abs(tail) < head.ulp`.
88
88
/// Assuming IEEE 754 default rounding, `abs(tail) <= head.ulp/2`.
89
+ ///
90
+ /// ["fastTwoSum"]: https://en.wikipedia.org/wiki/2Sum
89
91
@_transparent
90
92
public static func sum< T: Real > ( large a: T , small b: T ) -> ( head: T , tail: T ) {
91
93
assert ( !( b. magnitude > a. magnitude) )
92
94
let head = a + b
93
95
let tail = a - head + b
94
96
return ( head, tail)
95
97
}
98
+
99
+ /// The sum `a + b` represented as an implicit sum `head + tail`.
100
+ ///
101
+ /// `head` is the correctly rounded value of `a + b`. `tail` is the
102
+ /// error from that computation rounded to the closest representable
103
+ /// value.
104
+ ///
105
+ /// Unlike `Augmented.sum(large:, small:)`, the magnitude of the summands
106
+ /// does not matter. `a.magnitude` might as well be smaller than
107
+ /// `b.magnitude` – and vice versa. However, it is recommended to only use
108
+ /// this function over `Augmented.sum(large:, small:)` in cases where the
109
+ /// ordering of the summands magnitude is unknown at compile time. In cases
110
+ /// where either of the summands magnitude is known to be greater than or
111
+ /// equal the magnitude of the other summand, use
112
+ /// `Augmented.sum(large:, small:)` over this function; as it faster to
113
+ /// calculate.
114
+ ///
115
+ /// Unlike `Augmented.product(a, b)`, the rounding error of a sum can
116
+ /// never underflow. However, it may not be exactly representable when
117
+ /// `a` and `b` differ widely in magnitude.
118
+ ///
119
+ /// This operation is sometimes called ["twoSum"].
120
+ ///
121
+ /// - Parameters:
122
+ /// - a: One of the summand
123
+ /// - b: The other summand
124
+ ///
125
+ /// Edge Cases:
126
+ /// -
127
+ /// - `head` is always the IEEE 754 sum `a + b`.
128
+ /// - If `head` is not finite, `tail` is unspecified and should not be
129
+ /// interpreted as having any meaning (it may be `NaN` or `infinity`).
130
+ ///
131
+ /// Postconditions:
132
+ /// -
133
+ /// - If `head` is normal, then `abs(tail) < head.ulp`.
134
+ /// Assuming IEEE 754 default rounding, `abs(tail) <= head.ulp/2`.
135
+ ///
136
+ /// ["twoSum"]: https://en.wikipedia.org/wiki/2Sum
137
+ @_transparent
138
+ public static func sum< T: Real > ( _ a: T , _ b: T ) -> ( head: T , tail: T ) {
139
+ let head = a + b
140
+ let x = head - a
141
+ let y = head - x
142
+ let tail = ( a - x) + ( b - y)
143
+ return ( head, tail)
144
+ }
96
145
}
0 commit comments