From 737b9893da2a43e2903b865aa8116194e22ec57c Mon Sep 17 00:00:00 2001 From: Jaap Wijnen Date: Mon, 21 Jul 2025 16:26:32 +0200 Subject: [PATCH 1/2] add ElementaryFunctions conformance to SIMD types --- .../RealModule/SIMD+ElementaryFunctions.swift | 202 ++++++++++++++++++ Sources/RealModule/SIMD+RealFunctions.swift | 94 ++++++++ 2 files changed, 296 insertions(+) create mode 100644 Sources/RealModule/SIMD+ElementaryFunctions.swift create mode 100644 Sources/RealModule/SIMD+RealFunctions.swift diff --git a/Sources/RealModule/SIMD+ElementaryFunctions.swift b/Sources/RealModule/SIMD+ElementaryFunctions.swift new file mode 100644 index 00000000..8880ee47 --- /dev/null +++ b/Sources/RealModule/SIMD+ElementaryFunctions.swift @@ -0,0 +1,202 @@ +#if canImport(_Differentiation) +import _Differentiation +#endif + +#if !canImport(_Differentiation) +// add `AdditiveArithmetic` conformance since this is only present in the _Differentiation module which is not present everywhere +extension SIMD2: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} +extension SIMD4: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} +extension SIMD8: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} +extension SIMD16: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} +extension SIMD32: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} +extension SIMD64: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} +#endif + +extension SIMD where Scalar: ElementaryFunctions { + @_transparent + public static func exp(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .exp(x[i]) + } + return v + } + + @_transparent + public static func expMinusOne(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .expMinusOne(x[i]) + } + return v + } + + @_transparent + public static func cosh(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .cosh(x[i]) + } + return v + } + + @_transparent + public static func sinh(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .sinh(x[i]) + } + return v + } + + @_transparent + public static func tanh(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .tanh(x[i]) + } + return v + } + + @_transparent + public static func cos(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .cos(x[i]) + } + return v + } + + @_transparent + public static func sin(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .sin(x[i]) + } + return v + } + + @_transparent + public static func tan(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .tan(x[i]) + } + return v + } + + @_transparent + public static func log(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .log(x[i]) + } + return v + } + + @_transparent + public static func log(onePlus x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .log(onePlus: x[i]) + } + return v + } + + @_transparent + public static func acosh(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .acosh(x[i]) + } + return v + } + + @_transparent + public static func asinh(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .asinh(x[i]) + } + return v + } + + @_transparent + public static func atanh(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .atanh(x[i]) + } + return v + } + + @_transparent + public static func acos(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .acos(x[i]) + } + return v + } + + @_transparent + public static func asin(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .asin(x[i]) + } + return v + } + + @_transparent + public static func atan(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .atan(x[i]) + } + return v + } + + @_transparent + public static func pow(_ x: Self, _ n: Int) -> Self { + var v = Self() + for i in v.indices { + v[i] = .pow(x[i], n) + } + return v + } + + @_transparent + public static func pow(_ x: Self, _ y: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .pow(x[i], y[i]) + } + return v + } + + @_transparent + public static func sqrt(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .sqrt(x[i]) + } + return v + } + + @_transparent + public static func root(_ x: Self, _ n: Int) -> Self { + var v = Self() + for i in v.indices { + v[i] = .root(x[i], n) + } + return v + } +} + +extension SIMD2: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD4: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD8: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD16: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD32: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD64: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } diff --git a/Sources/RealModule/SIMD+RealFunctions.swift b/Sources/RealModule/SIMD+RealFunctions.swift new file mode 100644 index 00000000..5ac603fc --- /dev/null +++ b/Sources/RealModule/SIMD+RealFunctions.swift @@ -0,0 +1,94 @@ + +// Unfortunately we can't conform concrete simd types to `RealFunctions` as we can't implement a simd equivalent of +// `static func signGamma(_ x: Self) -> FloatingPointSign` +extension SIMD where Scalar: RealFunctions { + @_transparent + public static func atan2(y: Self, x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .atan2(y: y[i], x: x[i]) + } + return v + } + + @_transparent + public static func erf(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .erf(x[i]) + } + return v + } + + @_transparent + public static func erfc(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .erfc(x[i]) + } + return v + } + + @_transparent + public static func exp2(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .exp2(x[i]) + } + return v + } + + @_transparent + public static func exp10(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .exp10(x[i]) + } + return v + } + + @_transparent + public static func hypot(_ x: Self, _ y: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .hypot(x[i], y[i]) + } + return v + } + + @_transparent + public static func gamma(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .gamma(x[i]) + } + return v + } + + @_transparent + public static func log2(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .log2(x[i]) + } + return v + } + + @_transparent + public static func log10(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .log10(x[i]) + } + return v + } + + @_transparent + public static func logGamma(_ x: Self) -> Self { + var v = Self() + for i in v.indices { + v[i] = .logGamma(x[i]) + } + return v + } +} From b190f3683270fb33e7915358411093bd21db6441 Mon Sep 17 00:00:00 2001 From: Jaap Wijnen Date: Mon, 21 Jul 2025 16:54:12 +0200 Subject: [PATCH 2/2] remove use of _Differentiation based AdditiveArithmetic conformance --- .../RealModule/SIMD+ElementaryFunctions.swift | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/Sources/RealModule/SIMD+ElementaryFunctions.swift b/Sources/RealModule/SIMD+ElementaryFunctions.swift index 8880ee47..143939b7 100644 --- a/Sources/RealModule/SIMD+ElementaryFunctions.swift +++ b/Sources/RealModule/SIMD+ElementaryFunctions.swift @@ -1,16 +1,16 @@ -#if canImport(_Differentiation) -import _Differentiation -#endif - -#if !canImport(_Differentiation) -// add `AdditiveArithmetic` conformance since this is only present in the _Differentiation module which is not present everywhere extension SIMD2: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} extension SIMD4: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} extension SIMD8: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} extension SIMD16: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} extension SIMD32: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} extension SIMD64: @retroactive AdditiveArithmetic where Scalar: FloatingPoint {} -#endif + +extension SIMD2: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD4: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD8: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD16: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD32: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } +extension SIMD64: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } extension SIMD where Scalar: ElementaryFunctions { @_transparent @@ -193,10 +193,3 @@ extension SIMD where Scalar: ElementaryFunctions { return v } } - -extension SIMD2: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } -extension SIMD4: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } -extension SIMD8: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } -extension SIMD16: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } -extension SIMD32: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { } -extension SIMD64: ElementaryFunctions where Scalar: ElementaryFunctions & FloatingPoint { }