@@ -34,6 +34,7 @@ import SwiftShims
34
34
/// ElementaryFunctions and FloatingPoint.
35
35
///
36
36
/// [elfn]: http://en.wikipedia.org/wiki/Elementary_function
37
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * )
37
38
public protocol ElementaryFunctions {
38
39
39
40
% for func in ElementaryFunctions:
@@ -59,77 +60,12 @@ public protocol ElementaryFunctions {
59
60
static func root( _ x: Self , _ n: Int ) -> Self
60
61
}
61
62
62
- /// A type that models the real numbers.
63
- ///
64
- /// Conformance to this protocol means that all the FloatingPoint operations
65
- /// are available, as well as the ElementaryFunctions, plus the following
66
- /// additional math functions: atan2, erf, erc, hypot, tgamma.
67
- ///
68
- /// logGamma and signGamma are also available on non-Windows platforms.
69
- public protocol Real : ElementaryFunctions , FloatingPoint {
70
- % for func in RealFunctions:
71
-
72
- ${ func . comment}
73
- static func ${ func . decl( " Self " ) }
74
- % end
75
-
76
- /// `atan(y/x)` with quadrant fixup.
77
- ///
78
- /// There is an infinite family of angles whose tangent is `y/x`. `atan2`
79
- /// selects the representative that is the angle between the vector `(x, y)`
80
- /// and the real axis in the range [-π, π].
81
- static func atan2( y: Self , x: Self ) -> Self
82
-
83
- #if !os(Windows)
84
- // lgamma is not available on Windows.
85
- // TODO: provide an implementation of lgamma with the stdlib to support
86
- // Windows so we can vend a uniform interface.
87
-
88
- /// `log(gamma(x))` computed without undue overflow.
89
- ///
90
- /// `log(abs(gamma(x)))` is returned. To get the sign of `gamma(x)` cheaply,
91
- /// use `signGamma(x)`.
92
- static func logGamma( _ x: Self) -> Self
93
- #endif
94
- }
95
-
96
- extension Real {
97
- #if !os(Windows)
98
- // lgamma is not available on Windows; no lgamma means signGamma
99
- // is basically useless, so don't bother exposing it.
100
-
101
- /// The sign of `gamma(x)`.
102
- ///
103
- /// This function is typically used in conjunction with `logGamma(x)`, which
104
- /// computes `log(abs(gamma(x)))`, to recover the sign information that is
105
- /// lost to the absolute value.
106
- ///
107
- /// `gamma(x)` has a simple pole at each non-positive integer and an
108
- /// essential singularity at infinity; we arbitrarily choose to return
109
- /// `.plus` for the sign in those cases. For all other values, `signGamma(x)`
110
- /// is `.plus` if `x >= 0` or `trunc(x)` is odd, and `.minus` otherwise.
111
- @_alwaysEmitIntoClient
112
- public static func signGamma( _ x: Self ) -> FloatingPointSign {
113
- if x >= 0 { return . plus }
114
- let trunc = x. rounded ( . towardZero)
115
- // Treat poles as gamma(x) == +inf. This is arbitrary, but we need to
116
- // pick one sign or the other.
117
- if x == trunc { return . plus }
118
- // Result is .minus if trunc is even, .plus otherwise. To figure out if
119
- // trunc is even or odd, check if trunc/2 is an integer.
120
- let halfTrunc = trunc/ 2
121
- if halfTrunc == halfTrunc. rounded ( . towardZero) { return . minus }
122
- return . plus
123
- }
124
- #endif
125
- }
126
-
127
63
% for type in all_floating_point_types( ) :
128
64
% if type. bits == 80 :
129
65
#if (arch(i386) || arch(x86_64)) && !os(Windows)
130
66
% end
131
67
% Self = type. stdlib_name
132
- extension ${ Self} : Real {
68
+ extension ${ Self} : ElementaryFunctions {
133
69
% for func in ElementaryFunctions + RealFunctions:
134
70
135
71
@_alwaysEmitIntoClient
@@ -172,9 +108,66 @@ extension ${Self}: Real {
172
108
public static func logGamma( _ x: ${ Self} ) -> ${ Self} {
173
109
return _swift_stdlib_lgamma ${ type. cFuncSuffix} ( x)
174
110
}
111
+
112
+ @_alwaysEmitIntoClient
113
+ public static func signGamma( _ x: ${ Self} ) -> FloatingPointSign {
114
+ if x >= 0 { return . plus }
115
+ let trunc = x. rounded ( . towardZero)
116
+ if x == trunc { return . plus }
117
+ let halfTrunc = trunc/ 2
118
+ if halfTrunc == halfTrunc. rounded ( . towardZero) { return . minus }
119
+ return . plus
120
+ }
175
121
#endif
176
122
}
177
123
% if type. bits == 80 :
178
124
#endif
179
125
% end
180
126
% end
127
+
128
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * )
129
+ extension SIMD where Scalar: ElementaryFunctions {
130
+ % for func in ElementaryFunctions:
131
+
132
+ @_alwaysEmitIntoClient
133
+ public static func ${ func . decl( " Self " ) } {
134
+ var r = Self ( )
135
+ for i in r. indices {
136
+ r [ i] = Scalar . ${ func . swiftName} ( ${ func . params( suffix= " [i] " ) } )
137
+ }
138
+ return r
139
+ }
140
+ % end
141
+
142
+ @_alwaysEmitIntoClient
143
+ public static func pow( _ x: Self , _ y: Self ) -> Self {
144
+ var r = Self ( )
145
+ for i in r. indices {
146
+ r [ i] = Scalar . pow ( x [ i] , y [ i] )
147
+ }
148
+ return r
149
+ }
150
+
151
+ @_alwaysEmitIntoClient
152
+ public static func pow( _ x: Self , _ n: Int ) -> Self {
153
+ var r = Self ( )
154
+ for i in r. indices {
155
+ r [ i] = Scalar . pow ( x [ i] , n)
156
+ }
157
+ return r
158
+ }
159
+
160
+ @_alwaysEmitIntoClient
161
+ public static func root( _ x: Self , _ n: Int ) -> Self {
162
+ var r = Self ( )
163
+ for i in r. indices {
164
+ r [ i] = Scalar . root ( x [ i] , n)
165
+ }
166
+ return r
167
+ }
168
+ }
169
+
170
+ % for n in [ 2 , 3 , 4 , 8 , 16 , 32 , 64 ] :
171
+ @available ( macOS 9999 , iOS 9999 , tvOS 9999 , watchOS 9999 , * )
172
+ extension SIMD ${ n} : ElementaryFunctions where Scalar: ElementaryFunctions { }
173
+ % end
0 commit comments