Skip to content

Commit d86286f

Browse files
committed
Remove precondition assert from Augmented.sum(large:small:)
This is potentially useful to identify some bugs, but there are also algorithms (notably Kahan summation) that can be written in terms of fast2sum but would fail this check. Rework documentation to account for the change.
1 parent c1e6972 commit d86286f

File tree

1 file changed

+18
-22
lines changed

1 file changed

+18
-22
lines changed

Sources/RealModule/AugmentedArithmetic.swift

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ extension Augmented {
5656

5757
/// The sum `a + b` represented as an implicit sum `head + tail`.
5858
///
59+
/// - Parameters:
60+
/// - a: The summand with larger magnitude.
61+
/// - b: The summand with smaller magnitude.
62+
///
5963
/// `head` is the correctly rounded value of `a + b`. `tail` is the
6064
/// error from that computation rounded to the closest representable
6165
/// value.
@@ -65,15 +69,13 @@ extension Augmented {
6569
///
6670
/// This operation is sometimes called ["fastTwoSum"].
6771
///
68-
/// - Parameters:
69-
/// - a: The summand with larger magnitude.
70-
/// - b: The summand with smaller magnitude.
71-
///
72-
/// Preconditions:
73-
///
74-
/// - `large.magnitude` must not be smaller than `small.magnitude`.
75-
/// They may be equal, or one or both may be `NaN`.
76-
/// This precondition is only enforced in debug builds.
72+
/// > Note:
73+
/// > `tail` is guaranteed to be the best approximation to the error of
74+
/// the sum only if `large.magnitude` >= `small.magnitude`. If this is
75+
/// not the case, then `head` is the correctly rounded sum, but `tail`
76+
/// is not guaranteed to be the exact error. If you do not know a priori
77+
/// how the magnitudes of `a` and `b` compare, you likely want to use
78+
/// ``sum(_:_:)`` instead.
7779
///
7880
/// Edge Cases:
7981
///
@@ -89,29 +91,23 @@ extension Augmented {
8991
/// ["fastTwoSum"]: https://en.wikipedia.org/wiki/2Sum
9092
@_transparent
9193
public static func sum<T:Real>(large a: T, small b: T) -> (head: T, tail: T) {
92-
assert(!(b.magnitude > a.magnitude))
9394
let head = a + b
9495
let tail = a - head + b
9596
return (head, tail)
9697
}
97-
98+
9899
/// The sum `a + b` represented as an implicit sum `head + tail`.
99100
///
100101
/// `head` is the correctly rounded value of `a + b`. `tail` is the
101102
/// error from that computation rounded to the closest representable
102103
/// value.
103104
///
104-
/// Unlike `Augmented.sum(large: a, small: b)`, the magnitude of the summands
105-
/// does not matter and `a.magnitude` might as well be strictly less than
106-
/// `b.magnitude`. However, it is recommended to only use this function over
107-
/// `Augmented.sum(large: a, small: b)` in cases where the ordering of the
108-
/// summands magnitude is unknown at compile time. In cases where either of
109-
/// the summands magnitude is guaranteed to be greater than or equal the
110-
/// magnitude of the other summand, use `Augmented.sum(large: a, small: b)`
111-
/// over this function; as it faster to calculate.
105+
/// Unlike ``sum(large:small:)``, the magnitude of the summands does not
106+
/// matter. If you know statically that `a.magnitude >= b.magnitude`, you
107+
/// should use ``sum(large:small:)``. If you do not have such a static
108+
/// bound, you should use this function instead.
112109
///
113-
/// Unlike `Augmented.product(a, b)`, the rounding error of a sum can
114-
/// never underflow.
110+
/// Unlike ``product(_:_:)``, the rounding error of a sum never underflows.
115111
///
116112
/// This operation is sometimes called ["twoSum"].
117113
///
@@ -126,7 +122,7 @@ extension Augmented {
126122
/// interpreted as having any meaning (it may be `NaN` or `infinity`).
127123
///
128124
/// Postconditions:
129-
///
125+
///
130126
/// - If `head` is normal, then `abs(tail) < head.ulp`.
131127
/// Assuming IEEE 754 default rounding, `abs(tail) <= head.ulp/2`.
132128
///

0 commit comments

Comments
 (0)