//===--- MathFunctions.swift ----------------------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2019 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 // //===----------------------------------------------------------------------===// import SwiftShims %from SwiftMathFunctions import * %from SwiftFloatingPointTypes import all_floating_point_types /// A type that has elementary functions available. /// /// An ["elementary function"][elfn] is a function built up from powers, roots, /// exponentials, logarithms, trigonometric functions (sin, cos, tan) and /// their inverses, and the hyperbolic functions (sinh, cosh, tanh) and their /// inverses. /// /// Conformance to this protocol means that all of these building blocks are /// available as static functions on the type. /// /// ```swift /// let x: Float = 1 /// let y = Float.sin(x) // 0.84147096 /// ``` /// /// Additional operations, such as `atan2(y:x:)`, `hypot(_:_:)` and some /// special functions, are provided on the Real protocol, which refines both /// ElementaryFunctions and FloatingPoint. /// /// [elfn]: http://en.wikipedia.org/wiki/Elementary_function @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) public protocol ElementaryFunctions { %for func in ElementaryFunctions: ${func.comment} static func ${func.decl("Self")} %end /// `exp(y log(x))` computed without loss of intermediate precision. /// /// For real types, if `x` is negative the result is NaN, even if `y` has /// an integral value. For complex types, there is a branch cut on the /// negative real axis. static func pow(_ x: Self, _ y: Self) -> Self /// `x` raised to the `n`th power. static func pow(_ x: Self, _ n: Int) -> Self /// The `n`th root of `x`. /// /// For real types, if `x` is negative and `n` is even, the result is NaN. /// For complex types, there is a branch cut along the negative real axis. static func root(_ x: Self, _ n: Int) -> Self } %for type in all_floating_point_types(): % if type.bits == 80: #if (arch(i386) || arch(x86_64)) && !os(Windows) % end % Self = type.stdlib_name extension ${Self}: ElementaryFunctions { % for func in ElementaryFunctions + RealFunctions: @_alwaysEmitIntoClient public static func ${func.decl(Self)} { return ${func.impl(type)} } % end @_alwaysEmitIntoClient public static func pow(_ x: ${Self}, _ y: ${Self}) -> ${Self} { guard x >= 0 else { return .nan } return ${Self}(Builtin.int_pow_FPIEEE${type.bits}(x._value, y._value)) } @_alwaysEmitIntoClient public static func pow(_ x: ${Self}, _ n: Int) -> ${Self} { // TODO: this implementation isn't quite right for n so large that // the conversion to `${Self}` rounds. We could also consider using // a multiply-chain implementation for small `n`; this would be faster // for static `n`, but less accurate on platforms with a good `pow` // implementation. return ${Self}(Builtin.int_pow_FPIEEE${type.bits}(x._value, ${Self}(n)._value)) } @_alwaysEmitIntoClient public static func root(_ x: ${Self}, _ n: Int) -> ${Self} { guard x >= 0 || n % 2 != 0 else { return .nan } // TODO: this implementation isn't quite right for n so large that // the conversion to `${Self}` rounds. return ${Self}(signOf: x, magnitudeOf: pow(x, 1/${Self}(n))) } @_alwaysEmitIntoClient public static func atan2(y: ${Self}, x: ${Self}) -> ${Self} { return _swift_stdlib_atan2${type.cFuncSuffix}(y, x) } #if !os(Windows) @_alwaysEmitIntoClient public static func logGamma(_ x: ${Self}) -> ${Self} { return _swift_stdlib_lgamma${type.cFuncSuffix}(x) } @_alwaysEmitIntoClient public static func signGamma(_ x: ${Self}) -> FloatingPointSign { if x >= 0 { return .plus } let trunc = x.rounded(.towardZero) if x == trunc { return .plus } let halfTrunc = trunc/2 if halfTrunc == halfTrunc.rounded(.towardZero) { return .minus } return .plus } #endif } % if type.bits == 80: #endif % end %end @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) extension SIMD where Scalar: ElementaryFunctions { % for func in ElementaryFunctions: @_alwaysEmitIntoClient public static func ${func.decl("Self")} { var r = Self() for i in r.indices { r[i] = Scalar.${func.swiftName}(${func.params(suffix="[i]")}) } return r } % end @_alwaysEmitIntoClient public static func pow(_ x: Self, _ y: Self) -> Self { var r = Self() for i in r.indices { r[i] = Scalar.pow(x[i], y[i]) } return r } @_alwaysEmitIntoClient public static func pow(_ x: Self, _ n: Int) -> Self { var r = Self() for i in r.indices { r[i] = Scalar.pow(x[i], n) } return r } @_alwaysEmitIntoClient public static func root(_ x: Self, _ n: Int) -> Self { var r = Self() for i in r.indices { r[i] = Scalar.root(x[i], n) } return r } } %for n in [2,3,4,8,16,32,64]: @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *) extension SIMD${n}: ElementaryFunctions where Scalar: ElementaryFunctions { } %end