Skip to content

Commit 3811e3b

Browse files
Merge pull request #145 from stephentyrone/mulAdd-and-cosm1
Added mulAdd and cosMinusOne operations for Real.
2 parents fa16d7d + a0501be commit 3811e3b

File tree

6 files changed

+58
-0
lines changed

6 files changed

+58
-0
lines changed

Sources/RealModule/Double+Real.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,4 +218,9 @@ extension Double: Real {
218218
return libm_lgamma(x, &dontCare)
219219
}
220220
#endif
221+
222+
@_transparent
223+
public static func _mulAdd(_ a: Double, _ b: Double, _ c: Double) -> Double {
224+
_numerics_muladd(a, b, c)
225+
}
221226
}

Sources/RealModule/Float+Real.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,9 @@ extension Float: Real {
191191
return libm_lgammaf(x, &dontCare)
192192
}
193193
#endif
194+
195+
@_transparent
196+
public static func _mulAdd(_ a: Float, _ b: Float, _ c: Float) -> Float {
197+
_numerics_muladdf(a, b, c)
198+
}
194199
}

Sources/RealModule/Float16+Real.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,5 +172,10 @@ extension Float16: Real {
172172
Float16(.logGamma(Float(x)))
173173
}
174174
#endif
175+
176+
@_transparent
177+
public static func _mulAdd(_ a: Float16, _ b: Float16, _ c: Float16) -> Float16 {
178+
_numerics_muladdf16(a, b, c)
179+
}
175180
}
176181
#endif

Sources/RealModule/Real.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ extension Real {
4040
return pow(10, x)
4141
}
4242

43+
/// cos(x) - 1, computed in such a way as to maintain accuracy for small x.
44+
///
45+
/// See also:
46+
/// -
47+
/// - `ElementaryFunctions.expMinusOne()`
48+
@_transparent
49+
public static func cosMinusOne(_ x: Self) -> Self {
50+
let sinxOver2 = sin(x/2)
51+
return -2*sinxOver2*sinxOver2
52+
}
53+
4354
#if !os(Windows)
4455
public static func signGamma(_ x: Self) -> FloatingPointSign {
4556
// Gamma is strictly positive for x >= 0.
@@ -76,6 +87,11 @@ extension Real {
7687
}
7788
#endif
7889

90+
@_transparent
91+
public static func _mulAdd(_ a: Self, _ b: Self, _ c: Self) -> Self {
92+
a*b + c
93+
}
94+
7995
@_transparent
8096
public static func sqrt(_ x: Self) -> Self {
8197
return x.squareRoot()

Sources/RealModule/RealFunctions.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,9 @@ public protocol RealFunctions: ElementaryFunctions {
112112
/// - `logGamma()`
113113
static func signGamma(_ x: Self) -> FloatingPointSign
114114
#endif
115+
116+
/// a*b + c, computed _either_ with an FMA or with separate multiply and add.
117+
///
118+
/// Whichever is faster should be chosen by the compiler statically.
119+
static func _mulAdd(_ a: Self, _ b: Self, _ c: Self) -> Self
115120
}

Sources/_NumericsShims/include/_NumericsShims.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,28 @@ HEADER_SHIM long double libm_lgammal(long double x, int *signp) {
382382
}
383383
#endif
384384

385+
// MARK: - fast mul-add inlines
386+
/// a*b + c evaluated _either_ as two operations or fma, whichever is faster.
387+
HEADER_SHIM _Float16 _numerics_muladdf16(_Float16 a, _Float16 b, _Float16 c) {
388+
#pragma STDC FP_CONTRACT ON
389+
return a*b + c;
390+
}
391+
392+
/// a*b + c evaluated _either_ as two operations or fma, whichever is faster.
393+
HEADER_SHIM float _numerics_muladdf(float a, float b, float c) {
394+
#pragma STDC FP_CONTRACT ON
395+
return a*b + c;
396+
}
397+
398+
/// a*b + c evaluated _either_ as two operations or fma, whichever is faster.
399+
HEADER_SHIM double _numerics_muladd(double a, double b, double c) {
400+
#pragma STDC FP_CONTRACT ON
401+
return a*b + c;
402+
}
403+
404+
// No long-double muladd operation, because no one has built an FMA for it
405+
// (except for Itanium, which Swift doesn't support).
406+
385407
// MARK: - shims to import C complex operations for timing purposes
386408
// Clang doesn't provide complex arithmetic on Windows (because MSVC
387409
// doesn't), so we can't define these there, or we'll get link errors.

0 commit comments

Comments
 (0)