Skip to content

Commit 5e5cd76

Browse files
committed
Work in progress towards "Mathsable"
Fundamental decision to be made; should implementation hooks present like `Float.exp(_ x: Float) -> Float` or like `Float.Maths.exp(_ x: Float) -> Float`? Having the intermediate namespace to group them as in the second is definitely nicer, but it requires a little bit of extra machinery, and much more importantly, there doesn't seem to be any way to make access to the static `Maths` associatedtype transparent.
1 parent 473f3d2 commit 5e5cd76

File tree

8 files changed

+232
-4
lines changed

8 files changed

+232
-4
lines changed

stdlib/public/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ if(SWIFT_BUILD_STDLIB)
6161
add_subdirectory(stubs)
6262
add_subdirectory(core)
6363
add_subdirectory(SwiftOnoneSupport)
64+
65+
add_subdirectory(Maths)
6466
endif()
6567

6668
if(SWIFT_BUILD_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR)

stdlib/public/Maths/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
add_swift_target_library(swiftMaths ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
2+
Maths.swift.gyb
3+
4+
SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
5+
SWIFT_COMPILE_FLAGS
6+
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
7+
)
8+

stdlib/public/Maths/Maths.swift.gyb

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===--- Maths.swift ------------------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
// MARK: - Free functions defined on FloatingPoint
14+
@_transparent
15+
public func ceil<T>(_ x: T) -> T where T: FloatingPoint {
16+
return x.rounded(.up)
17+
}
18+
19+
@_transparent
20+
public func floor<T>(_ x: T) -> T where T: FloatingPoint {
21+
return x.rounded(.down)
22+
}
23+
24+
@_transparent
25+
public func round<T: FloatingPoint>(_ x: T) -> T {
26+
return x.rounded()
27+
}
28+
29+
@_transparent
30+
public func trunc<T>(_ x: T) -> T where T: FloatingPoint {
31+
return x.rounded(.towardZero)
32+
}
33+
34+
@_transparent
35+
public func sqrt<T>(_ x: T) -> T where T: FloatingPoint {
36+
return x.squareRoot()
37+
}
38+
39+
@_transparent
40+
public func fma<T>(_ x: T, _ y: T, _ z: T) -> T where T: FloatingPoint {
41+
return z.addingProduct(x, y)
42+
}
43+
44+
@_transparent
45+
public func remainder<T>(_ x: T, _ y: T) -> T where T: FloatingPoint {
46+
return x.remainder(dividingBy: y)
47+
}
48+
49+
@_transparent
50+
public func fmod<T>(_ x: T, _ y: T) -> T where T: FloatingPoint {
51+
return x.truncatingRemainder(dividingBy: y)
52+
}
53+
54+
// MARK: - Free functions defined on Mathsable
55+
56+
%from SwiftMathsFunctions import *
57+
%for func in MathFunctions:
58+
59+
@_transparent
60+
public func ${func.free_decl()} {
61+
// return T.Maths.${func.name}(${func.params()})
62+
return T.${func.name}(${func.params()})
63+
}
64+
%end

stdlib/public/Platform/tgmath.swift.gyb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import SwiftShims
14+
@_exported import Maths
1415

1516
// Generic functions implementable directly on FloatingPoint.
1617
@_transparent
@@ -163,9 +164,6 @@ UnaryFunctions = [
163164
# We call this intrinsic via the Builtin method so keep this list in
164165
# sync with core/BuiltinMath.swift.gyb
165166
UnaryIntrinsicFunctions = [
166-
'cos', 'sin',
167-
'exp', 'exp2',
168-
'log', 'log10', 'log2',
169167
'nearbyint', 'rint',
170168
]
171169

stdlib/public/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ set(SWIFTLIB_ESSENTIAL
8787
LifetimeManager.swift
8888
ManagedBuffer.swift
8989
Map.swift
90+
Mathsable.swift.gyb
9091
MemoryLayout.swift
9192
UnicodeScalar.swift # ORDER DEPENDENCY: Must precede Mirrors.swift
9293
Misc.swift

stdlib/public/core/GroupInfo.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,8 @@
167167
"Floating": [
168168
"FloatingPoint.swift",
169169
"FloatingPointParsing.swift",
170-
"FloatingPointTypes.swift"],
170+
"FloatingPointTypes.swift",
171+
"Mathsable.swift"],
171172
"Vector": [
172173
"SIMDVector.swift",
173174
"SIMDVectorTypes.swift"]}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//===--- Mathsable.swift --------------------------------------*- swift -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
// We are omitting the following for now, which could also be defined on
14+
// FloatingPoint, as it's not obvious that we want free function
15+
// implementations:
16+
//
17+
// fabs - use Swift.abs instead.
18+
//
19+
// scalbn, frexp, ldexp, ilogb - we should provide a better technique
20+
// for safely rescaling floating-point computations instead of these
21+
// poorly named and easy to misuse functions.
22+
23+
%{
24+
from SwiftMathsFunctions import *
25+
}%
26+
27+
/* NAMESPACED
28+
public protocol Mathsable {
29+
associatedtype Maths: MathsImplementations where Maths.Value == Self
30+
}
31+
32+
public protocol MathsImplementations {
33+
associatedtype Value
34+
%for func in MathFunctions:
35+
static func ${func.decl("Value")}
36+
%end
37+
}
38+
39+
%for type in all_floating_point_types():
40+
extension ${type.stdlib_name}: Mathsable {
41+
public enum Maths: MathsImplementations {
42+
public typealias Value = ${type.stdlib_name}
43+
% for func in MathFunctions:
44+
45+
@_transparent
46+
public static func ${func.decl("Value")} {
47+
return ${func.impl(type)}
48+
}
49+
%end
50+
}
51+
}
52+
53+
%end
54+
55+
public struct _SIMDMaths<V>: MathsImplementations
56+
where V: SIMD, V.Scalar: Mathsable {
57+
58+
public typealias Value = V
59+
%for func in MathFunctions:
60+
61+
@_transparent
62+
public static func ${func.decl("V")} {
63+
var r = V()
64+
for i in x.indices {
65+
r[i] = V.Scalar.Maths.${func.name}(${func.params("", "[i]")})
66+
}
67+
return r
68+
}
69+
%end
70+
}
71+
72+
extension SIMD where Scalar: Mathsable {
73+
public typealias Maths = _SIMDMaths<Self>
74+
}
75+
76+
%for n in [2,3,4,8,16,32,64]:
77+
extension SIMD${n}: Mathsable where Scalar: Mathsable { }
78+
%end
79+
*/
80+
81+
/* NO NAMESPACE */
82+
public protocol Mathsable {
83+
%for func in MathFunctions:
84+
static func ${func.decl("Self")}
85+
%end
86+
}
87+
88+
%for type in all_floating_point_types():
89+
extension ${type.stdlib_name}: Mathsable {
90+
% for func in MathFunctions:
91+
92+
@_transparent
93+
public static func ${func.decl(type.stdlib_name)} {
94+
return ${func.impl(type)}
95+
}
96+
%end
97+
}
98+
99+
%end
100+
101+
extension SIMD where Scalar: Mathsable {
102+
%for func in MathFunctions:
103+
104+
@_transparent
105+
public static func ${func.decl("Self")} {
106+
var r = Self()
107+
for i in x.indices {
108+
r[i] = Scalar.${func.name}(${func.params("", "[i]")})
109+
}
110+
return r
111+
}
112+
%end
113+
}
114+
115+
%for n in [2,3,4,8,16,32,64]:
116+
extension SIMD${n}: Mathsable where Scalar: Mathsable { }
117+
%end

utils/SwiftMathsFunctions.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from SwiftFloatingPointTypes import all_floating_point_types
2+
3+
class SwiftMathsFunction(object):
4+
def __init__(self, name, cName=None, intrinsic=False, args="x"):
5+
self.name = name
6+
self.cName = cName if cName is not None else name
7+
self.intrinsic = intrinsic
8+
self.args = args
9+
10+
def params(self, prefix="", suffix=""):
11+
return ", ".join(
12+
map(lambda a: prefix + a + suffix, self.args)
13+
)
14+
15+
def decl(self, type):
16+
return self.name + "(" + self.params("_ ", ": " + type) + ") -> " + type
17+
18+
def free_decl(self):
19+
return self.name + "<T>(" + self.params("_ ", ": T") + ") -> T where T: Mathsable"
20+
21+
def impl(self, type):
22+
if self.intrinsic:
23+
builtin = "Builtin.int_" + self.name + "_FPIEEE" + str(type.bits)
24+
return type.stdlib_name + "(" + builtin + "(" + self.params("","._value") + "))"
25+
return self.cName + type.cFuncSuffix + "(" + self.params() + ")"
26+
27+
MathFunctions = [
28+
SwiftMathsFunction(name="cos", intrinsic=True),
29+
SwiftMathsFunction(name="sin", intrinsic=True),
30+
SwiftMathsFunction(name="exp", intrinsic=True),
31+
SwiftMathsFunction(name="exp2", intrinsic=True),
32+
SwiftMathsFunction(name="log", intrinsic=True),
33+
SwiftMathsFunction(name="log10", intrinsic=True),
34+
SwiftMathsFunction(name="log2", intrinsic=True),
35+
]
36+
37+

0 commit comments

Comments
 (0)