mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Replace the non-generic tgmath functions with generic <T: FloatingPoint> implementations where possible, and move the global sqrt() operation into tgmath.
929 lines
34 KiB
Swift
929 lines
34 KiB
Swift
//===--- FloatingPoint.swift.gyb ------------------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
%{
|
|
|
|
from SwiftIntTypes import all_integer_types
|
|
|
|
# Number of bits in the Builtin.Word type
|
|
word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
|
|
|
|
}%
|
|
|
|
/// A floating-point type that provides most of the IEEE 754 basic (clause 5)
|
|
/// operations. The base, precision, and exponent range are not fixed in
|
|
/// any way by this protocol, but it enforces the basic requirements of
|
|
/// any IEEE 754 floating-point type.
|
|
///
|
|
/// The BinaryFloatingPoint protocol refines these requirements, adds some
|
|
/// additional operations that only make sense for a fixed radix, and also
|
|
/// provides default implementations of some of the FloatingPoint APIs.
|
|
public protocol FloatingPoint: Comparable, Arithmetic,
|
|
SignedNumber, Strideable {
|
|
|
|
/// An integer type that can represent any written exponent.
|
|
associatedtype Exponent: SignedInteger
|
|
|
|
/// Initialize from sign, exponent, and significand.
|
|
///
|
|
/// The result is:
|
|
///
|
|
/// ~~~
|
|
/// (sign == .minus ? -1 : 1) * significand * radix**exponent
|
|
/// ~~~
|
|
///
|
|
/// (where `**` is exponentiation) computed as if by a single correctly-
|
|
/// rounded floating-point operation. If this value is outside the
|
|
/// representable range of the type, overflow or underflow occurs, and zero,
|
|
/// a subnormal value, or infinity may result, as with any basic operation.
|
|
/// Other edge cases:
|
|
///
|
|
/// - If `significand` is zero or infinite, the result is zero or infinite,
|
|
/// regardless of the value of `exponent`.
|
|
///
|
|
/// - If `significand` is NaN, the result is NaN.
|
|
///
|
|
/// Note that for any floating-point `x` the result of
|
|
///
|
|
/// `Self(sign: x.sign,
|
|
/// exponent: x.exponent,
|
|
/// significand: x.significand)`
|
|
///
|
|
/// is "the same" as `x`; it is `x` canonicalized.
|
|
///
|
|
/// This initializer implements the IEEE 754 `scaleB` operation.
|
|
init(sign: FloatingPointSign, exponent: Exponent, significand: Self)
|
|
|
|
/// A floating point value whose exponent and significand are taken from
|
|
/// `magnitude` and whose sign is taken from `signOf`. Implements the
|
|
/// IEEE 754 `copysign` operation.
|
|
init(signOf: Self, magnitudeOf: Self)
|
|
|
|
% for src_ty in all_integer_types(word_bits):
|
|
/// `value` rounded to the closest representable `Self`.
|
|
init(_ value: ${src_ty.stdlib_name})
|
|
|
|
% end
|
|
/* TODO: Implement the following APIs once a revised integer protocol is
|
|
introduced that allows for them to be implemented. In particular, we
|
|
need to have an "index of most significant bit" operation and "get
|
|
absolute value as unsigned type" operation on the Integer protocol.
|
|
|
|
/// The closest representable value to the argument.
|
|
init<Source: Integer>(_ value: Source)
|
|
|
|
/// Fails if the argument cannot be exactly represented.
|
|
init?<Source: Integer>(exactly value: Source)
|
|
*/
|
|
|
|
/// 2 for binary floating-point types, 10 for decimal.
|
|
///
|
|
/// A conforming type may use any integer radix, but values other than
|
|
/// 2 or 10 are extraordinarily rare in practice.
|
|
static var radix: Int { get }
|
|
|
|
/// A quiet NaN (not-a-number). Compares not equal to every value,
|
|
/// including itself.
|
|
static var nan: Self { get }
|
|
|
|
/// A signaling NaN (not-a-number).
|
|
///
|
|
/// The default IEEE 754 behavior of operations involving a signaling NaN
|
|
/// is to raise the Invalid flag in the floating-point environment and
|
|
/// return a quiet NaN. Operations on types conforming to FloatingPoint
|
|
/// should support this behavior, but they might also support other options;
|
|
/// for example, it would be reasonable to implement alternative operations
|
|
/// in which operating on a signaling NaN is a `fatalError()` or results in
|
|
/// a diagnostic for debugging purposes.
|
|
static var signalingNaN: Self { get }
|
|
|
|
/// Positive infinity. Compares greater than all finite numbers.
|
|
static var infinity: Self { get }
|
|
|
|
/// The greatest finite number.
|
|
///
|
|
/// Compares greater than or equal to all finite numbers, but less than
|
|
/// infinity. Corresponds to the C macros `FLT_MAX`, `DBL_MAX`, etc.
|
|
/// The naming of those macros is slightly misleading, because infinity
|
|
/// is greater than this value.
|
|
static var greatestFiniteMagnitude: Self { get }
|
|
|
|
/// The mathematical constant pi = 3.14159...
|
|
///
|
|
/// This value should be rounded towards zero to keep user computations
|
|
/// with angles from inadvertently ending up in the wrong quadrant.
|
|
///
|
|
/// Extensible floating-point types might provide additional APIs to obtain
|
|
/// this value to caller-specified precision.
|
|
static var pi: Self { get }
|
|
|
|
// NOTE: Rationale for "ulp" instead of "epsilon":
|
|
// We do not use that name because it is ambiguous at best and misleading
|
|
// at worst:
|
|
//
|
|
// - Historically several definitions of "machine epsilon" have commonly
|
|
// been used, which differ by up to a factor of two or so. By contrast
|
|
// "ulp" is a term with a specific unambiguous definition.
|
|
//
|
|
// - Some languages have used "epsilon" to refer to wildly different values,
|
|
// such as `leastNonzeroMagnitude`.
|
|
//
|
|
// - Inexperienced users often believe that "epsilon" should be used as a
|
|
// tolerance for floating-point comparisons, because of the name. It is
|
|
// nearly always the wrong value to use for this purpose.
|
|
|
|
/// The unit in the last place of `self`.
|
|
///
|
|
/// This is the unit of the least significant digit in the significand of
|
|
/// `self`. For most numbers `x`, this is the difference between `x` and
|
|
/// the next greater (in magnitude) representable number. There are some
|
|
/// edge cases to be aware of:
|
|
///
|
|
/// - `greatestFiniteMagnitude.ulp` is a finite number, even though
|
|
/// the next greater representable value is `infinity`.
|
|
/// - `x.ulp` is `NaN` if `x` is not a finite number.
|
|
/// - If `x` is very small in magnitude, then `x.ulp` may be a subnormal
|
|
/// number. On targets that do not support subnormals, `x.ulp` may be
|
|
/// flushed to zero.
|
|
///
|
|
/// This quantity, or a related quantity is sometimes called "epsilon" or
|
|
/// "machine epsilon". We avoid that name because it has different meanings
|
|
/// in different languages, which can lead to confusion, and because it
|
|
/// suggests that it is a good tolerance to use for comparisons,
|
|
/// which is almost never is.
|
|
///
|
|
/// (See https://en.wikipedia.org/wiki/Machine_epsilon for more detail)
|
|
var ulp: Self { get }
|
|
|
|
/// The unit in the last place of 1.0.
|
|
///
|
|
/// The positive difference between 1.0 and the next greater representable
|
|
/// number. Corresponds to the C macros `FLT_EPSILON`, `DBL_EPSILON`, etc.
|
|
static var ulpOfOne: Self { get }
|
|
|
|
/// The least positive normal number.
|
|
///
|
|
/// Compares less than or equal to all positive normal numbers. There may
|
|
/// be smaller positive numbers, but they are "subnormal", meaning that
|
|
/// they are represented with less precision than normal numbers.
|
|
/// Corresponds to the C macros `FLT_MIN`, `DBL_MIN`, etc. The naming of
|
|
/// those macros is slightly misleading, because subnormals, zeros, and
|
|
/// negative numbers are smaller than this value.
|
|
static var leastNormalMagnitude: Self { get }
|
|
|
|
/// The least positive number.
|
|
///
|
|
/// Compares less than or equal to all positive numbers, but greater than
|
|
/// zero. If the target supports subnormal values, this is smaller than
|
|
/// `leastNormalMagnitude`; otherwise they are equal.
|
|
static var leastNonzeroMagnitude: Self { get }
|
|
|
|
/// `minus` if the signbit of `self` is set, and `plus` otherwise.
|
|
/// Implements the IEEE 754 `signbit` operation.
|
|
///
|
|
/// Note that the property `x.sign == .minus` is not the same as `x < 0`.
|
|
/// In particular, `x < 0` while `x.sign == .minus` if `x` is -0, and while
|
|
/// `x < 0` is always false if `x` is NaN, `x.sign` could be either `.plus`
|
|
/// or `.minus`.
|
|
var sign: FloatingPointSign { get }
|
|
|
|
/// The integer part of the base-r logarithm of the magnitude of `self`,
|
|
/// where r is the radix (2 for binary, 10 for decimal). Implements the
|
|
/// IEEE 754 `logB` operation.
|
|
///
|
|
/// Edge cases:
|
|
///
|
|
/// - If `x` is zero, then `x.exponent` is `Int.min`.
|
|
/// - If `x` is +/-infinity or NaN, then `x.exponent` is `Int.max`
|
|
var exponent: Exponent { get }
|
|
|
|
/// The significand satisfies:
|
|
///
|
|
/// ~~~
|
|
/// self = (sign == .minus ? -1 : 1) * significand * radix**exponent
|
|
/// ~~~
|
|
///
|
|
/// (where `**` is exponentiation). If radix is 2, then for finite non-zero
|
|
/// numbers `1 <= significand` and `significand < 2`. For other values of
|
|
/// `x`, `x.significand` is defined as follows:
|
|
///
|
|
/// - If `x` is zero, then `x.significand` is 0.0.
|
|
/// - If `x` is infinity, then `x.significand` is 1.0.
|
|
/// - If `x` is NaN, then `x.significand` is NaN.
|
|
///
|
|
/// For all floating-point `x`, if we define y by:
|
|
///
|
|
/// ~~~
|
|
/// let y = Self(sign: x.sign, exponent: x.exponent,
|
|
/// significand: x.significand)
|
|
/// ~~~
|
|
///
|
|
/// then `y` is equivalent to `x`, meaning that `y` is `x` canonicalized.
|
|
var significand: Self { get }
|
|
|
|
/// Sum of `self` and `other` rounded to a representable value. The IEEE
|
|
/// 754 addition operation.
|
|
///
|
|
/// A default implementation is provided in terms of `add()`.
|
|
func adding(_ other: Self) -> Self
|
|
|
|
/// Replace `self` with the sum of `self` and `other` rounded to a
|
|
/// representable value.
|
|
mutating func add(_ other: Self)
|
|
|
|
/// Additive inverse of `self`. Always exact.
|
|
func negated() -> Self
|
|
|
|
/// Replace `self` with its additive inverse.
|
|
mutating func negate()
|
|
|
|
/// Sum of `self` and the additive inverse of `other` rounded to a
|
|
/// representable value. The IEEE 754 subtraction operation.
|
|
///
|
|
/// A default implementation is provided in terms of `subtract()`.
|
|
func subtracting(_ other: Self) -> Self
|
|
|
|
/// Replace `self` with the sum of `self` and the additive inverse of `other`
|
|
/// rounded to a representable value.
|
|
mutating func subtract(_ other: Self)
|
|
|
|
/// Product of `self` and `other` rounded to a representable value. The
|
|
/// IEEE 754 multiply operation.
|
|
///
|
|
/// A default implementation is provided in terms of `multiply(by:)`.
|
|
func multiplied(by other: Self) -> Self
|
|
|
|
/// Replace `self` with the product of `self` and `other` rounded to a
|
|
/// representable value.
|
|
mutating func multiply(by other: Self)
|
|
|
|
/// Quotient of `self` and `other` rounded to a representable value. The
|
|
/// IEEE 754 divide operation.
|
|
///
|
|
/// A default implementation is provided in terms of `divide(by:)`.
|
|
func divided(by other: Self) -> Self
|
|
|
|
/// Replace `self` with the quotient of `self` and `other` rounded to a
|
|
/// representable value.
|
|
mutating func divide(by other: Self)
|
|
|
|
/// Remainder of `self` divided by `other`. This is the IEEE 754 remainder
|
|
/// operation.
|
|
///
|
|
/// For finite `self` and `other`, the remainder `r` is defined by
|
|
/// `r = self - other*n`, where `n` is the integer nearest to `self/other`.
|
|
/// (Note that `n` is *not* `self/other` computed in floating-point
|
|
/// arithmetic, and that `n` may not even be representable in any available
|
|
/// integer type). If `self/other` is exactly halfway between two integers,
|
|
/// `n` is chosen to be even.
|
|
///
|
|
/// It follows that if `self` and `other` are finite numbers, the remainder
|
|
/// `r` satisfies `-|other|/2 <= r` and `r <= |other|/2`.
|
|
///
|
|
/// `remainder` is always exact.
|
|
func remainder(dividingBy other: Self) -> Self
|
|
|
|
/// Mutating form of `remainder`.
|
|
mutating func formRemainder(dividingBy other: Self)
|
|
|
|
/// Remainder of `self` divided by `other` using truncating division.
|
|
/// Equivalent to the C standard library function `fmod`.
|
|
///
|
|
/// If `self` and `other` are finite numbers, the truncating remainder
|
|
/// `r` has the same sign as `other` and is strictly smaller in magnitude.
|
|
/// It satisfies `r = self - other*n`, where `n` is the integral part
|
|
/// of `self/other`.
|
|
///
|
|
/// `truncatingRemainder` is always exact.
|
|
func truncatingRemainder(dividingBy other: Self) -> Self
|
|
|
|
/// Mutating form of `truncatingRemainder`.
|
|
mutating func formTruncatingRemainder(dividingBy other: Self)
|
|
|
|
/// Square root of `self`.
|
|
func squareRoot() -> Self
|
|
|
|
/// Mutating form of square root.
|
|
mutating func formSquareRoot()
|
|
|
|
/// `self + lhs*rhs` computed without intermediate rounding. Implements the
|
|
/// IEEE 754 `fusedMultiplyAdd` operation.
|
|
func addingProduct(_ lhs: Self, _ rhs: Self) -> Self
|
|
|
|
/// Fused multiply-add, accumulating the product of `lhs` and `rhs` to `self`.
|
|
mutating func addProduct(_ lhs: Self, _ rhs: Self)
|
|
|
|
/// The minimum of `x` and `y`. Implements the IEEE 754 `minNum` operation.
|
|
///
|
|
/// If either of `x` or `y` is a signaling NaN, the result is a quiet NaN.
|
|
/// Otherwise, the result is `x` if x <= y, `y` if x > y, and whichever
|
|
/// is a number if the other is a quiet NaN. If both `x` and `y` are quiet
|
|
/// NaNs, a quiet NaN is returned.
|
|
static func minimum(_ x: Self, _ y: Self) -> Self
|
|
|
|
/// The maximum of `x` and `y`. Implements the IEEE 754 `maxNum` operation.
|
|
///
|
|
/// If either of `x` or `y` is a signaling NaN, the result is a quiet NaN.
|
|
/// Otherwise, the result is `x` if x > y, `y` if x <= y, and whichever
|
|
/// is a number if the other is a quiet NaN. If both `x` and `y` are quiet
|
|
/// NaNs, a quiet NaN is returned.
|
|
static func maximum(_ x: Self, _ y: Self) -> Self
|
|
|
|
/// Whichever of `x` or `y` has lesser magnitude. Implements the IEEE 754
|
|
/// `minNumMag` operation.
|
|
///
|
|
/// If either of `x` or `y` is a signaling NaN, the result is a quiet NaN.
|
|
/// Otherwise, the result is `x` if abs(x) <= abs(y), `y` if abs(x) > abs(y),
|
|
/// and whichever is a number if the other is a quiet NaN. If both `x` and
|
|
/// `y` are quiet NaNs, a quiet NaN is returned.
|
|
static func minimumMagnitude(_ x: Self, _ y: Self) -> Self
|
|
|
|
/// Whichever of `x` or `y` has greater magnitude. Implements the IEEE 754
|
|
/// `maxNumMag` operation.
|
|
///
|
|
/// If either of `x` or `y` is a signaling NaN, the result is a quiet NaN.
|
|
/// Otherwise, the result is `x` if abs(x) > abs(y), `y` if abs(x) <= abs(y),
|
|
/// and whichever is a number if the other is a quiet NaN. If both `x` and
|
|
/// `y` are quiet NaNs, a quiet NaN is returned.
|
|
static func maximumMagnitude(_ x: Self, _ y: Self) -> Self
|
|
|
|
/// Returns the value of `self` rounded to an integral value using the
|
|
/// specified rounding rule. If the rounding rule is omitted, it defaults
|
|
/// to `.toNearestOrAwayFromZero`, aka "schoolbook rounding".
|
|
///
|
|
/// This implements the C library rounding functions and the IEEE 754
|
|
/// operations that they bind.
|
|
///
|
|
/// - `round(x)` is `x.rounded()` (the default rounding rule is provided by
|
|
/// an extension. This implements the IEEE 754 `roundToIntegralTiesToAway`
|
|
/// operation.
|
|
///
|
|
/// - `roundeven(x)` is `x.rounded(.toNearestOrEven)`. This implements
|
|
/// the IEEE 754 `roundToIntegralTiesToEven` operation.
|
|
///
|
|
/// - `trunc(x)` is `x.rounded(.towardZero)`. This implements the IEEE 754
|
|
/// `roundToIntegralTowardZero` operation.
|
|
///
|
|
/// - `ceil(x)` is `x.rounded(.up)`. This implements the IEEE 754
|
|
/// `roundToIntegralTowardPositive` operation.
|
|
///
|
|
/// - `floor(x)` is `x.rounded(.down)`. This implements the IEEE 754
|
|
/// `roundToIntegralTowardNegative` operation.
|
|
func rounded(_ rule: FloatingPointRoundingRule) -> Self
|
|
|
|
/// Rounds `self` to an integral value using the specified rounding rule.
|
|
/// If the rounding rule is omitted, it defaults to
|
|
/// `.toNearestOrAwayFromZero`, aka "schoolbook rounding".
|
|
mutating func round(_ rule: FloatingPointRoundingRule)
|
|
|
|
/// The least representable value that compares greater than `self`.
|
|
///
|
|
/// - If `x` is `-infinity`, then `x.nextUp` is `-greatestMagnitude`.
|
|
/// - If `x` is `-leastNonzeroMagnitude`, then `x.nextUp` is `-0.0`.
|
|
/// - If `x` is zero, then `x.nextUp` is `leastNonzeroMagnitude`.
|
|
/// - If `x` is `greatestMagnitude`, then `x.nextUp` is `infinity`.
|
|
/// - If `x` is `infinity` or `NaN`, then `x.nextUp` is `x`.
|
|
var nextUp: Self { get }
|
|
|
|
/// The greatest representable value that compares less than `self`.
|
|
///
|
|
/// `x.nextDown` is equivalent to `-(-x).nextUp`
|
|
var nextDown: Self { get }
|
|
|
|
/// IEEE 754 equality predicate.
|
|
///
|
|
/// -0 compares equal to +0, and NaN compares not equal to anything,
|
|
/// including itself.
|
|
func isEqual(to other: Self) -> Bool
|
|
|
|
/// IEEE 754 less-than predicate.
|
|
///
|
|
/// NaN compares not less than anything. -infinity compares less than
|
|
/// all values except for itself and NaN. Everything except for NaN and
|
|
/// +infinity compares less than +infinity.
|
|
func isLess(than other: Self) -> Bool
|
|
|
|
/// IEEE 754 less-than-or-equal predicate.
|
|
///
|
|
/// NaN compares not less than or equal to anything, including itself.
|
|
/// -infinity compares less than or equal to everything except NaN.
|
|
/// Everything except NaN compares less than or equal to +infinity.
|
|
///
|
|
/// Because of the existence of NaN in FloatingPoint types, trichotomy does
|
|
/// not hold, which means that `x < y` and `!(y <= x)` are not equivalent.
|
|
/// This is why `isLessThanOrEqualTo(_:)` is a separate implementation hook
|
|
/// in the protocol.
|
|
///
|
|
/// Note that this predicate does not impose a total order. The
|
|
/// `isTotallyOrdered` predicate refines this relation so that all values
|
|
/// are totally ordered.
|
|
func isLessThanOrEqualTo(_ other: Self) -> Bool
|
|
|
|
/// True if and only if `self` precedes `other` in the IEEE 754 total order
|
|
/// relation.
|
|
///
|
|
/// This relation is a refinement of `<=` that provides a total order on all
|
|
/// values of type `Self`, including non-canonical encodings, signed zeros,
|
|
/// and NaNs. Because it is used much less frequently than the usual
|
|
/// comparisons, there is no operator form of this relation.
|
|
func isTotallyOrdered(below other: Self) -> Bool
|
|
|
|
/// True if and only if `self` is normal.
|
|
///
|
|
/// A normal number uses the full precision available in the format. Zero
|
|
/// is not a normal number.
|
|
var isNormal: Bool { get }
|
|
|
|
/// True if and only if `self` is finite.
|
|
///
|
|
/// If `x.isFinite` is `true`, then one of `x.isZero`, `x.isSubnormal`, or
|
|
/// `x.isNormal` is also `true`, and `x.isInfinite` and `x.isNaN` are
|
|
/// `false`.
|
|
var isFinite: Bool { get }
|
|
|
|
/// True iff `self` is zero. Equivalent to `self == 0`.
|
|
var isZero: Bool { get }
|
|
|
|
/// True if and only if `self` is subnormal.
|
|
///
|
|
/// A subnormal number does not use the full precision available to normal
|
|
/// numbers of the same format. Zero is not a subnormal number.
|
|
///
|
|
/// Subnormal numbers are often called "denormal" or "denormalized". These
|
|
/// are simply different names for the same concept. IEEE 754 prefers the
|
|
/// name "subnormal", and we follow that usage.
|
|
var isSubnormal: Bool { get }
|
|
|
|
/// True if and only if `self` is infinite.
|
|
///
|
|
/// Note that `isFinite` and `isInfinite` do not form a dichotomy, because
|
|
/// they are not total. If `x` is `NaN`, then both properties are `false`.
|
|
var isInfinite: Bool { get }
|
|
|
|
/// True if and only if `self` is NaN ("not a number"); this property is
|
|
/// true for both quiet and signaling NaNs.
|
|
var isNaN: Bool { get }
|
|
|
|
/// True if and only if `self` is a signaling NaN.
|
|
var isSignalingNaN: Bool { get }
|
|
|
|
/// The IEEE 754 "class" of this type.
|
|
var floatingPointClass: FloatingPointClassification { get }
|
|
|
|
/// True if and only if `self` is canonical.
|
|
///
|
|
/// Every floating-point value of type Float or Double is canonical, but
|
|
/// non-canonical values of type Float80 exist, and non-canonical values
|
|
/// may exist for other types that conform to FloatingPoint.
|
|
///
|
|
/// The non-canonical Float80 values are known as "pseudo-denormal",
|
|
/// "unnormal", "pseudo-infinity", and "pseudo-NaN".
|
|
/// (https://en.wikipedia.org/wiki/Extended_precision#x86_Extended_Precision_Format)
|
|
var isCanonical: Bool { get }
|
|
}
|
|
|
|
/// The sign of a floating-point value.
|
|
public enum FloatingPointSign: Int {
|
|
case plus
|
|
case minus
|
|
}
|
|
|
|
/// The IEEE 754 floating-point classes.
|
|
public enum FloatingPointClassification {
|
|
case signalingNaN
|
|
case quietNaN
|
|
case negativeInfinity
|
|
case negativeNormal
|
|
case negativeSubnormal
|
|
case negativeZero
|
|
case positiveZero
|
|
case positiveSubnormal
|
|
case positiveNormal
|
|
case positiveInfinity
|
|
}
|
|
|
|
/// Describes a rule for rounding a floating-point number.
|
|
public enum FloatingPointRoundingRule {
|
|
|
|
/// The result is the closest allowed value; if two values are equally close,
|
|
/// the one with greater magnitude is chosen. Also known as "schoolbook
|
|
/// rounding".
|
|
case toNearestOrAwayFromZero
|
|
|
|
/// The result is the closest allowed value; if two values are equally close,
|
|
/// the even one is chosen. Also known as "bankers rounding".
|
|
case toNearestOrEven
|
|
|
|
/// The result is the closest allowed value that is greater than or equal
|
|
/// to the source.
|
|
case up
|
|
|
|
/// The result is the closest allowed value that is less than or equal to
|
|
/// the source.
|
|
case down
|
|
|
|
/// The result is the closest allowed value whose magnitude is less than or
|
|
/// equal to that of the source.
|
|
case towardZero
|
|
|
|
/// The result is the closest allowed value whose magnitude is greater than
|
|
/// or equal to that of the source.
|
|
case awayFromZero
|
|
}
|
|
|
|
@_transparent
|
|
public prefix func +<T : FloatingPoint>(x: T) -> T {
|
|
return x
|
|
}
|
|
|
|
@_transparent
|
|
public prefix func -<T : FloatingPoint>(x: T) -> T {
|
|
return x.negated()
|
|
}
|
|
|
|
%{
|
|
binary_arithmetic = [
|
|
('+', 'adding', 'add', None),
|
|
('-', 'subtracting', 'subtract', None),
|
|
('*', 'multiplied', 'multiply', 'by'),
|
|
('/', 'divided', 'divide', 'by')
|
|
]
|
|
}%
|
|
|
|
%for op in binary_arithmetic:
|
|
@_transparent
|
|
public func ${op[0]}<T : FloatingPoint>(lhs: T, rhs: T) -> T {
|
|
return lhs.${op[1]}(${op[3]+': ' if op[3] else ''}rhs)
|
|
}
|
|
|
|
@_transparent
|
|
public func ${op[0]}=<T : FloatingPoint>(lhs: inout T, rhs: T) {
|
|
return lhs.${op[2]}(${op[3]+': ' if op[3] else ''}rhs)
|
|
}
|
|
|
|
%end
|
|
|
|
@_transparent
|
|
public func ==<T : FloatingPoint>(lhs: T, rhs: T) -> Bool {
|
|
return lhs.isEqual(to: rhs)
|
|
}
|
|
|
|
@_transparent
|
|
public func < <T : FloatingPoint>(lhs: T, rhs: T) -> Bool {
|
|
return lhs.isLess(than: rhs)
|
|
}
|
|
|
|
@_transparent
|
|
public func <= <T : FloatingPoint>(lhs: T, rhs: T) -> Bool {
|
|
return lhs.isLessThanOrEqualTo(rhs)
|
|
}
|
|
|
|
@_transparent
|
|
public func > <T : FloatingPoint>(lhs: T, rhs: T) -> Bool {
|
|
return rhs.isLess(than: lhs)
|
|
}
|
|
|
|
@_transparent
|
|
public func >= <T : FloatingPoint>(lhs: T, rhs: T) -> Bool {
|
|
return rhs.isLessThanOrEqualTo(lhs)
|
|
}
|
|
|
|
/// A radix-2 (binary) floating-point type that follows the IEEE 754 encoding
|
|
/// conventions.
|
|
public protocol BinaryFloatingPoint: FloatingPoint, ExpressibleByFloatLiteral {
|
|
|
|
/// An unsigned integer type that can represent the significand of any value.
|
|
///
|
|
/// The significand (http://en.wikipedia.org/wiki/Significand) is frequently
|
|
/// also called the "mantissa", but this terminology is slightly incorrect
|
|
/// (see the "Use of 'mantissa'" section on the linked Wikipedia page for
|
|
/// more details). "Significand" is the preferred terminology in IEEE 754.
|
|
associatedtype RawSignificand: UnsignedInteger
|
|
|
|
/// An unsigned integer type that can represent the exponent encoding of any
|
|
/// value.
|
|
associatedtype RawExponent: UnsignedInteger
|
|
|
|
/// Combines `sign`, `exponent` and `significand` bit patterns to produce
|
|
/// a floating-point value.
|
|
init(sign: FloatingPointSign,
|
|
exponentBitPattern: RawExponent,
|
|
significandBitPattern: RawSignificand)
|
|
|
|
/// `value` rounded to the closest representable `Self`.
|
|
init(_ value: Float)
|
|
|
|
/// `value` rounded to the closest representable `Self`.
|
|
init(_ value: Double)
|
|
|
|
#if !os(Windows) && (arch(i386) || arch(x86_64))
|
|
/// `value` rounded to the closest representable `Self`.
|
|
init(_ value: Float80)
|
|
#endif
|
|
|
|
/* TODO: Implement these once it becomes possible to do so (requires revised
|
|
Integer protocol).
|
|
/// `value` rounded to the closest representable value.
|
|
init<Source: BinaryFloatingPoint>(_ value: Source)
|
|
|
|
/// Fails if `value` cannot be represented exactly as `Self`.
|
|
init?<Source: BinaryFloatingPoint>(exactly value: Source)
|
|
*/
|
|
|
|
/// The number of bits used to represent the exponent.
|
|
///
|
|
/// Following IEEE 754 encoding convention, the exponent bias is:
|
|
///
|
|
/// ~~~
|
|
/// bias = 2**(exponentBitCount-1) - 1
|
|
/// ~~~
|
|
///
|
|
/// (where `**` is exponentiation). The least normal exponent is `1-bias`
|
|
/// and the largest finite exponent is `bias`. The all-zeros exponent is
|
|
/// reserved for subnormals and zeros, and the all-ones exponent is reserved
|
|
/// for infinities and NaNs.
|
|
static var exponentBitCount: Int { get }
|
|
|
|
/// For fixed-width floating-point types, this is the number of fractional
|
|
/// significand bits.
|
|
///
|
|
/// For extensible floating-point types, `significandBitCount` should be
|
|
/// the maximum allowed significand width (without counting any leading
|
|
/// integral bit of the significand). If there is no upper limit, then
|
|
/// `significandBitCount` should be `Int.max`.
|
|
///
|
|
/// Note that `Float80.significandBitCount` is 63, even though 64 bits
|
|
/// are used to store the significand in the memory representation of a
|
|
/// `Float80` (unlike other floating-point types, `Float80` explicitly
|
|
/// stores the leading integral significand bit, but the
|
|
/// `BinaryFloatingPoint` APIs provide an abstraction so that users don't
|
|
/// need to be aware of this detail).
|
|
static var significandBitCount: Int { get }
|
|
|
|
/// The raw encoding of the exponent field of the floating-point value.
|
|
var exponentBitPattern: RawExponent { get }
|
|
|
|
/// The raw encoding of the significand field of the floating-point value.
|
|
///
|
|
/// `significandBitPattern` does *not* include the leading integral bit of
|
|
/// the significand, even for types like `Float80` that store it explicitly.
|
|
var significandBitPattern: RawSignificand { get }
|
|
|
|
/// The least-magnitude member of the binade of `self`.
|
|
///
|
|
/// If `x` is `+/-significand * 2**exponent`, then `x.binade` is
|
|
/// `+/- 2**exponent`; i.e. the floating point number with the same sign
|
|
/// and exponent, but with a significand of 1.0.
|
|
var binade: Self { get }
|
|
|
|
/// The number of bits required to represent significand.
|
|
///
|
|
/// If `self` is not a finite non-zero number, `significandWidth` is
|
|
/// `-1`. Otherwise, it is the number of fractional bits required to
|
|
/// represent `self.significand`, which is an integer between zero and
|
|
/// `significandBitCount`. Some examples:
|
|
///
|
|
/// - For any representable power of two, `significandWidth` is zero,
|
|
/// because `significand` is `1.0`.
|
|
/// - If `x` is 10, then `x.significand` is `1.01` in binary, so
|
|
/// `x.significandWidth` is 2.
|
|
/// - If `x` is Float.pi, `x.significand` is `1.10010010000111111011011`,
|
|
/// and `x.significandWidth` is 23.
|
|
var significandWidth: Int { get }
|
|
|
|
/* TODO: Implement these once it becomes possible to do so. (Requires
|
|
* revised Integer protocol).
|
|
func isEqual<Other: BinaryFloatingPoint>(to other: Other) -> Bool
|
|
|
|
func isLess<Other: BinaryFloatingPoint>(than other: Other) -> Bool
|
|
|
|
func isLessThanOrEqualTo<Other: BinaryFloatingPoint>(other: Other) -> Bool
|
|
|
|
func isTotallyOrdered<Other: BinaryFloatingPoint>(below other: Other) -> Bool
|
|
*/
|
|
}
|
|
|
|
extension FloatingPoint {
|
|
|
|
public static var ulpOfOne: Self {
|
|
return Self(1).ulp
|
|
}
|
|
|
|
@_transparent
|
|
public func rounded(_ rule: FloatingPointRoundingRule) -> Self {
|
|
var lhs = self
|
|
lhs.round(rule)
|
|
return lhs
|
|
}
|
|
|
|
/// Returns `self` rounded to the closest integral value. If `self` is
|
|
/// exactly halfway between two integers (e.g. 1.5), the integral value
|
|
/// with greater magnitude (2.0 in this example) is returned.
|
|
///
|
|
/// Other rounding modes can be explicitly specified with
|
|
/// `.rounded(_: FloatingPointRoundingRule)`.
|
|
@_transparent
|
|
public func rounded() -> Self {
|
|
return rounded(.toNearestOrAwayFromZero)
|
|
}
|
|
|
|
/// Rounds `self` to the closest integral value. If `self` is exactly
|
|
/// halfway between two integers (e.g. 1.5), the integral value with
|
|
/// greater magnitude is selected.
|
|
///
|
|
/// Other rounding modes can be explicitly specified with
|
|
/// `.round(_: FloatingPointRoundingRule)`.
|
|
@_transparent
|
|
public mutating func round() {
|
|
round(.toNearestOrAwayFromZero)
|
|
}
|
|
|
|
@_transparent
|
|
public var nextDown: Self {
|
|
return -(-self).nextUp
|
|
}
|
|
|
|
@_transparent
|
|
public func truncatingRemainder(dividingBy rhs: Self) -> Self {
|
|
var lhs = self
|
|
lhs.formTruncatingRemainder(dividingBy: rhs)
|
|
return lhs
|
|
}
|
|
|
|
@_transparent
|
|
public func remainder(dividingBy rhs: Self) -> Self {
|
|
var lhs = self
|
|
lhs.formRemainder(dividingBy: rhs)
|
|
return lhs
|
|
}
|
|
|
|
@_transparent
|
|
public func squareRoot( ) -> Self {
|
|
var lhs = self
|
|
lhs.formSquareRoot( )
|
|
return lhs
|
|
}
|
|
|
|
@_transparent
|
|
public func addingProduct(_ lhs: Self, _ rhs: Self) -> Self {
|
|
var addend = self
|
|
addend.addProduct(lhs, rhs)
|
|
return addend
|
|
}
|
|
|
|
public static func minimum(_ left: Self, _ right: Self) -> Self {
|
|
if left.isSignalingNaN || right.isSignalingNaN {
|
|
// Produce a quiet NaN matching platform arithmetic behavior.
|
|
return left + right
|
|
}
|
|
if left <= right || right.isNaN { return left }
|
|
return right
|
|
}
|
|
|
|
public static func maximum(_ left: Self, _ right: Self) -> Self {
|
|
if left.isSignalingNaN || right.isSignalingNaN {
|
|
// Produce a quiet NaN matching platform arithmetic behavior.
|
|
return left + right
|
|
}
|
|
if left > right || right.isNaN { return left }
|
|
return right
|
|
}
|
|
|
|
public static func minimumMagnitude(_ left: Self, _ right: Self) -> Self {
|
|
if left.isSignalingNaN || right.isSignalingNaN {
|
|
// Produce a quiet NaN matching platform arithmetic behavior.
|
|
return left + right
|
|
}
|
|
if abs(left) <= abs(right) || right.isNaN { return left }
|
|
return right
|
|
}
|
|
|
|
public static func maximumMagnitude(_ left: Self, _ right: Self) -> Self {
|
|
if left.isSignalingNaN || right.isSignalingNaN {
|
|
// Produce a quiet NaN matching platform arithmetic behavior.
|
|
return left + right
|
|
}
|
|
if abs(left) > abs(right) || right.isNaN { return left }
|
|
return right
|
|
}
|
|
|
|
public var floatingPointClass: FloatingPointClassification {
|
|
if isSignalingNaN { return .signalingNaN }
|
|
if isNaN { return .quietNaN }
|
|
if isInfinite { return sign == .minus ? .negativeInfinity : .positiveInfinity }
|
|
if isNormal { return sign == .minus ? .negativeNormal : .positiveNormal }
|
|
if isSubnormal { return sign == .minus ? .negativeSubnormal : .positiveSubnormal }
|
|
return sign == .minus ? .negativeZero : .positiveZero
|
|
}
|
|
|
|
%for op in binary_arithmetic:
|
|
@_transparent
|
|
public func ${op[1]}(${op[3] if op[3] else '_'} other: Self) -> Self {
|
|
var lhs = self
|
|
lhs.${op[2]}(${op[3]+': ' if op[3] else ''}other)
|
|
return lhs
|
|
}
|
|
%end
|
|
|
|
@_transparent
|
|
public func negated() -> Self {
|
|
var rhs = self
|
|
rhs.negate()
|
|
return rhs
|
|
}
|
|
}
|
|
|
|
extension BinaryFloatingPoint {
|
|
|
|
public static var radix: Int { return 2 }
|
|
|
|
public init(signOf: Self, magnitudeOf: Self) {
|
|
self.init(sign: signOf.sign,
|
|
exponentBitPattern: magnitudeOf.exponentBitPattern,
|
|
significandBitPattern: magnitudeOf.significandBitPattern)
|
|
}
|
|
|
|
public func isTotallyOrdered(below other: Self) -> Bool {
|
|
// Quick return when possible.
|
|
if self < other { return true }
|
|
if other > self { return false }
|
|
// Self and other are either equal or unordered.
|
|
// Every negative-signed value (even NaN) is less than every positive-
|
|
// signed value, so if the signs do not match, we simply return the
|
|
// sign bit of self.
|
|
if sign != other.sign { return sign == .minus }
|
|
// Sign bits match; look at exponents.
|
|
if exponentBitPattern > other.exponentBitPattern { return sign == .minus }
|
|
if exponentBitPattern < other.exponentBitPattern { return sign == .plus }
|
|
// Signs and exponents match, look at significands.
|
|
if significandBitPattern > other.significandBitPattern {
|
|
return sign == .minus
|
|
}
|
|
if significandBitPattern < other.significandBitPattern {
|
|
return sign == .plus
|
|
}
|
|
// Sign, exponent, and significand all match.
|
|
return true
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "isSignalingNaN")
|
|
public var isSignaling: Bool {
|
|
return isSignalingNaN
|
|
}
|
|
|
|
/* TODO: uncomment these default implementations when it becomes possible
|
|
to use them.
|
|
// TODO: The following comparison implementations are not quite correct for
|
|
// the unusual case where one type has more exponent range and the other
|
|
// uses more fractional bits, *and* the value with more exponent range is
|
|
// subnormal when converted to the other type. This is an extremely niche
|
|
// corner case, however (it cannot occur with the usual IEEE 754 floating-
|
|
// point types). Nonetheless, this should be fixed someday.
|
|
public func isEqual<Other: BinaryFloatingPoint>(to other: Other) -> Bool {
|
|
if Self.significandBitCount >= Other.significandBitCount {
|
|
return self.isEqual(to: Self(other))
|
|
}
|
|
return other.isEqual(to: Other(self))
|
|
}
|
|
|
|
public func isLess<Other: BinaryFloatingPoint>(than other: Other) -> Bool {
|
|
if Self.significandBitCount >= Other.significandBitCount {
|
|
return self.isLess(than: Self(other))
|
|
}
|
|
return Other(self).isLess(than: other)
|
|
}
|
|
|
|
public func isLessThanOrEqualTo<Other: BinaryFloatingPoint>(other: Other) -> Bool {
|
|
if Self.significandBitCount >= Other.significandBitCount {
|
|
return self.isLessThanOrEqualTo(Self(other))
|
|
}
|
|
return Other(self).isLessThanOrEqualTo(other)
|
|
}
|
|
|
|
public func isTotallyOrdered<Other: BinaryFloatingPoint>(before other: Other) -> Bool {
|
|
if Self.significandBitCount >= Other.significandBitCount {
|
|
return self.totalOrder(with: Self(other))
|
|
}
|
|
return Other(self).totalOrder(with: other)
|
|
}
|
|
*/
|
|
}
|
|
|
|
/// Returns the absolute value of `x`.
|
|
@_transparent
|
|
public func abs<T : FloatingPoint>(_ x: T) -> T where T.Magnitude == T {
|
|
return x.magnitude
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "FloatingPoint")
|
|
public typealias FloatingPointType = FloatingPoint
|