-
Notifications
You must be signed in to change notification settings - Fork 146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document the Augmented enum in RealModule in advance of 1.0 #181
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,18 +9,85 @@ | |
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
/// A namespace for "augmented arithmetic" operations for types conforming to | ||
/// `Real`. | ||
/// | ||
/// Augmented arithmetic refers to a family of algorithms that represent | ||
/// the results of floating-point computations using multiple values such that | ||
/// either the error is minimized or the result is exact. | ||
public enum Augmented { } | ||
|
||
extension Augmented { | ||
/// The product `a * b` represented as an implicit sum `head + tail`. | ||
/// | ||
/// `head` is the correctly rounded value of `a*b`. If no overflow or | ||
/// underflow occurs, `tail` represents the rounding error incurred in | ||
/// computing `head`, such that the exact product is the sum of `head` | ||
/// and `tail` computed without rounding. | ||
/// | ||
/// This operation is sometimes called "twoProd" or "twoProduct". | ||
/// | ||
/// Edge Cases: | ||
/// - | ||
/// - `head` is always the IEEE 754 product `a * b`. | ||
/// - If `head` is not finite, `tail` is unspecified and should not be | ||
/// interpreted as having any meaning (it may be `NaN` or `infinity`). | ||
/// - When `head` is close to the underflow boundary, the rounding error | ||
/// may not be representable due to underflow, and `tail` will be rounded. | ||
/// If `head` is very small, `tail` may even be zero, even though the | ||
/// product is not exact. | ||
/// - If `head` is zero, `tail` is also a zero with unspecified sign. | ||
/// | ||
/// Postconditions: | ||
/// - | ||
/// - If `head` is normal, then `abs(tail) < abs(head.ulp)`. | ||
/// Assuming IEEE 754 default rounding, `abs(tail) <= abs(head.ulp)/2`. | ||
Comment on lines
+43
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are the “abs” on the right-hand sides necessary? I was under the impression that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's right (I'll roll this in with another upcoming PR) |
||
/// - If both `head` and `tail` are normal, then `a * b` is exactly | ||
/// equal to `head + tail` when computed as real numbers. | ||
@_transparent | ||
public static func twoProdFMA<T:Real>(_ a: T, _ b: T) -> (head: T, tail: T) { | ||
public static func product<T:Real>(_ a: T, _ b: T) -> (head: T, tail: T) { | ||
let head = a*b | ||
// TODO: consider providing an FMA-less implementation for use when | ||
// targeting platforms without hardware FMA support. This works everywhere, | ||
// falling back on the C math.h fma funcions, but may be slow on older x86. | ||
let tail = (-head).addingProduct(a, b) | ||
return (head, tail) | ||
} | ||
|
||
/// The sum `a + b` represented as an implicit sum `head + tail`. | ||
/// | ||
/// `head` is the correctly rounded value of `a + b`. `tail` is the | ||
/// error from that computation rounded to the closest representable | ||
/// value. | ||
/// | ||
/// Unlike `Augmented.product(a, b)`, the rounding error of a sum can | ||
/// never underflow. However, it may not be exactly representable when | ||
/// `a` and `b` differ widely in magnitude. | ||
/// | ||
/// This operation is sometimes called "fastTwoSum". | ||
/// | ||
/// - Parameters: | ||
/// - a: The summand with larger magnitude. | ||
/// - b: The summand with smaller magnitude. | ||
/// | ||
/// Preconditions: | ||
/// - | ||
/// - `large.magnitude` must not be smaller than `small.magnitude`. | ||
/// They may be equal, or one or both may be `NaN`. | ||
/// This precondition is only enforced in debug builds. | ||
/// | ||
/// Edge Cases: | ||
/// - | ||
/// - `head` is always the IEEE 754 sum `a + b`. | ||
/// - If `head` is not finite, `tail` is unspecified and should not be | ||
/// interpreted as having any meaning (it may be `NaN` or `infinity`). | ||
/// | ||
/// Postconditions: | ||
/// - | ||
/// - If `head` is normal, then `abs(tail) < abs(head.ulp)`. | ||
/// Assuming IEEE 754 default rounding, `abs(tail) <= abs(head.ulp)/2`. | ||
@_transparent | ||
public static func fastTwoSum<T:Real>(_ a: T, _ b: T) -> (head: T, tail: T) { | ||
public static func sum<T:Real>(large a: T, small b: T) -> (head: T, tail: T) { | ||
assert(!(b.magnitude > a.magnitude)) | ||
let head = a + b | ||
let tail = a - head + b | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a blank bullet here and also in some lists below. Is it intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this produces the desired formatting in Xcode: