mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
* Updates to tgmath functions for CGFloat These changes bring CGFloat in line with the other FloatingPoint types. Some of this stuff is now defined at the protocol level, so we can get rid of it at the concrete type level. A couple other functions have been deprecated for all types, with protocol or tgmath replacements.
662 lines
16 KiB
Swift
662 lines
16 KiB
Swift
//===--- CGFloat.swift.gyb ------------------------------------*- swift -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://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
|
|
|
|
}%
|
|
|
|
@_exported import CoreGraphics
|
|
import Darwin
|
|
|
|
@_fixed_layout
|
|
public struct CGFloat {
|
|
#if arch(i386) || arch(arm)
|
|
/// The native type used to store the CGFloat, which is Float on
|
|
/// 32-bit architectures and Double on 64-bit architectures.
|
|
public typealias NativeType = Float
|
|
#elseif arch(x86_64) || arch(arm64)
|
|
/// The native type used to store the CGFloat, which is Float on
|
|
/// 32-bit architectures and Double on 64-bit architectures.
|
|
public typealias NativeType = Double
|
|
#endif
|
|
|
|
@_transparent public init() {
|
|
self.native = 0.0
|
|
}
|
|
|
|
@_transparent public init(_ value: Float) {
|
|
self.native = NativeType(value)
|
|
}
|
|
|
|
@_transparent public init(_ value: Double) {
|
|
self.native = NativeType(value)
|
|
}
|
|
|
|
#if !os(Windows) && (arch(i386) || arch(x86_64))
|
|
@_transparent public init(_ value: Float80) {
|
|
self.native = NativeType(value)
|
|
}
|
|
#endif
|
|
|
|
@_transparent public init(_ value: CGFloat) {
|
|
self.native = value.native
|
|
}
|
|
|
|
% for src_ty in all_integer_types(word_bits):
|
|
@_transparent public init(_ value: ${src_ty.stdlib_name}) {
|
|
self.native = NativeType(value)
|
|
}
|
|
|
|
% end
|
|
|
|
/// The native value.
|
|
public var native: NativeType
|
|
}
|
|
|
|
extension CGFloat : SignedNumeric {
|
|
// FIXME(integers): implement properly
|
|
public init?<T : BinaryInteger>(exactly source: T) {
|
|
fatalError()
|
|
}
|
|
|
|
@_transparent
|
|
public var magnitude: CGFloat {
|
|
return CGFloat(Swift.abs(native))
|
|
}
|
|
|
|
}
|
|
|
|
extension CGFloat : BinaryFloatingPoint {
|
|
|
|
public typealias RawSignificand = UInt
|
|
public typealias Exponent = Int
|
|
|
|
@_transparent
|
|
public static var exponentBitCount: Int {
|
|
return NativeType.exponentBitCount
|
|
}
|
|
|
|
@_transparent
|
|
public static var significandBitCount: Int {
|
|
return NativeType.significandBitCount
|
|
}
|
|
|
|
// Conversions to/from integer encoding. These are not part of the
|
|
// BinaryFloatingPoint prototype because there's no guarantee that an
|
|
// integer type of the same size actually exists (e.g. Float80).
|
|
@_transparent
|
|
public var bitPattern: UInt {
|
|
return UInt(native.bitPattern)
|
|
}
|
|
|
|
@_transparent
|
|
public init(bitPattern: UInt) {
|
|
native = NativeType(bitPattern: UInt${word_bits}(bitPattern))
|
|
}
|
|
|
|
@_transparent
|
|
public var sign: FloatingPointSign {
|
|
return native.sign
|
|
}
|
|
|
|
@_transparent
|
|
public var exponentBitPattern: UInt {
|
|
return native.exponentBitPattern
|
|
}
|
|
|
|
@_transparent
|
|
public var significandBitPattern: UInt {
|
|
return UInt(native.significandBitPattern)
|
|
}
|
|
|
|
@_transparent
|
|
public init(sign: FloatingPointSign,
|
|
exponentBitPattern: UInt,
|
|
significandBitPattern: UInt) {
|
|
native = NativeType(sign: sign,
|
|
exponentBitPattern: exponentBitPattern,
|
|
significandBitPattern: NativeType.RawSignificand(significandBitPattern))
|
|
}
|
|
|
|
@_transparent
|
|
public init(nan payload: RawSignificand, signaling: Bool) {
|
|
native = NativeType(nan: NativeType.RawSignificand(payload),
|
|
signaling: signaling)
|
|
}
|
|
|
|
@_transparent
|
|
public static var infinity: CGFloat {
|
|
return CGFloat(NativeType.infinity)
|
|
}
|
|
|
|
@_transparent
|
|
public static var nan: CGFloat {
|
|
return CGFloat(NativeType.nan)
|
|
}
|
|
|
|
@_transparent
|
|
public static var signalingNaN: CGFloat {
|
|
return CGFloat(NativeType.signalingNaN)
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "nan")
|
|
public static var quietNaN: CGFloat {
|
|
fatalError("unavailable")
|
|
}
|
|
|
|
@_transparent
|
|
public static var greatestFiniteMagnitude: CGFloat {
|
|
return CGFloat(NativeType.greatestFiniteMagnitude)
|
|
}
|
|
|
|
@_transparent
|
|
public static var pi: CGFloat {
|
|
return CGFloat(NativeType.pi)
|
|
}
|
|
|
|
@_transparent
|
|
public var ulp: CGFloat {
|
|
return CGFloat(native.ulp)
|
|
}
|
|
|
|
@_transparent
|
|
public static var leastNormalMagnitude: CGFloat {
|
|
return CGFloat(NativeType.leastNormalMagnitude)
|
|
}
|
|
|
|
@_transparent
|
|
public static var leastNonzeroMagnitude: CGFloat {
|
|
return CGFloat(NativeType.leastNonzeroMagnitude)
|
|
}
|
|
|
|
@_transparent
|
|
public var exponent: Int {
|
|
return native.exponent
|
|
}
|
|
|
|
@_transparent
|
|
public var significand: CGFloat {
|
|
return CGFloat(native.significand)
|
|
}
|
|
|
|
@_transparent
|
|
public init(sign: FloatingPointSign, exponent: Int, significand: CGFloat) {
|
|
native = NativeType(sign: sign,
|
|
exponent: exponent, significand: significand.native)
|
|
}
|
|
|
|
@_transparent
|
|
public mutating func round(_ rule: FloatingPointRoundingRule) {
|
|
native.round(rule)
|
|
}
|
|
|
|
@_transparent
|
|
public var nextUp: CGFloat {
|
|
return CGFloat(native.nextUp)
|
|
}
|
|
|
|
public mutating func negate() {
|
|
native.negate()
|
|
}
|
|
|
|
@_transparent
|
|
public static func +=(_ lhs: inout CGFloat, _ rhs: CGFloat) {
|
|
lhs.native += rhs.native
|
|
}
|
|
|
|
@_transparent
|
|
public static func -=(_ lhs: inout CGFloat, _ rhs: CGFloat) {
|
|
lhs.native -= rhs.native
|
|
}
|
|
|
|
@_transparent
|
|
public static func *=(_ lhs: inout CGFloat, _ rhs: CGFloat) {
|
|
lhs.native *= rhs.native
|
|
}
|
|
|
|
@_transparent
|
|
public static func /=(_ lhs: inout CGFloat, _ rhs: CGFloat) {
|
|
lhs.native /= rhs.native
|
|
}
|
|
|
|
@_transparent
|
|
public mutating func formTruncatingRemainder(dividingBy other: CGFloat) {
|
|
native.formTruncatingRemainder(dividingBy: other.native)
|
|
}
|
|
|
|
@_transparent
|
|
public mutating func formRemainder(dividingBy other: CGFloat) {
|
|
native.formRemainder(dividingBy: other.native)
|
|
}
|
|
|
|
@_transparent
|
|
public mutating func formSquareRoot( ) {
|
|
native.formSquareRoot( )
|
|
}
|
|
|
|
@_transparent
|
|
public mutating func addProduct(_ lhs: CGFloat, _ rhs: CGFloat) {
|
|
native.addProduct(lhs.native, rhs.native)
|
|
}
|
|
|
|
@_transparent
|
|
public func isEqual(to other: CGFloat) -> Bool {
|
|
return self.native.isEqual(to: other.native)
|
|
}
|
|
|
|
@_transparent
|
|
public func isLess(than other: CGFloat) -> Bool {
|
|
return self.native.isLess(than: other.native)
|
|
}
|
|
|
|
@_transparent
|
|
public func isLessThanOrEqualTo(_ other: CGFloat) -> Bool {
|
|
return self.native.isLessThanOrEqualTo(other.native)
|
|
}
|
|
|
|
@_transparent
|
|
public var isNormal: Bool {
|
|
return native.isNormal
|
|
}
|
|
|
|
@_transparent
|
|
public var isFinite: Bool {
|
|
return native.isFinite
|
|
}
|
|
|
|
public var isZero: Bool {
|
|
return native.isZero
|
|
}
|
|
|
|
public var isSubnormal: Bool {
|
|
return native.isSubnormal
|
|
}
|
|
|
|
public var isInfinite: Bool {
|
|
return native.isInfinite
|
|
}
|
|
|
|
public var isNaN: Bool {
|
|
return native.isNaN
|
|
}
|
|
|
|
public var isSignalingNaN: Bool {
|
|
return native.isSignalingNaN
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "isSignalingNaN")
|
|
public var isSignaling: Bool {
|
|
fatalError("unavailable")
|
|
}
|
|
|
|
public var isCanonical: Bool {
|
|
return true
|
|
}
|
|
|
|
public var floatingPointClass: FloatingPointClassification {
|
|
return native.floatingPointClass
|
|
}
|
|
|
|
public var binade: CGFloat {
|
|
return CGFloat(native.binade)
|
|
}
|
|
|
|
public var significandWidth: Int {
|
|
return native.significandWidth
|
|
}
|
|
|
|
/// Create an instance initialized to `value`.
|
|
@_transparent
|
|
public init(floatLiteral value: NativeType) {
|
|
native = value
|
|
}
|
|
|
|
/// Create an instance initialized to `value`.
|
|
@_transparent
|
|
public init(integerLiteral value: Int) {
|
|
native = NativeType(value)
|
|
}
|
|
}
|
|
|
|
extension CGFloat {
|
|
@available(*, unavailable, renamed: "leastNormalMagnitude")
|
|
public static var min: CGFloat {
|
|
fatalError("unavailable")
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "greatestFiniteMagnitude")
|
|
public static var max: CGFloat {
|
|
fatalError("unavailable")
|
|
}
|
|
|
|
@available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Please use the `abs(_:)` free function")
|
|
@_transparent
|
|
public static func abs(_ x: CGFloat) -> CGFloat {
|
|
return x.magnitude
|
|
}
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "CGFloat.leastNormalMagnitude")
|
|
public var CGFLOAT_MIN: CGFloat {
|
|
fatalError("unavailable")
|
|
}
|
|
|
|
@available(*, unavailable, renamed: "CGFloat.greatestFiniteMagnitude")
|
|
public var CGFLOAT_MAX: CGFloat {
|
|
fatalError("unavailable")
|
|
}
|
|
|
|
extension CGFloat : CustomReflectable {
|
|
/// Returns a mirror that reflects `self`.
|
|
public var customMirror: Mirror {
|
|
return Mirror(reflecting: native)
|
|
}
|
|
}
|
|
|
|
extension CGFloat : CustomStringConvertible {
|
|
/// A textual representation of `self`.
|
|
@_transparent
|
|
public var description: String {
|
|
return native.description
|
|
}
|
|
}
|
|
|
|
extension CGFloat : Hashable {
|
|
/// The hash value.
|
|
///
|
|
/// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`
|
|
///
|
|
/// - Note: the hash value is not guaranteed to be stable across
|
|
/// different invocations of the same program. Do not persist the
|
|
/// hash value across program runs.
|
|
@_transparent
|
|
public var hashValue: Int {
|
|
return native.hashValue
|
|
}
|
|
}
|
|
|
|
% for dst_ty in all_integer_types(word_bits):
|
|
|
|
extension ${dst_ty.stdlib_name} {
|
|
@_transparent
|
|
public init(_ value: CGFloat) {
|
|
self = ${dst_ty.stdlib_name}(value.native)
|
|
}
|
|
}
|
|
|
|
% end
|
|
|
|
|
|
extension Double {
|
|
@_transparent
|
|
public init(_ value: CGFloat) {
|
|
self = Double(value.native)
|
|
}
|
|
}
|
|
|
|
extension Float {
|
|
@_transparent
|
|
public init(_ value: CGFloat) {
|
|
self = Float(value.native)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Standard Operator Table
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TODO: These should not be necessary, since they're already provided by
|
|
// <T: FloatingPoint>, but in practice they are currently needed to
|
|
// disambiguate overloads. We should find a way to remove them, either by
|
|
// tweaking the overload resolution rules, or by removing the other
|
|
// definitions in the standard lib, or both.
|
|
|
|
extension CGFloat {
|
|
@_transparent
|
|
public static func +(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
|
|
var lhs = lhs
|
|
lhs += rhs
|
|
return lhs
|
|
}
|
|
|
|
@_transparent
|
|
public static func -(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
|
|
var lhs = lhs
|
|
lhs -= rhs
|
|
return lhs
|
|
}
|
|
|
|
@_transparent
|
|
public static func *(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
|
|
var lhs = lhs
|
|
lhs *= rhs
|
|
return lhs
|
|
}
|
|
|
|
@_transparent
|
|
public static func /(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
|
|
var lhs = lhs
|
|
lhs /= rhs
|
|
return lhs
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Strideable Conformance
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension CGFloat : Strideable {
|
|
/// Returns a stride `x` such that `self.advanced(by: x)` approximates
|
|
/// `other`.
|
|
///
|
|
/// - Complexity: O(1).
|
|
@_transparent
|
|
public func distance(to other: CGFloat) -> CGFloat {
|
|
return CGFloat(other.native - self.native)
|
|
}
|
|
|
|
/// Returns a `Self` `x` such that `self.distance(to: x)` approximates
|
|
/// `n`.
|
|
///
|
|
/// - Complexity: O(1).
|
|
@_transparent
|
|
public func advanced(by amount: CGFloat) -> CGFloat {
|
|
return CGFloat(self.native + amount.native)
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Deprecated operators
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@_transparent
|
|
@available(*, unavailable, message: "Use truncatingRemainder instead")
|
|
public func %(lhs: CGFloat, rhs: CGFloat) -> CGFloat {
|
|
fatalError("% is not available.")
|
|
}
|
|
|
|
@_transparent
|
|
@available(*, unavailable, message: "Use formTruncatingRemainder instead")
|
|
public func %=(lhs: inout CGFloat, rhs: CGFloat) {
|
|
fatalError("%= is not available.")
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// tgmath
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
%{
|
|
UnaryFunctions = [
|
|
'acos', 'asin', 'atan', 'cos', 'sin', 'tan',
|
|
'acosh', 'asinh', 'atanh', 'cosh', 'sinh', 'tanh',
|
|
'exp', 'exp2', 'expm1',
|
|
'log', 'log10', 'log1p', 'log2', 'logb',
|
|
'cbrt', 'erf', 'erfc', 'tgamma',
|
|
'nearbyint', 'rint'
|
|
]
|
|
|
|
BinaryFunctions = [
|
|
'atan2', 'hypot', 'pow', 'copysign', 'nextafter', 'fdim', 'fmax', 'fmin'
|
|
]
|
|
}%
|
|
|
|
%for ufunc in UnaryFunctions:
|
|
@_transparent
|
|
public func ${ufunc}(_ x: CGFloat) -> CGFloat {
|
|
return CGFloat(${ufunc}(x.native))
|
|
}
|
|
|
|
%end
|
|
|
|
%for bfunc in BinaryFunctions:
|
|
@_transparent
|
|
public func ${bfunc}(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat {
|
|
return CGFloat(${bfunc}(lhs.native, rhs.native))
|
|
}
|
|
|
|
%end
|
|
|
|
@_transparent
|
|
@available(*, unavailable, message: "use the floatingPointClass property.")
|
|
public func fpclassify(_ x: CGFloat) -> Int {
|
|
fatalError("unavailable")
|
|
}
|
|
|
|
@available(*, unavailable, message: "use the isNormal property.")
|
|
public func isnormal(_ value: CGFloat) -> Bool { return value.isNormal }
|
|
|
|
@available(*, unavailable, message: "use the isFinite property.")
|
|
public func isfinite(_ value: CGFloat) -> Bool { return value.isFinite }
|
|
|
|
@available(*, unavailable, message: "use the isInfinite property.")
|
|
public func isinf(_ value: CGFloat) -> Bool { return value.isInfinite }
|
|
|
|
@available(*, unavailable, message: "use the isNaN property.")
|
|
public func isnan(_ value: CGFloat) -> Bool { return value.isNaN }
|
|
|
|
@available(*, unavailable, message: "use the sign property.")
|
|
public func signbit(_ value: CGFloat) -> Int { return value.sign.rawValue }
|
|
|
|
@available(swift, deprecated: 4.2, renamed: "scalbn")
|
|
@_transparent
|
|
public func ldexp(_ x: CGFloat, _ n: Int) -> CGFloat {
|
|
return CGFloat(ldexp(x.native, n))
|
|
}
|
|
|
|
@available(swift, deprecated: 4.2, message: "use the exponent property.")
|
|
@_transparent
|
|
public func ilogb(_ x: CGFloat) -> Int {
|
|
return Int(x.exponent)
|
|
}
|
|
|
|
@_transparent
|
|
public func lgamma(_ x: CGFloat) -> (CGFloat, Int) {
|
|
let (value, sign) = lgamma(x.native)
|
|
return (CGFloat(value), sign)
|
|
}
|
|
|
|
@_transparent
|
|
public func remquo(_ x: CGFloat, _ y: CGFloat) -> (CGFloat, Int) {
|
|
let (rem, quo) = remquo(x.native, y.native)
|
|
return (CGFloat(rem), quo)
|
|
}
|
|
|
|
@available(*, deprecated: 4.2, message:
|
|
"use CGFloat(nan: CGFloat.RawSignificand) instead.")
|
|
@_transparent
|
|
public func nan(_ tag: String) -> CGFloat {
|
|
return CGFloat(nan(tag) as CGFloat.NativeType)
|
|
}
|
|
|
|
@_transparent
|
|
public func j0(_ x: CGFloat) -> CGFloat {
|
|
return CGFloat(j0(Double(x.native)))
|
|
}
|
|
|
|
@_transparent
|
|
public func j1(_ x: CGFloat) -> CGFloat {
|
|
return CGFloat(j1(Double(x.native)))
|
|
}
|
|
|
|
@_transparent
|
|
public func jn(_ n: Int, _ x: CGFloat) -> CGFloat {
|
|
return CGFloat(jn(n, Double(x.native)))
|
|
}
|
|
|
|
@_transparent
|
|
public func y0(_ x: CGFloat) -> CGFloat {
|
|
return CGFloat(y0(Double(x.native)))
|
|
}
|
|
|
|
@_transparent
|
|
public func y1(_ x: CGFloat) -> CGFloat {
|
|
return CGFloat(y1(Double(x.native)))
|
|
}
|
|
|
|
@_transparent
|
|
public func yn(_ n: Int, _ x: CGFloat) -> CGFloat {
|
|
return CGFloat(yn(n, Double(x.native)))
|
|
}
|
|
|
|
extension CGFloat : _CVarArgPassedAsDouble, _CVarArgAligned {
|
|
/// Transform `self` into a series of machine words that can be
|
|
/// appropriately interpreted by C varargs
|
|
@_transparent
|
|
public var _cVarArgEncoding: [Int] {
|
|
return native._cVarArgEncoding
|
|
}
|
|
|
|
/// Return the required alignment in bytes of
|
|
/// the value returned by `_cVarArgEncoding`.
|
|
@_transparent
|
|
public var _cVarArgAlignment: Int {
|
|
return native._cVarArgAlignment
|
|
}
|
|
}
|
|
|
|
extension CGFloat : Codable {
|
|
@_transparent
|
|
public init(from decoder: Decoder) throws {
|
|
let container = try decoder.singleValueContainer()
|
|
do {
|
|
self.native = try container.decode(NativeType.self)
|
|
} catch DecodingError.typeMismatch(let type, let context) {
|
|
// We may have encoded as a different type on a different platform. A
|
|
// strict fixed-format decoder may disallow a conversion, so let's try the
|
|
// other type.
|
|
do {
|
|
if NativeType.self == Float.self {
|
|
self.native = NativeType(try container.decode(Double.self))
|
|
} else {
|
|
self.native = NativeType(try container.decode(Float.self))
|
|
}
|
|
} catch {
|
|
// Failed to decode as the other type, too. This is neither a Float nor
|
|
// a Double. Throw the old error; we don't want to clobber the original
|
|
// info.
|
|
throw DecodingError.typeMismatch(type, context)
|
|
}
|
|
}
|
|
}
|
|
|
|
@_transparent
|
|
public func encode(to encoder: Encoder) throws {
|
|
var container = encoder.singleValueContainer()
|
|
try container.encode(self.native)
|
|
}
|
|
}
|