Skip to content

Commit 93e5499

Browse files
Merge pull request #214 from stephentyrone/rilakkuma
Initial pass at "relaxed" multiply and add operations.
2 parents 97c716b + 740cc50 commit 93e5499

17 files changed

+396
-30
lines changed

Package.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ let package = Package(
5353
.target(
5454
name: "_NumericsShims",
5555
exclude: excludedFilenames,
56-
linkerSettings: [.linkedLibrary("m", .when(platforms: [.linux, .android]))]
56+
linkerSettings: [
57+
.linkedLibrary("m", .when(platforms: [.linux, .android]))
58+
]
5759
),
5860

5961
.target(

Sources/ComplexModule/Complex+AlgebraicField.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,17 @@ extension Complex: AlgebraicField {
123123
}
124124
return nil
125125
}
126+
127+
@_transparent
128+
public static func _relaxedAdd(_ a: Self, _ b: Self) -> Self {
129+
Complex(Relaxed.sum(a.x, b.x), Relaxed.sum(a.y, b.y))
130+
}
131+
132+
@_transparent
133+
public static func _relaxedMul(_ a: Self, _ b: Self) -> Self {
134+
Complex(
135+
Relaxed.sum(Relaxed.product(a.x, b.x), -Relaxed.product(a.y, b.y)),
136+
Relaxed.sum(Relaxed.product(a.x, b.y), Relaxed.product(a.y, b.x))
137+
)
138+
}
126139
}

Sources/ComplexModule/Complex+ElementaryFunctions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ extension Complex: ElementaryFunctions {
119119
}
120120
// Special cases out of the way, evaluate as discussed above.
121121
return Complex(
122-
RealType._mulAdd(.cos(z.y), .expMinusOne(z.x), .cosMinusOne(z.y)),
122+
Relaxed.multiplyAdd(.cos(z.y), .expMinusOne(z.x), .cosMinusOne(z.y)),
123123
.exp(z.x) * .sin(z.y)
124124
)
125125
}
@@ -300,7 +300,7 @@ extension Complex: ElementaryFunctions {
300300
// We are not trying for sub-ulp accuracy, just a good relative error
301301
// bound, so for our purposes it suffices to have log u dominate the
302302
// result:
303-
if u >= 1 || u >= RealType._mulAdd(u,u,v*v) {
303+
if u >= 1 || u >= Relaxed.multiplyAdd(u, u, v*v) {
304304
let r = v / u
305305
return Complex(.log(u) + .log(onePlus: r*r)/2, θ)
306306
}

Sources/RealModule/AlgebraicField.swift

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ public protocol AlgebraicField: SignedNumeric {
8989
/// }
9090
/// ```
9191
var reciprocal: Self? { get }
92+
93+
/// a + b, with the optimizer licensed to reassociate and form FMAs.
94+
static func _relaxedAdd(_ a: Self, _ b: Self) -> Self
95+
96+
/// a * b, with the optimizer licensed to reassociate and form FMAs.
97+
static func _relaxedMul(_ a: Self, _ b: Self) -> Self
9298
}
9399

94100
extension AlgebraicField {
@@ -99,12 +105,27 @@ extension AlgebraicField {
99105
return result
100106
}
101107

102-
/// Implementations should be *conservative* with the reciprocal property;
103-
/// it is OK to return `nil` even in cases where a reciprocal could be
104-
/// represented. For this reason, a default implementation that simply
105-
/// always returns `nil` is correct, but conforming types should provide
106-
/// a better implementation if possible.
108+
// Implementations should be *conservative* with the reciprocal property;
109+
// it is OK to return `nil` even in cases where a reciprocal could be
110+
// represented. For this reason, a default implementation that simply
111+
// always returns `nil` is correct, but conforming types should provide
112+
// a better implementation if possible.
113+
@_transparent
107114
public var reciprocal: Self? {
108115
return nil
109116
}
117+
118+
// It's always OK to simply fall back on normal arithmetic, and for any
119+
// field with exact arithmetic, this is the correct definition.
120+
@_transparent
121+
public static func _relaxedAdd(_ a: Self, _ b: Self) -> Self {
122+
a + b
123+
}
124+
125+
// It's always OK to simply fall back on normal arithmetic, and for any
126+
// field with exact arithmetic, this is the correct definition.
127+
@_transparent
128+
public static func _relaxedMul(_ a: Self, _ b: Self) -> Self {
129+
a * b
130+
}
110131
}

Sources/RealModule/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ add_library(RealModule
1717
Float16+Real.swift
1818
Float80+Real.swift
1919
Real.swift
20-
RealFunctions.swift)
20+
RealFunctions.swift
21+
RelaxedArithmetic.swift)
2122
set_target_properties(RealModule PROPERTIES
2223
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
2324
target_link_libraries(RealModule PUBLIC

Sources/RealModule/Double+Real.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,12 @@ extension Double: Real {
221221
#endif
222222

223223
@_transparent
224-
public static func _mulAdd(_ a: Double, _ b: Double, _ c: Double) -> Double {
225-
_numerics_muladd(a, b, c)
224+
public static func _relaxedAdd(_ a: Double, _ b: Double) -> Double {
225+
_numerics_relaxed_add(a, b)
226+
}
227+
228+
@_transparent
229+
public static func _relaxedMul(_ a: Double, _ b: Double) -> Double {
230+
_numerics_relaxed_mul(a, b)
226231
}
227232
}

Sources/RealModule/Float+Real.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,12 @@ extension Float: Real {
194194
#endif
195195

196196
@_transparent
197-
public static func _mulAdd(_ a: Float, _ b: Float, _ c: Float) -> Float {
198-
_numerics_muladdf(a, b, c)
197+
public static func _relaxedAdd(_ a: Float, _ b: Float) -> Float {
198+
_numerics_relaxed_addf(a, b)
199+
}
200+
201+
@_transparent
202+
public static func _relaxedMul(_ a: Float, _ b: Float) -> Float {
203+
_numerics_relaxed_mulf(a, b)
199204
}
200205
}

Sources/RealModule/Float16+Real.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,20 @@ extension Float16: Real {
172172
Float16(.logGamma(Float(x)))
173173
}
174174
#endif
175+
176+
// TODO: once clang stabilizes the calling conventions for _Float16 on Intel,
177+
// we can re-enable these; presently the type is disabled on the target.
178+
#if !(arch(i386) || arch(x86_64))
179+
@_transparent
180+
public static func _relaxedAdd(_ a: Float16, _ b: Float16) -> Float16 {
181+
_numerics_relaxed_addf16(a, b)
182+
}
183+
184+
@_transparent
185+
public static func _relaxedMul(_ a: Float16, _ b: Float16) -> Float16 {
186+
_numerics_relaxed_mulf16(a, b)
187+
}
188+
#endif
175189
}
176190

177191
#endif

Sources/RealModule/Float80+Real.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,5 +165,15 @@ extension Float80: Real {
165165
var dontCare: Int32 = 0
166166
return libm_lgammal(x, &dontCare)
167167
}
168+
169+
@_transparent
170+
public static func _relaxedAdd(_ a: Float80, _ b: Float80) -> Float80 {
171+
_numerics_relaxed_addl(a, b)
172+
}
173+
174+
@_transparent
175+
public static func _relaxedMul(_ a: Float80, _ b: Float80) -> Float80 {
176+
_numerics_relaxed_mull(a, b)
177+
}
168178
}
169179
#endif

Sources/RealModule/RealFunctions.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,4 @@ public protocol RealFunctions: ElementaryFunctions {
7676
/// See also `gamma()` and `logGamma()`.
7777
static func signGamma(_ x: Self) -> FloatingPointSign
7878
#endif
79-
80-
/// a*b + c, computed _either_ with an FMA or with separate multiply and add.
81-
///
82-
/// Whichever is faster should be chosen by the compiler statically.
83-
static func _mulAdd(_ a: Self, _ b: Self, _ c: Self) -> Self
8479
}

0 commit comments

Comments
 (0)