blob: c9d77029365041424272b56899f7eb52e8e05fa6 [file] [log] [blame]
// RUN: rm -rf %t && mkdir -p %t
// RUN: %S/../../utils/line-directive %s -- %target-build-swift -parse-stdlib %s -o %t/a.out
// RUN: %S/../../utils/line-directive %s -- %target-run %t/a.out
// REQUIRES: executable_test
import Swift
// TODO: These should probably subsumed into UnsignedIntegerType or
// another integer protocol. Dave has already done some work here.
public protocol FloatingPointRepresentationType : UnsignedIntegerType {
var leadingZeros: UInt { get }
func <<(left: Self, right: Self) -> Self
func >>(left: Self, right: Self) -> Self
init(_ value: UInt)
}
extension UInt64 : FloatingPointRepresentationType {
public var leadingZeros: UInt {
return UInt(_countLeadingZeros(Int64(bitPattern: self)))
}
}
extension UInt32 : FloatingPointRepresentationType {
public var leadingZeros: UInt {
return UInt64(self).leadingZeros - 32
}
}
// Ewwww? <rdar://problem/20060017>
#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#elseif os(Linux)
import Glibc
#endif
public protocol FloatingPointType : Comparable, SignedNumberType,
IntegerLiteralConvertible,
FloatLiteralConvertible {
/// An unsigned integer type large enough to hold the significand field.
typealias SignificandBits: FloatingPointRepresentationType
/// Positive infinity.
///
/// Compares greater than all finite numbers.
static var infinity: Self { get }
/// Quiet NaN.
///
/// Compares not equal to every value, including itself. Most operations
/// with a `NaN` operand will produce a `NaN` result.
static var NaN: Self { get }
/// NaN with specified `payload`.
///
/// Compares not equal to every value, including itself. Most operations
/// with a `NaN` operand will produce a `NaN` result.
static func NaN(payload bits: SignificandBits, signaling: Bool) -> Self
/// The greatest finite value.
///
/// Compares greater than or equal to all finite numbers, but less than
/// infinity.
static var greatestFiniteMagnitude: 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 `leastMagnitude`.
//
// - 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 1.0.
///
/// This is the weight of the least significant bit of the significand of 1.0,
/// or the positive difference between 1.0 and the next greater representable
/// number.
///
/// This value (or a similar value) is often called "epsilon", "machine
/// epsilon", or "macheps" in other languages.
static var ulp: Self { get }
/// The least positive normal value.
///
/// 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.
static var leastNormalMagnitude: Self { get }
/// The least positive value.
///
/// 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 (as on armv7), they are equal.
static var leastMagnitude: Self { get }
/// The `signbit`. True for negative numbers, false for positive.
///
/// This is simply the high-order bit in the encoding of `self`, regardless
/// of the encoded value. This *is not* the same thing as `self < 0`.
/// In particular:
///
/// - If `x` is `-0.0`, then `x.signbit` is `true`, but `x < 0` is `false`.
/// - If `x` is `NaN`, then `x.signbit` could be either `true` or `false`,
/// (the signbit of `NaN` is unspecified) but `x < 0` is `false`.
///
/// Implements the IEEE-754 `isSignMinus` operation.
var signbit: Bool { get }
/// The mathematical `exponent`.
///
/// If `x` is a normal floating-point number, then `exponent` is simply the
/// raw encoded exponent interpreted as a signed integer with the exponent
/// bias removed.
///
/// For subnormal numbers, `exponent` is computed as though the exponent
/// range of `Self` were unbounded. In particular, `x.exponent` will
/// be smaller than the minimum normal exponent that can be encoded.
///
/// Other edge cases:
///
/// - If `x` is zero, then `x.exponent` is `Int.min`.
/// - If `x` is +/-infinity or NaN, then `x.exponent` is `Int.max`
///
/// Implements the IEEE-754 `logB` operation.
var exponent: Int { get }
/// The mathematical `significand` (sometimes erroneously called the "mantissa").
///
/// `significand` is computed as though the exponent range of `Self` were
/// unbounded; if `x` is a finite non-zero number, then `x.significand` is
/// in the range `[1,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.signficand` 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(signbit: x.signbit, exponent: x.exponent,
/// significand: x.significand)
///
/// then `y` is equivalent to `x`, meaning that `y` is `x` canonicalized.
/// For types that do not have non-canonical encodings, this implies that
/// `y` has the same encoding as `x`. Note that this is a stronger
/// statement than `x == y`, as it implies that both the sign of zero and
/// the payload of NaN are preserved.
var significand: Self { get }
/// Combines a signbit, exponent, and signficand to produce a floating-point
/// datum.
///
/// In common usage, `significand` will generally be a number in the range
/// `[1,2)`, but this is not required; the initializer supports any valid
/// floating-point datum. The result is:
///
/// `(-1)^signbit * signficand * 2^exponent`
///
/// (where ^ denotes the mathematical operation of 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 will occur, and zero, a subnormal value, or infinity will be
/// returned, 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 datum `x` the result of
///
/// `Self(signbit: x.signbit,
/// exponent: x.exponent,
/// significand: x.significand)`
///
/// is "the same" as `x` (if `x` is NaN, then this result is also `NaN`, but
/// it might be a different NaN).
///
/// Because of these properties, this initializer also implements the
/// IEEE-754 `scaleB` operation.
init(signbit: Bool, exponent: Int, significand: Self)
/// The unit in the last place of `self`.
///
/// This is the value of the least significant bit 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 respresentable 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.
var ulp: Self { get }
// TODO: IEEE-754 requires the following operations for every FP type.
// They need bindings (names) for Swift. Some of them map to existing
// C library functions, so the default choice would be to use the C
// names, but we should consider if other names would be more appropriate
// for Swift.
//
// For now I have simply used the IEEE-754 names to track them.
//
// The C bindings for these operations are:
// roundToIntegralTiesToEven roundeven (n1778)
// roundToIntegralTiesAway round (c99)
// roundToIntegralTowardZero trunc (c99)
// roundToIntegralTowardPositive ceil (c90)
// roundToIntegralTowardNegative floor (c90)
//
// Also TBD: should these only be available as free functions?
/// Rounds `self` to nearest integral value, with halfway cases rounded
/// to the even integer.
func roundToIntegralTiesToEven() -> Self
/// Rounds `self` to the nearest integral value, with halfway cases rounded
/// away from zero.
func roundToIntegralTiesToAway() -> Self
/// Rounds `self` to an integral value towards zero.
func roundToIntegralTowardZero() -> Self
/// Rounds `self` to an integral value toward positive infinity.
func roundToIntegralTowardPositive() -> Self
/// Rounds `self` to an integral value toward negative infinity.
func roundToIntegralTowardNegative() -> Self
// TODO: roundToIntegralExact requires a notion of flags and of
// rounding modes, which require language design.
// TODO: should nextUp and nextDown be computed properties or funcs?
// For me, these sit right on the edge in terms of what makes sense.
/// The least `Self` that compares greater than `self`.
///
/// - If `x` is `-infinity`, then `x.nextUp` is `-greatestMagnitude`.
/// - If `x` is `-leastMagnitude`, then `x.nextUp` is `-0.0`.
/// - If `x` is zero, then `x.nextUp` is `leastMagnitude`.
/// - 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 `Self` that compares less than `self`.
///
/// `x.nextDown` is equivalent to `-(-x).nextUp`
var nextDown: Self { get }
// TODO: IEEE-754 defines the following semantics for remainder(x, y).
//
// This operation differs from what is currently provided by the %
// operator, which implements fmod, not remainder. The difference is
// that fmod is the remainder of truncating division (the sign matches
// that of x and the magnitude is in [0, y)), whereas remainder is what
// results from round-to-nearest division (it lies in [y/2, y/2]).
//
// I would prefer that % implement the remainder operation, but this is
// a fairly significant change to the language that needs discussion.
// Both operations should be probably be available, anyway.
/// Remainder of `x` divided by `y`.
///
/// `remainder(x,y)` is defined for finite `x` and `y` by the mathematical
/// relation `r = x - yn`, where `n` is the integer nearest to the exact
/// number (*not* the floating-point value) `x/y`. If `x/y` is exactly
/// halfway between two integers, `n` is even. `remainder` is always
/// exact, and therefore is not affected by the rounding mode.
///
/// If `remainder(x,y)` is zero, it has the same sign as `x`. If `y` is
/// infinite, then `remainder(x,y)` is `x`.
static func remainder(x: Self, _ y: Self) -> Self
// TODO: The IEEE-754 "minNumber" and "maxNumber" operations should
// probably be provided by the min and max generic free functions, but
// there is some question of how best to do that. As an initial
// binding, they are provided as static functions.
//
// We will end up naming the static functions something else
// (if we keep them at all) to avoid confusion with Int.min, etc.
/// The minimum of `x` and `y`.
///
/// Returns `x` if `x < y`, `y` if `y < x`, and whichever of `x` or `y`
/// is a number if the other is NaN. The result is NaN only if both
/// arguments are NaN.
static func min(x: Self, _ y: Self) -> Self
/// The maximum of `x` and `y`.
///
/// Returns `x` if `x > y`, `y` if `y > x`, and whichever of `x` or `y`
/// is a number if the other is NaN. The result is NaN only if both
/// arguments are NaN.
static func max(x: Self, _ y: Self) -> Self
// Note: IEEE-754 calls these "minNumMag" and "maxNumMag". C (n1778)
// uses "fminmag" and "fmaxmag". Neither of these strike me as very
// good names. I prefer minMagnitude and maxMagnitude, which are
// clear without being too wordy.
/// Whichever of `x` or `y` has lesser magnitude.
///
/// Returns `x` if `|x| < |y|`, `y` if `|y| < |x|`, and whichever of
/// `x` or `y` is a number if the other is NaN. The result is NaN
/// only if both arguments are NaN.
static func minMagnitude(left: Self, _ right: Self) -> Self
/// Whichever of `x` or `y` has greater magnitude.
///
/// Returns `x` if `|x| > |y|`, `y` if `|y| > |x|`, and whichever of
/// `x` or `y` is a number if the other is NaN. The result is NaN
/// only if both arguments are NaN.
static func maxMagnitude(left: Self, _ right: Self) -> Self
func +(x: Self, y: Self) -> Self
func -(x: Self, y: Self) -> Self
func *(x: Self, y: Self) -> Self
func /(x: Self, y: Self) -> Self
// Implementation details of formatOf operations.
static func _addStickyRounding(x: Self, _ y: Self) -> Self
static func _mulStickyRounding(x: Self, _ y: Self) -> Self
static func _divStickyRounding(x: Self, _ y: Self) -> Self
static func _sqrtStickyRounding(x: Self) -> Self
static func _mulAddStickyRounding(x: Self, _ y: Self, _ z: Self) -> Self
// TODO: do we actually want to provide remainder as an operator? It's
// definitely not obvious to me that we should, but we have until now.
// See further discustion with func remainder(x,y) above.
func %(x: Self, y: Self) -> Self
// Conversions from all integer types.
init(_ value: Int8)
init(_ value: Int16)
init(_ value: Int32)
init(_ value: Int64)
init(_ value: Int)
init(_ value: UInt8)
init(_ value: UInt16)
init(_ value: UInt32)
init(_ value: UInt64)
init(_ value: UInt)
init(_ value: SignificandBits)
// Conversions from all floating-point types.
init(_ value: Float)
init(_ value: Double)
#if arch(i386) || arch(x86_64)
init(_ value: Float80)
#endif
// TODO: where do conversions to/from string live? IEEE-754 requires
// conversions to/from decimal character and hexadecimal character
// sequences.
/// Implements the IEEE-754 copy operation.
prefix func +(value: Self) -> Self
// IEEE-754 negate operation is prefix `-`, provided by SignedNumberType.
// TODO: ensure that the optimizer is able to produce a simple xor for -.
// IEEE-754 abs operation is the free function abs( ), provided by
// SignedNumberType. TODO: ensure that the optimizer is able to produce
// a simple and or bic for abs( ).
// TODO: should this be the free function copysign(x, y) instead, a la C?
/// Returns datum with magnitude of `self` and sign of `from`.
///
/// Implements the IEEE-754 copysign operation.
func copysign(from: Self) -> Self
// TODO: "signaling/quiet" comparison predicates if/when we have a model for
// floating-point flags and exceptions in Swift.
/// The floating point "class" of this datum.
///
/// Implements the IEEE-754 `class` operation.
var floatingPointClass: FloatingPointClassification { get }
/// True if and only if `self` is zero.
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.
var isSubnormal: Bool { get }
/// 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 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").
var isNaN: Bool { get }
/// True if and only if `self` is a signaling NaN.
var isSignaling: Bool { get }
/// True if and only if `self` is canonical.
///
/// Every floating-point datum of type Float or Double is canonical, but
/// non-canonical values of type Float80 exist. These 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 }
/// A total order relation on all values of type Self (including NaN).
func totalOrder(other: Self) -> Bool
/// A total order relation that compares magnitudes.
func totalOrderMagnitude(other: Self) -> Bool
// Note: this operation is *not* required by IEEE-754, but it is an oft-
// requested feature. TBD: should +0 and -0 be equivalent? Substitution
// property of equality says no.
//
// More adventurous (probably crazy) thought: we *could* make this (or
// something like it) the default behavior of the == operator, and make
// IEEE-754 equality be the function. IEEE-754 merely dictates that
// certain operations be available, not what their bindings in a
// language actually are. Their are two problems with this:
//
// - it violates the hell out of the principle of least surprise,
// given that programmers have been conditioned by years of using
// other langauges.
//
// - it would introduce a gratuitous minor inefficiency to most
// code on the hardware we have today, where IEEE-754 equality is
// generally a single test, and "equivalent" is not.
//
// Still, I want to at least make note of the possibility.
/// An equivalence relation on all values of type Self (including NaN).
///
/// Unlike `==`, this relation is a formal equivalence relation. In
/// particular, it is reflexive. All NaNs compare equal to each other
/// under this relation.
func equivalent(other: Self) -> Bool
}
// Features of FloatingPointType that can be implemented without any
// dependence on the internals of the type.
extension FloatingPointType {
public static var NaN: Self { return NaN(payload: 0, signaling: false) }
public static var ulp: Self { return Self(1).ulp }
public func roundToIntegralTiesToEven() -> Self {
fatalError("TODO once roundeven functions are provided in math.h")
}
public static func minMagnitude(left: Self, _ right: Self) -> Self {
fatalError("TODO once fminmag functions are available in libm")
}
public static func maxMagnitude(left: Self, _ right: Self) -> Self {
fatalError("TODO once fmaxmag functions are available in libm")
}
public static func _addStickyRounding(x: Self, _ y: Self) -> Self {
fatalError("TODO: Unimplemented")
}
public static func _mulStickyRounding(x: Self, _ y: Self) -> Self {
fatalError("TODO: Unimplemented")
}
public static func _divStickyRounding(x: Self, _ y: Self) -> Self {
fatalError("TODO: Unimplemented")
}
public static func _sqrtStickyRounding(x: Self) -> Self {
fatalError("TODO: Unimplemented")
}
public static func _mulAddStickyRounding(x: Self, _ y: Self, _ z: Self) -> Self {
fatalError("TODO: Unimplemented")
}
public var floatingPointClass: FloatingPointClassification {
if isSignaling { return .SignalingNaN }
if isNaN { return .QuietNaN }
if isInfinite { return signbit ? .NegativeInfinity : .PositiveInfinity }
if isNormal { return signbit ? .NegativeNormal : .PositiveNormal }
if isSubnormal { return signbit ? .NegativeSubnormal : .PositiveSubnormal }
return signbit ? .NegativeZero : .PositiveZero
}
public func totalOrderMagnitude(other: Self) -> Bool {
return abs(self).totalOrder(abs(other))
}
public func equivalent(other: Self) -> Bool {
if self.isNaN && other.isNaN { return true }
if self.isZero && other.isZero { return self.signbit == other.signbit }
return self == other
}
}
public protocol BinaryFloatingPointType: FloatingPointType {
/// Values that parametrize the type:
static var _exponentBitCount: UInt { get }
static var _fractionalBitCount: UInt { get }
/// The raw encoding of the exponent field of the floating-point datum.
var exponentBitPattern: UInt { get }
/// The raw encoding of the significand field of the floating-point datum.
var significandBitPattern: SignificandBits { get }
/// The least-magnitude member of the binade of `self`.
///
/// If `x` is `+/-signficand * 2^exponent`, then `x.binade` is
/// `+/- 2^exponent`; i.e. the floating point number with the same sign
/// and exponent, but a significand of 1.0.
var binade: Self { get }
/// Combines a signbit, exponent and signficand bit patterns to produce a
/// floating-point datum. No error-checking is performed by this function;
/// the bit patterns are simply concatenated to produce the floating-point
/// encoding of the result.
init(signbit: Bool,
exponentBitPattern: UInt,
significandBitPattern: SignificandBits)
init<T: BinaryFloatingPointType>(_ other: T)
// TODO: IEEE-754 requires that the six basic operations (add, subtract,
// multiply, divide, square root, and FMA) be provided from all source
// formats to all destination formats, with a single rounding. In order
// to satisfy this requirement (which I believe we should), we'll need
// something like the following.
//
// fusedMultiplyAdd needs naming attention for Swift. The C name
// fma(x,y,z) might be too terse for the Swift standard library, but
// fusedMultiplyAdd is awfully verbose. mulAdd(x, y, z), perhaps?
// Or we could go full Obj-C style and do mul(_:, _:, add:), I suppose.
//
// While `sqrt` and `fma` have traditionally been part of the
// math library in C-derived languages, they rightfully belong as part
// of the base FloatingPointType protocol in Swift, because they are
// IEEE-754 required operations, like + or *.
/// The sum of `x` and `y`, correctly rounded to `Self`.
static func add<X: BinaryFloatingPointType, Y: BinaryFloatingPointType>(x: X, _ y: Y) -> Self
/// The difference of `x` and `y`, correctly rounded to `Self`.
static func sub<X: BinaryFloatingPointType, Y: BinaryFloatingPointType>(x: X, _ y: Y) -> Self
/// The product of `x` and `y`, correctly rounded to `Self`.
static func mul<X: BinaryFloatingPointType, Y: BinaryFloatingPointType>(x: X, _ y: Y) -> Self
/// The quotient of `x` and `y`, correctly rounded to `Self`.
static func div<X: BinaryFloatingPointType, Y: BinaryFloatingPointType>(x: X, _ y: Y) -> Self
/// The square root of `x`, correctly rounded to `Self`.
static func sqrt<X: BinaryFloatingPointType>(x: X) -> Self
/// (x*y) + z correctly rounded to `Self`.
static func mulAdd<X: BinaryFloatingPointType, Y: BinaryFloatingPointType, Z: BinaryFloatingPointType>(x: X, _ y: Y, _ z: Z) -> Self
}
extension BinaryFloatingPointType {
static var _exponentBias: UInt {
return Self._infinityExponent >> 1
}
static var _infinityExponent: UInt {
return 1 << _exponentBitCount - 1
}
static var _integralBitMask: SignificandBits {
return 1 << SignificandBits(UIntMax(_fractionalBitCount))
}
static var _fractionalBitMask: SignificandBits {
return _integralBitMask - 1
}
static var _quietBitMask: SignificandBits {
return _integralBitMask >> 1
}
static var _payloadBitMask: SignificandBits {
return _quietBitMask - 1
}
public static var infinity: Self {
return Self(signbit: false,
exponentBitPattern:_infinityExponent,
significandBitPattern: 0)
}
public static func NaN(payload bits: SignificandBits, signaling: Bool) -> Self {
var significand = bits & _payloadBitMask
if signaling {
// Ensure at least one bit is set in payload, otherwise we will get
// an infinity instead of NaN.
if significand == 0 {
significand = _quietBitMask >> 1
}
} else {
significand = significand | _quietBitMask
}
return Self(signbit: false,
exponentBitPattern: _infinityExponent,
significandBitPattern: significand)
}
public static var greatestFiniteMagnitude: Self {
return Self(signbit: false,
exponentBitPattern: _infinityExponent - 1,
significandBitPattern: _fractionalBitMask)
}
public static var leastNormalMagnitude: Self {
return Self(signbit: false, exponentBitPattern: 1, significandBitPattern: 0)
}
public static var leastMagnitude: Self {
#if arch(arm)
return .leastNormalMagnitude
#else
return Self(signbit: false, exponentBitPattern: 0, significandBitPattern: 1)
#endif
}
public var exponent: Int {
if !isFinite { return .max }
let provisional = Int(exponentBitPattern) - Int(Self._exponentBias)
if isNormal { return provisional }
if isZero { return .min }
let shift = significandBitPattern.leadingZeros - Self._fractionalBitMask.leadingZeros
return provisional - Int(shift)
}
public var significand: Self {
if isNaN { return self }
if isNormal {
return Self(Self._integralBitMask | significandBitPattern) * Self.ulp
}
if isZero { return 0 }
let shift = 1 + significandBitPattern.leadingZeros - Self._fractionalBitMask.leadingZeros
return Self(significandBitPattern << SignificandBits(shift)) * Self.ulp
}
public init(signbit: Bool, exponent: Int, significand: Self) {
var result = significand
if signbit { result = -result }
if significand.isFinite && !significand.isZero {
var clamped = exponent
if clamped < Self.leastNormalMagnitude.exponent {
clamped = max(clamped, 3*Self.leastNormalMagnitude.exponent)
while clamped < Self.leastNormalMagnitude.exponent {
result = result * Self.leastNormalMagnitude
clamped += Self.leastNormalMagnitude.exponent
}
}
else if clamped > Self.greatestFiniteMagnitude.exponent {
clamped = min(clamped, 3*Self.greatestFiniteMagnitude.exponent)
while clamped > Self.greatestFiniteMagnitude.exponent {
result = result * Self.greatestFiniteMagnitude.binade
clamped -= Self.greatestFiniteMagnitude.exponent
}
}
let scale = Self(signbit: false,
exponentBitPattern: UInt(Int(Self._exponentBias) + clamped),
significandBitPattern: Self._integralBitMask)
result = result * scale
}
self = result
}
public var ulp: Self {
if !isFinite { return .NaN }
if exponentBitPattern > Self._fractionalBitCount {
// ulp is normal, so we directly manifest its exponent and use a
// significand of 1.
let ulpExponent = exponentBitPattern - Self._fractionalBitCount
return Self(signbit: false, exponentBitPattern: ulpExponent, significandBitPattern: 0)
}
if exponentBitPattern >= 1 {
// self is normal, but ulp is subnormal; we need to compute a shift
// to apply to the significand.
let ulpShift = SignificandBits(exponentBitPattern - 1)
return Self(signbit: false, exponentBitPattern: 0, significandBitPattern: 1 << ulpShift)
}
return Self(signbit:false, exponentBitPattern:0, significandBitPattern:1)
}
public var nextUp: Self {
if isNaN { return self }
if signbit {
if significandBitPattern == 0 {
if exponentBitPattern == 0 { return Self.leastMagnitude }
return Self(signbit: true,
exponentBitPattern: exponentBitPattern - 1,
significandBitPattern: Self._fractionalBitMask)
}
return Self(signbit: true,
exponentBitPattern: exponentBitPattern,
significandBitPattern: significandBitPattern - 1)
}
if isInfinite { return self }
if significandBitPattern == Self._fractionalBitMask {
return Self(signbit: false,
exponentBitPattern: exponentBitPattern + 1,
significandBitPattern: 0)
}
return Self(signbit: false,
exponentBitPattern: exponentBitPattern,
significandBitPattern: significandBitPattern + 1)
}
public var nextDown: Self { return -(-self).nextUp }
public var binade: Self {
if !isFinite { return .NaN }
if isNormal {
return Self(signbit: false, exponentBitPattern: exponentBitPattern,
significandBitPattern: Self._integralBitMask)
}
if isZero { return 0 }
let shift = significandBitPattern.leadingZeros - Self._integralBitMask.leadingZeros
let significand = Self._integralBitMask >> SignificandBits(shift)
return Self(signbit: false, exponentBitPattern: 0,
significandBitPattern: significand)
}
public static func add<X: BinaryFloatingPointType, Y: BinaryFloatingPointType>(x: X, _ y: Y) -> Self {
if X._fractionalBitCount < Y._fractionalBitCount { return add(y, x) }
if X._fractionalBitCount <= Self._fractionalBitCount { return Self(x) + Self(y) }
return Self(X._addStickyRounding(x, X(y)))
}
public static func sub<X: BinaryFloatingPointType, Y: BinaryFloatingPointType>(x: X, _ y: Y) -> Self {
return Self.add(x, -y)
}
public static func mul<X: BinaryFloatingPointType, Y: BinaryFloatingPointType>(x: X, _ y: Y) -> Self {
if X._fractionalBitCount < Y._fractionalBitCount { return mul(y, x) }
if X._fractionalBitCount <= Self._fractionalBitCount { return Self(x) * Self(y) }
return Self(X._mulStickyRounding(x, X(y)))
}
public static func div<X: BinaryFloatingPointType, Y: BinaryFloatingPointType>(x: X, _ y: Y) -> Self {
if X._fractionalBitCount <= Self._fractionalBitCount &&
Y._fractionalBitCount <= Self._fractionalBitCount { return Self(x) / Self(y) }
if X._fractionalBitCount < Y._fractionalBitCount { return Self(Y._divStickyRounding(Y(x), y)) }
return Self(X._divStickyRounding(x, X(y)))
}
public static func sqrt<X: BinaryFloatingPointType>(x: X) -> Self {
if X._fractionalBitCount <= Self._fractionalBitCount { return sqrt(Self(x)) }
return Self(X._sqrtStickyRounding(x))
}
public static func mulAdd<X: BinaryFloatingPointType, Y: BinaryFloatingPointType, Z: BinaryFloatingPointType>(x: X, _ y: Y, _ z: Z) -> Self {
if X._fractionalBitCount < Y._fractionalBitCount { return mulAdd(y, x, z) }
if X._fractionalBitCount <= Self._fractionalBitCount &&
Z._fractionalBitCount <= Self._fractionalBitCount { return mulAdd(Self(x), Self(y), Self(z)) }
if X._fractionalBitCount < Z._fractionalBitCount { return Self(Z._mulAddStickyRounding(Z(x), Z(y), z)) }
return Self(X._mulAddStickyRounding(x, X(y), X(z)))
}
public var absoluteValue: Self {
return Self(signbit: false, exponentBitPattern: exponentBitPattern,
significandBitPattern: significandBitPattern)
}
public func copysign(from: Self) -> Self {
return Self(signbit: from.signbit, exponentBitPattern: exponentBitPattern,
significandBitPattern: significandBitPattern)
}
public var isZero: Bool {
return exponentBitPattern == 0 && significandBitPattern == 0
}
public var isSubnormal: Bool {
return exponentBitPattern == 0 && significandBitPattern != 0
}
public var isNormal: Bool {
return exponentBitPattern > 0 && isFinite
}
public var isFinite: Bool {
return exponentBitPattern < Self._infinityExponent
}
public var isInfinite: Bool {
return exponentBitPattern == Self._infinityExponent &&
significandBitPattern == Self._integralBitMask
}
public var isNaN: Bool {
return exponentBitPattern == Self._infinityExponent && !isInfinite
}
public var isSignaling: Bool {
return isNaN && (significandBitPattern & Self._quietBitMask == 0)
}
public var isCanonical: Bool { return true }
public func totalOrder(other: Self) -> Bool {
// Every negative-signed value (even NaN) is less than every positive-
// signed value, so if the signs do not match, we simply return the
// signbit of self.
if signbit != other.signbit { return signbit }
// Signbits match; look at exponents.
if exponentBitPattern > other.exponentBitPattern { return signbit }
if exponentBitPattern < other.exponentBitPattern { return !signbit }
// Signs and exponents match, look at significands.
if significandBitPattern > other.significandBitPattern { return signbit }
if significandBitPattern < other.significandBitPattern { return !signbit }
return true
}
}
public protocol FloatingPointInterchangeType: FloatingPointType {
/// An unsigned integer type used to represent floating-point encodings.
typealias BitPattern: FloatingPointRepresentationType
/// Interpret `encoding` as a little-endian encoding of `Self`.
init(littleEndian encoding: BitPattern)
/// Interpret `encoding` as a big-endian encoding of `Self`.
init(bigEndian encoding: BitPattern)
/// Get the little-endian encoding of `self` as an integer.
var littleEndian: BitPattern { get }
/// Get the big-endian encoding of `self` as an integer.
var bigEndian: BitPattern { get }
}
extension FloatingPointInterchangeType {
public init(littleEndian encoding: BitPattern) {
#if arch(i386) || arch(x86_64) || arch(arm) || arch(arm64)
self = unsafeBitCast(encoding, Self.self)
#else
_UnsupportedArchitectureError()
#endif
}
public init(bigEndian encoding: BitPattern) {
fatalError("TODO: with low-level generic integer type support for bswap.")
}
public var littleEndian: BitPattern {
#if arch(i386) || arch(x86_64) || arch(arm) || arch(arm64)
return unsafeBitCast(self, BitPattern.self)
#else
_UnsupportedArchitectureError()
#endif
}
public var bigEndian: BitPattern {
fatalError("TODO: with low-level generic integer type support for bswap.")
}
}
extension Float : BinaryFloatingPointType, FloatingPointInterchangeType {
var _representation: UInt32 { return unsafeBitCast(self, UInt32.self) }
public typealias SignificandBits = UInt32
public typealias BitPattern = UInt32
public static var _fractionalBitCount: UInt { return 23 }
public static var _exponentBitCount: UInt { return 8 }
public var signbit: Bool { return _representation >> 31 == 1 }
public var exponentBitPattern: UInt { return UInt(_representation >> 23) & 0xff }
public var significandBitPattern: SignificandBits { return _representation & Float._fractionalBitMask }
public init(signbit: Bool, exponentBitPattern: UInt, significandBitPattern: SignificandBits) {
let sign = SignificandBits(signbit ? 1 : 0) << 31
let exponent = SignificandBits(exponentBitPattern) << 23
let _representation = sign | exponent | significandBitPattern
self = unsafeBitCast(_representation, Float.self)
}
public init<T: BinaryFloatingPointType>(_ other: T) {
// rdar://16980851 #if does not work with 'switch'
#if arch(i386) || arch(x86_64)
switch other {
case let f as Float:
self = f
case let d as Double:
self = Float(d)
case let ld as Float80:
self = Float(ld)
default:
fatalError()
}
#else
switch other {
case let f as Float:
self = f
case let d as Double:
self = Float(d)
default:
fatalError()
}
#endif
}
public func roundToIntegralTiesToAway() -> Float { return roundf(self) }
public func roundToIntegralTowardZero() -> Float { return truncf(self) }
public func roundToIntegralTowardPositive() -> Float { return ceilf(self) }
public func roundToIntegralTowardNegative() -> Float { return floorf(self) }
public static func remainder(left: Float, _ right: Float) -> Float { return remainderf(left, right) }
public static func min(left: Float, _ right: Float) -> Float { return fminf(left, right) }
public static func max(left: Float, _ right: Float) -> Float { return fmaxf(left, right) }
public static func sqrt(x: Float) -> Float { return sqrtf(x) }
}
extension Double : BinaryFloatingPointType {
var _representation: UInt64 { return unsafeBitCast(self, UInt64.self) }
public typealias SignificandBits = UInt64
public static var _fractionalBitCount: UInt { return 52 }
public static var _exponentBitCount: UInt { return 11 }
public var signbit: Bool { return _representation >> 63 == 1 }
public var exponentBitPattern: UInt { return UInt(_representation >> 52) & 0x7ff }
public var significandBitPattern: SignificandBits { return _representation & Double._fractionalBitMask }
public init(signbit: Bool, exponentBitPattern: UInt, significandBitPattern: SignificandBits) {
let sign = SignificandBits(signbit ? 1 : 0) << 63
let exponent = SignificandBits(exponentBitPattern) << 52
let _representation = sign | exponent | significandBitPattern
self = unsafeBitCast(_representation, Double.self)
}
public init<T: BinaryFloatingPointType>(_ other: T) {
// rdar://16980851 #if does not work with 'switch' cases
#if arch(i386) || arch(x86_64)
switch other {
case let f as Float:
self = Double(f)
case let d as Double:
self = d
case let ld as Float80:
self = Double(ld)
default:
fatalError()
}
#else
switch other {
case let f as Float:
self = Double(f)
case let d as Double:
self = d
default:
fatalError()
}
#endif
}
public func roundToIntegralTiesToAway() -> Double { return round(self) }
public func roundToIntegralTowardZero() -> Double { return trunc(self) }
public func roundToIntegralTowardPositive() -> Double { return ceil(self) }
public func roundToIntegralTowardNegative() -> Double { return floor(self) }
public static func remainder(left: Double, _ right: Double) -> Double { return remainder(left, right) }
public static func min(left: Double, _ right: Double) -> Double { return fmin(left, right) }
public static func max(left: Double, _ right: Double) -> Double { return fmax(left, right) }
}
#if arch(i386) || arch(x86_64)
extension Float80 : BinaryFloatingPointType {
// Internal implementation details
struct _Float80Representation {
var explicitSignificand: UInt64
var signAndExponent: UInt16
var _padding: (UInt16, UInt16, UInt16) = (0, 0, 0)
var signbit: Bool { return signAndExponent >> 15 == 1 }
var exponentBitPattern: UInt { return UInt(signAndExponent) & 0x7fff }
init(explicitSignificand: UInt64, signAndExponent: UInt16) {
self.explicitSignificand = explicitSignificand
self.signAndExponent = signAndExponent
}
}
var _representation: _Float80Representation {
return unsafeBitCast(self, _Float80Representation.self)
}
// Public requirements
public typealias SignificandBits = UInt64
public static var _fractionalBitCount: UInt { return 63 }
public static var _exponentBitCount: UInt { return 15 }
public var signbit: Bool { return _representation.signbit }
public var exponentBitPattern: UInt {
if _representation.exponentBitPattern == 0 {
if _representation.explicitSignificand >= Float80._integralBitMask {
// Pseudo-denormals have an exponent of 0 but the leading bit of the
// significand field is set. These are non-canonical encodings of the
// same significand with an exponent of 1.
return 1
}
// Exponent is zero, leading bit of significand is clear, so this is
// just a canonical zero or subnormal number.
return 0
}
if _representation.explicitSignificand < Float80._integralBitMask {
// If the exponent is not-zero and the leading bit of the significand
// is clear, then we have an invalid operand (unnormal, pseudo-inf, or
// pseudo-nan). All of these are treated as NaN by the hardware, so
// we pretend that the exponent is that of a NaN.
return Float80._infinityExponent
}
return _representation.exponentBitPattern
}
public var significandBitPattern: UInt64 {
if _representation.exponentBitPattern > 0 &&
_representation.explicitSignificand < Float80._integralBitMask {
// If the exponent is non-zero and the leading bit of the significand
// is clear, then we have an invalid operand (unnormal, pseudo-inf, or
// pseudo-nan). All of these are treated as NaN by the hardware, so
// we make sure that bit of the signficand field is set.
return _representation.explicitSignificand | Float80._quietBitMask
}
// Otherwise we always get the "right" significand by simply clearing the
// integral bit.
return _representation.explicitSignificand & Float80._fractionalBitMask
}
public init(signbit: Bool, exponentBitPattern: UInt, significandBitPattern: UInt64) {
let sign = UInt16(signbit ? 0x8000 : 0)
let exponent = UInt16(exponentBitPattern)
var significand = significandBitPattern
if exponent != 0 { significand |= Float80._integralBitMask }
let representation = _Float80Representation(explicitSignificand: significand, signAndExponent: sign|exponent)
self = unsafeBitCast(representation, Float80.self)
}
public init<T: BinaryFloatingPointType>(_ other: T) {
switch other {
case let f as Float:
self = Float80(f)
case let d as Double:
self = Float80(d)
case let ld as Float80:
self = ld
default:
fatalError()
}
}
public func roundToIntegralTiesToAway() -> Float80 { fatalError("TODO: nead roundl( )") }
public func roundToIntegralTowardZero() -> Float80 { fatalError("TODO: nead truncl( )") }
public func roundToIntegralTowardPositive() -> Float80 { fatalError("TODO: nead ceill( )") }
public func roundToIntegralTowardNegative() -> Float80 { fatalError("TODO: nead floorl( )") }
public static func remainder(left: Float80, _ right: Float80) -> Float80 { fatalError("TODO: nead remainderl( )") }
public static func min(left: Float80, _ right: Float80) -> Float80 { fatalError("TODO: nead fminl( )") }
public static func max(left: Float80, _ right: Float80) -> Float80 { fatalError("TODO: nead fmaxl( )") }
public var isCanonical: Bool {
if exponentBitPattern == 0 {
return _representation.explicitSignificand < Float80._integralBitMask
}
return _representation.explicitSignificand >= Float80._integralBitMask
}
}
#endif
// Unchanged from existing FloatingPoint protocol support.
/// The set of IEEE-754 floating-point "classes". Every floating-point datum
/// belongs to exactly one of these classes.
public enum FloatingPointClassification {
case SignalingNaN
case QuietNaN
case NegativeInfinity
case NegativeNormal
case NegativeSubnormal
case NegativeZero
case PositiveZero
case PositiveSubnormal
case PositiveNormal
case PositiveInfinity
}
extension FloatingPointClassification : Equatable {}
public func ==(lhs: FloatingPointClassification, rhs: FloatingPointClassification) -> Bool {
switch (lhs, rhs) {
case (.SignalingNaN, .SignalingNaN),
(.QuietNaN, .QuietNaN),
(.NegativeInfinity, .NegativeInfinity),
(.NegativeNormal, .NegativeNormal),
(.NegativeSubnormal, .NegativeSubnormal),
(.NegativeZero, .NegativeZero),
(.PositiveZero, .PositiveZero),
(.PositiveSubnormal, .PositiveSubnormal),
(.PositiveNormal, .PositiveNormal),
(.PositiveInfinity, .PositiveInfinity):
return true
default:
return false
}
}
//===--- tests ------------------------------------------------------------===//
import StdlibUnittest
var tests = TestSuite("Floating Point")
tests.test("Parts") {
expectEqual(Int.max, (-Float.infinity).exponent)
expectEqual(127, (-Float.greatestFiniteMagnitude).exponent)
expectEqual(1, Float(-2).exponent)
expectEqual(0, Float(-1).exponent)
expectEqual(-1, Float(-0.5).exponent)
expectEqual(-23, (-Float.ulp).exponent)
expectEqual(-125, (-2*Float.leastNormalMagnitude).exponent)
expectEqual(-126, Float.leastNormalMagnitude.exponent)
#if !arch(arm)
expectEqual(-127, (-0.5*Float.leastNormalMagnitude).exponent)
expectEqual(-149, (-Float.leastMagnitude).exponent)
#endif
expectEqual(Int.min, Float(-0).exponent)
expectEqual(Int.min, Float(0).exponent)
#if !arch(arm)
expectEqual(-149, Float.leastMagnitude.exponent)
expectEqual(-127, (Float.leastNormalMagnitude/2).exponent)
#endif
expectEqual(-126, Float.leastNormalMagnitude.exponent)
expectEqual(-125, (2*Float.leastNormalMagnitude).exponent)
expectEqual(-23, Float.ulp.exponent)
expectEqual(-1, Float(0.5).exponent)
expectEqual(0, Float(1).exponent)
expectEqual(1, Float(2).exponent)
expectEqual(127, Float.greatestFiniteMagnitude.exponent)
expectEqual(Int.max, Float.infinity.exponent)
expectEqual(Int.max, Float.NaN.exponent)
expectEqual(Int.max, (-Double.infinity).exponent)
expectEqual(1023, (-Double.greatestFiniteMagnitude).exponent)
expectEqual(1, Double(-2).exponent)
expectEqual(0, Double(-1).exponent)
expectEqual(-1, Double(-0.5).exponent)
expectEqual(-52, (-Double.ulp).exponent)
expectEqual(-1021, (-2*Double.leastNormalMagnitude).exponent)
expectEqual(-1022, Double.leastNormalMagnitude.exponent)
#if !arch(arm)
expectEqual(-1023, (-0.5*Double.leastNormalMagnitude).exponent)
expectEqual(-1074, (-Double.leastMagnitude).exponent)
#endif
expectEqual(Int.min, Double(-0).exponent)
expectEqual(Int.min, Double(0).exponent)
#if !arch(arm)
expectEqual(-1074, Double.leastMagnitude.exponent)
expectEqual(-1023, (Double.leastNormalMagnitude/2).exponent)
#endif
expectEqual(-1022, Double.leastNormalMagnitude.exponent)
expectEqual(-1021, (2*Double.leastNormalMagnitude).exponent)
expectEqual(-52, Double.ulp.exponent)
expectEqual(-1, Double(0.5).exponent)
expectEqual(0, Double(1).exponent)
expectEqual(1, Double(2).exponent)
expectEqual(1023, Double.greatestFiniteMagnitude.exponent)
expectEqual(Int.max, Double.infinity.exponent)
expectEqual(Int.max, Double.NaN.exponent)
#if arch(i386) || arch(x86_64)
expectEqual(Int.max, (-Float80.infinity).exponent)
expectEqual(16383, (-Float80.greatestFiniteMagnitude).exponent)
expectEqual(1, Float80(-2).exponent)
expectEqual(0, Float80(-1).exponent)
expectEqual(-1, Float80(-0.5).exponent)
expectEqual(-63, (-Float80.ulp).exponent)
expectEqual(-16381, (-2*Float80.leastNormalMagnitude).exponent)
expectEqual(-16382, Float80.leastNormalMagnitude.exponent)
expectEqual(-16383, (-0.5*Float80.leastNormalMagnitude).exponent)
expectEqual(-16445, (-Float80.leastMagnitude).exponent)
expectEqual(Int.min, Float80(-0).exponent)
expectEqual(Int.min, Float80(0).exponent)
expectEqual(-16445, Float80.leastMagnitude.exponent)
expectEqual(-16383, (Float80.leastNormalMagnitude/2).exponent)
expectEqual(-16382, Float80.leastNormalMagnitude.exponent)
expectEqual(-16381, (2*Float80.leastNormalMagnitude).exponent)
expectEqual(-63, Float80.ulp.exponent)
expectEqual(-1, Float80(0.5).exponent)
expectEqual(0, Float80(1).exponent)
expectEqual(1, Float80(2).exponent)
expectEqual(16383, Float80.greatestFiniteMagnitude.exponent)
expectEqual(Int.max, Float80.infinity.exponent)
expectEqual(Int.max, Float80.NaN.exponent)
#endif
}
runAllTests()