Attempt Swift 5.9 compatibility.

This commit is contained in:
2024-10-30 17:07:53 -05:00
parent 01c48650e9
commit 157b187116
4 changed files with 61 additions and 54 deletions

View File

@@ -1,5 +1,4 @@
{ {
"originHash" : "d50b9049eb671b1ad14bc8ba592c78735f9e357a6b59835343af6e20e8be4701",
"pins" : [ "pins" : [
{ {
"identity" : "swift-numerics", "identity" : "swift-numerics",
@@ -11,5 +10,5 @@
} }
} }
], ],
"version" : 3 "version" : 2
} }

View File

@@ -1,4 +1,4 @@
// swift-tools-version: 6.0 // swift-tools-version: 5.9
// The swift-tools-version declares the minimum version of Swift required to build this package. // The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription import PackageDescription
@@ -22,12 +22,12 @@ let package = Package(
.define("PFFFT_SCALVEC_ENABLED", to: "1"), .define("PFFFT_SCALVEC_ENABLED", to: "1"),
.define("_USE_MATH_DEFINES"), .define("_USE_MATH_DEFINES"),
.define("NDEBUG"), .define("NDEBUG"),
.unsafeFlags(["-O3"]),
] ]
), ),
.target( .target(
name: "PFFFT", name: "PFFFT",
dependencies: ["PFFFTLib", .product(name: "Numerics", package: "swift-numerics")] dependencies: ["PFFFTLib", .product(name: "Numerics", package: "swift-numerics")],
swiftSettings: [.enableExperimentalFeature("AccessLevelOnImport")]
), ),
.testTarget( .testTarget(
name: "PFFFTTests", name: "PFFFTTests",

View File

@@ -159,14 +159,20 @@ public struct FFT<T: FFTElement>: ~Copyable {
let ptr: OpaquePointer let ptr: OpaquePointer
let n: Int let n: Int
let work: Buffer<ScalarType>? let work: Buffer<ScalarType>
let setup: Setup let setup: Setup
public init(setup: Setup) { public init(setup: Setup) {
self.setup = setup self.setup = setup
ptr = setup.ptr ptr = setup.ptr
n = setup.n n = setup.n
work = n > 4096 ? Buffer<ScalarType>(capacity: T.self == ComplexType.self ? 2 * n : n) : nil
let workCapacity = if n > 4096 {
T.self == ComplexType.self ? 2 * n : n
} else {
0
}
work = Buffer(capacity: workCapacity)
} }
/// Initialize the FFT implementation with the given size and type. /// Initialize the FFT implementation with the given size and type.
@@ -202,10 +208,11 @@ public struct FFT<T: FFTElement>: ~Copyable {
} }
@inline(__always) @inline(__always)
func toAddress(_ work: borrowing Buffer<ScalarType>?) -> UnsafeMutablePointer<ScalarType>? { var workPtr: UnsafeMutablePointer<ScalarType>? {
switch work { if work.count > 0 {
case let .some(b): return b.baseAddress return work.baseAddress
case .none: return nil } else {
return nil
} }
} }
@@ -271,12 +278,12 @@ public struct FFT<T: FFTElement>: ~Copyable {
/// - sign: The direction of the FFT. /// - sign: The direction of the FFT.
public func forward(signal: borrowing Buffer<T>, spectrum: borrowing Buffer<ComplexType>) { public func forward(signal: borrowing Buffer<T>, spectrum: borrowing Buffer<ComplexType>) {
checkFftBufferCounts(signal: signal, spectrum: spectrum) checkFftBufferCounts(signal: signal, spectrum: spectrum)
ScalarType.pffftTransformOrdered(ptr, rebind(signal), rebind(spectrum), toAddress(work), .forward) ScalarType.pffftTransformOrdered(ptr, rebind(signal), rebind(spectrum), workPtr, .forward)
} }
public func inverse(spectrum: borrowing Buffer<ComplexType>, signal: borrowing Buffer<T>) { public func inverse(spectrum: borrowing Buffer<ComplexType>, signal: borrowing Buffer<T>) {
checkFftBufferCounts(signal: signal, spectrum: spectrum) checkFftBufferCounts(signal: signal, spectrum: spectrum)
ScalarType.pffftTransformOrdered(ptr, rebind(spectrum), rebind(signal), toAddress(work), .backward) ScalarType.pffftTransformOrdered(ptr, rebind(spectrum), rebind(signal), workPtr, .backward)
} }
/// Perform a forward FFT on the input buffer, with implementation defined order. /// Perform a forward FFT on the input buffer, with implementation defined order.
@@ -290,12 +297,12 @@ public struct FFT<T: FFTElement>: ~Copyable {
/// - sign: The direction of the FFT. /// - sign: The direction of the FFT.
public func forwardToInternalLayout(signal: borrowing Buffer<T>, spectrum: borrowing Buffer<ScalarType>) { public func forwardToInternalLayout(signal: borrowing Buffer<T>, spectrum: borrowing Buffer<ScalarType>) {
checkFftInternalLayoutBufferCounts(signal: signal, spectrum: spectrum) checkFftInternalLayoutBufferCounts(signal: signal, spectrum: spectrum)
ScalarType.pffftTransform(ptr, rebind(signal), spectrum.baseAddress, toAddress(work), .forward) ScalarType.pffftTransform(ptr, rebind(signal), spectrum.baseAddress, workPtr, .forward)
} }
public func inverseFromInternalLayout(spectrum: borrowing Buffer<ScalarType>, signal: borrowing Buffer<T>) { public func inverseFromInternalLayout(spectrum: borrowing Buffer<ScalarType>, signal: borrowing Buffer<T>) {
checkFftInternalLayoutBufferCounts(signal: signal, spectrum: spectrum) checkFftInternalLayoutBufferCounts(signal: signal, spectrum: spectrum)
ScalarType.pffftTransform(ptr, spectrum.baseAddress, rebind(signal), toAddress(work), .backward) ScalarType.pffftTransform(ptr, spectrum.baseAddress, rebind(signal), workPtr, .backward)
} }
public func reorder(spectrum: borrowing Buffer<ScalarType>, output: borrowing Buffer<ComplexType>) { public func reorder(spectrum: borrowing Buffer<ScalarType>, output: borrowing Buffer<ComplexType>) {

View File

@@ -1,50 +1,51 @@
import Testing
import ComplexModule import ComplexModule
@testable import PFFFT @testable import PFFFT
import XCTest
@Test func fftFloat() async throws { final class FFTTests: XCTestCase {
func testFftFloat() throws {
let fft = try FFT<Complex<Float>>(n: 16)
let signal = fft.makeSignalBuffer()
let spectrum = fft.makeSpectrumBuffer()
let fft = try FFT<Complex<Float>>(n: 16) signal.mapInPlace { i, v in
let signal = fft.makeSignalBuffer() v = Complex(Float(i) + 1.0, Float(i) - 2.0)
let spectrum = fft.makeSpectrumBuffer() }
signal.mutateEach { (i, v) in fft.forward(signal: signal, spectrum: spectrum)
v = Complex(Float(i) + 1.0, Float(i) - 2.0)
}
fft.forward(signal: signal, spectrum: spectrum) let result = spectrum.map { $0 }
let expected: [Complex<Float>] = [
.init(136.0, 88.0),
.init(-48.218716, 32.218716),
.init(-27.31371, 11.313708),
.init(-19.972847, 3.972846),
.init(-16.0, 0.0),
.init(-13.345428, -2.6545706),
.init(-11.313709, -4.6862917),
.init(-9.591298, -6.408703),
.init(-8.0, -8.0),
.init(-6.408703, -9.591298),
.init(-4.6862917, -11.313708),
.init(-2.6545706, -13.345429),
.init(0.0, -16.0),
.init(3.972845, -19.972847),
.init(11.313707, -27.31371),
.init(32.218716, -48.218716),
]
for (r, e) in zip(result, expected) {
XCTAssert(r.isApproximatelyEqual(to: e))
}
let result = spectrum.map { $0 } fft.inverse(spectrum: spectrum, signal: signal)
let expected: [Complex<Float>] = [
.init(136.0, 88.0),
.init(-48.218716, 32.218716),
.init(-27.31371, 11.313708),
.init(-19.972847, 3.972846),
.init(-16.0, 0.0),
.init(-13.345428, -2.6545706),
.init(-11.313709, -4.6862917),
.init(-9.591298, -6.408703),
.init(-8.0, -8.0),
.init(-6.408703, -9.591298),
.init(-4.6862917, -11.313708),
.init(-2.6545706, -13.345429),
.init(0.0, -16.0),
.init(3.972845, -19.972847),
.init(11.313707, -27.31371),
.init(32.218716, -48.218716),
]
zip(result, expected).forEach { r, e in
#expect(r.isApproximatelyEqual(to: e))
}
fft.inverse(spectrum: spectrum, signal: signal) let signalResult = signal.map { $0 }
let signalExpected = (0 ..< 16).map { i in
Complex(Float(i) + 1.0, Float(i) - 2.0) * 16
}
let signalResult = signal.map { $0 } for (r, e) in zip(signalResult, signalExpected) {
let signalExpected = (0..<16).map { i in XCTAssert(r.isApproximatelyEqual(to: e))
Complex(Float(i) + 1.0, Float(i) - 2.0) * 16 }
}
zip(signalResult, signalExpected).forEach { r, e in
#expect(r.isApproximatelyEqual(to: e))
} }
} }