blob: 5c8bba82326466861883001ee7fbc3ea3274fce5 [file] [log] [blame] [edit]
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: rdar50301438
// REQUIRES: objc_interop
// UNSUPPORTED: OS=watchos
import StdlibUnittest
import Accelerate
var Accelerate_vDSPFourierTransformTests = TestSuite("Accelerate_vDSPFourierTransform")
//===----------------------------------------------------------------------===//
//
// vDSP discrete Fourier transform tests; single-precision
//
//===----------------------------------------------------------------------===//
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
let n = 2048
let tau: Float = .pi * 2
let frequencies: [Float] = [1, 5, 25, 30, 75, 100,
300, 500, 512, 1023]
let inputReal: [Float] = (0 ..< n).map { index in
frequencies.reduce(0) { accumulator, frequency in
let normalizedIndex = Float(index) / Float(n)
return accumulator + sin(normalizedIndex * frequency * tau)
}
}
let inputImag: [Float] = (0 ..< n).map { index in
frequencies.reduce(0) { accumulator, frequency in
let normalizedIndex = Float(index) / Float(n)
return accumulator + sin(normalizedIndex * 1/frequency * tau)
}
}
Accelerate_vDSPFourierTransformTests.test("vDSP/SinglePrecisionForwardComplexComplex") {
let fwdDFT = vDSP.DFT(count: n,
direction: .forward,
transformType: .complexComplex,
ofType: Float.self)!
var outputReal = [Float](repeating: 0, count: n)
var outputImag = [Float](repeating: 0, count: n)
fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag,
outputReal: &outputReal,
outputImaginary: &outputImag)
// legacy...
let legacySetup = vDSP_DFT_zop_CreateSetup(nil,
vDSP_Length(n),
.FORWARD)!
var legacyOutputReal = [Float](repeating: -1, count: n)
var legacyOutputImag = [Float](repeating: -1, count: n)
vDSP_DFT_Execute(legacySetup,
inputReal,
inputImag,
&legacyOutputReal,
&legacyOutputImag)
expectTrue(outputReal.elementsEqual(legacyOutputReal))
expectTrue(outputImag.elementsEqual(legacyOutputImag))
let returnedResult = fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag)
expectTrue(outputReal.elementsEqual(returnedResult.real))
expectTrue(outputImag.elementsEqual(returnedResult.imaginary))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/SinglePrecisionInverseComplexComplex") {
let fwdDFT = vDSP.DFT(count: n,
direction: .inverse,
transformType: .complexComplex,
ofType: Float.self)!
var outputReal = [Float](repeating: 0, count: n)
var outputImag = [Float](repeating: 0, count: n)
fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag,
outputReal: &outputReal,
outputImaginary: &outputImag)
// legacy...
let legacySetup = vDSP_DFT_zop_CreateSetup(nil,
vDSP_Length(n),
.INVERSE)!
var legacyOutputReal = [Float](repeating: -1, count: n)
var legacyOutputImag = [Float](repeating: -1, count: n)
vDSP_DFT_Execute(legacySetup,
inputReal,
inputImag,
&legacyOutputReal,
&legacyOutputImag)
expectTrue(outputReal.elementsEqual(legacyOutputReal))
expectTrue(outputImag.elementsEqual(legacyOutputImag))
let returnedResult = fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag)
expectTrue(outputReal.elementsEqual(returnedResult.real))
expectTrue(outputImag.elementsEqual(returnedResult.imaginary))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/SinglePrecisionForwardComplexReal") {
let fwdDFT = vDSP.DFT(count: n,
direction: .forward,
transformType: .complexReal,
ofType: Float.self)!
var outputReal = [Float](repeating: 0, count: n / 2)
var outputImag = [Float](repeating: 0, count: n / 2)
fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag,
outputReal: &outputReal,
outputImaginary: &outputImag)
// legacy...
let legacySetup = vDSP_DFT_zrop_CreateSetup(nil,
vDSP_Length(n),
.FORWARD)!
var legacyOutputReal = [Float](repeating: -1, count: n / 2)
var legacyOutputImag = [Float](repeating: -1, count: n / 2)
vDSP_DFT_Execute(legacySetup,
inputReal,
inputImag,
&legacyOutputReal,
&legacyOutputImag)
expectTrue(outputReal.elementsEqual(legacyOutputReal))
expectTrue(outputImag.elementsEqual(legacyOutputImag))
let returnedResult = fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag)
expectTrue(outputReal.elementsEqual(returnedResult.real))
expectTrue(outputImag.elementsEqual(returnedResult.imaginary))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/SinglePrecisionInverseComplexReal") {
let fwdDFT = vDSP.DFT(count: n,
direction: .inverse,
transformType: .complexReal,
ofType: Float.self)!
var outputReal = [Float](repeating: 0, count: n / 2)
var outputImag = [Float](repeating: 0, count: n / 2)
fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag,
outputReal: &outputReal,
outputImaginary: &outputImag)
// legacy...
let legacySetup = vDSP_DFT_zrop_CreateSetup(nil,
vDSP_Length(n),
.INVERSE)!
var legacyOutputReal = [Float](repeating: -1, count: n / 2)
var legacyOutputImag = [Float](repeating: -1, count: n / 2)
vDSP_DFT_Execute(legacySetup,
inputReal,
inputImag,
&legacyOutputReal,
&legacyOutputImag)
expectTrue(outputReal.elementsEqual(legacyOutputReal))
expectTrue(outputImag.elementsEqual(legacyOutputImag))
let returnedResult = fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag)
expectTrue(outputReal.elementsEqual(returnedResult.real))
expectTrue(outputImag.elementsEqual(returnedResult.imaginary))
}
}
//===----------------------------------------------------------------------===//
//
// vDSP discrete Fourier transform tests; double-precision
//
//===----------------------------------------------------------------------===//
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
let n = 2048
let tau: Double = .pi * 2
let frequencies: [Double] = [1, 5, 25, 30, 75, 100,
300, 500, 512, 1023]
let inputReal: [Double] = (0 ..< n).map { index in
frequencies.reduce(0) { accumulator, frequency in
let normalizedIndex = Double(index) / Double(n)
return accumulator + sin(normalizedIndex * frequency * tau)
}
}
let inputImag: [Double] = (0 ..< n).map { index in
frequencies.reduce(0) { accumulator, frequency in
let normalizedIndex = Double(index) / Double(n)
return accumulator + sin(normalizedIndex * 1/frequency * tau)
}
}
Accelerate_vDSPFourierTransformTests.test("vDSP/DoublePrecisionForwardComplexComplex") {
let fwdDFT = vDSP.DFT(count: n,
direction: .forward,
transformType: .complexComplex,
ofType: Double.self)!
var outputReal = [Double](repeating: 0, count: n)
var outputImag = [Double](repeating: 0, count: n)
fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag,
outputReal: &outputReal,
outputImaginary: &outputImag)
// legacy...
let legacySetup = vDSP_DFT_zop_CreateSetupD(nil,
vDSP_Length(n),
.FORWARD)!
var legacyOutputReal = [Double](repeating: -1, count: n)
var legacyOutputImag = [Double](repeating: -1, count: n)
vDSP_DFT_ExecuteD(legacySetup,
inputReal,
inputImag,
&legacyOutputReal,
&legacyOutputImag)
expectTrue(outputReal.elementsEqual(legacyOutputReal))
expectTrue(outputImag.elementsEqual(legacyOutputImag))
let returnedResult = fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag)
expectTrue(outputReal.elementsEqual(returnedResult.real))
expectTrue(outputImag.elementsEqual(returnedResult.imaginary))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/DoublePrecisionInverseComplexComplex") {
let fwdDFT = vDSP.DFT(count: n,
direction: .inverse,
transformType: .complexComplex,
ofType: Double.self)!
var outputReal = [Double](repeating: 0, count: n)
var outputImag = [Double](repeating: 0, count: n)
fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag,
outputReal: &outputReal,
outputImaginary: &outputImag)
// legacy...
let legacySetup = vDSP_DFT_zop_CreateSetupD(nil,
vDSP_Length(n),
.INVERSE)!
var legacyOutputReal = [Double](repeating: -1, count: n)
var legacyOutputImag = [Double](repeating: -1, count: n)
vDSP_DFT_ExecuteD(legacySetup,
inputReal,
inputImag,
&legacyOutputReal,
&legacyOutputImag)
expectTrue(outputReal.elementsEqual(legacyOutputReal))
expectTrue(outputImag.elementsEqual(legacyOutputImag))
let returnedResult = fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag)
expectTrue(outputReal.elementsEqual(returnedResult.real))
expectTrue(outputImag.elementsEqual(returnedResult.imaginary))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/DoublePrecisionForwardComplexReal") {
let fwdDFT = vDSP.DFT(count: n,
direction: .forward,
transformType: .complexReal,
ofType: Double.self)!
var outputReal = [Double](repeating: 0, count: n / 2)
var outputImag = [Double](repeating: 0, count: n / 2)
fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag,
outputReal: &outputReal,
outputImaginary: &outputImag)
// legacy...
let legacySetup = vDSP_DFT_zrop_CreateSetupD(nil,
vDSP_Length(n),
.FORWARD)!
var legacyOutputReal = [Double](repeating: -1, count: n / 2)
var legacyOutputImag = [Double](repeating: -1, count: n / 2)
vDSP_DFT_ExecuteD(legacySetup,
inputReal,
inputImag,
&legacyOutputReal,
&legacyOutputImag)
expectTrue(outputReal.elementsEqual(legacyOutputReal))
expectTrue(outputImag.elementsEqual(legacyOutputImag))
let returnedResult = fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag)
expectTrue(outputReal.elementsEqual(returnedResult.real))
expectTrue(outputImag.elementsEqual(returnedResult.imaginary))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/DoublePrecisionInverseComplexReal") {
let fwdDFT = vDSP.DFT(count: n,
direction: .inverse,
transformType: .complexReal,
ofType: Double.self)!
var outputReal = [Double](repeating: 0, count: n / 2)
var outputImag = [Double](repeating: 0, count: n / 2)
fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag,
outputReal: &outputReal,
outputImaginary: &outputImag)
// legacy...
let legacySetup = vDSP_DFT_zrop_CreateSetupD(nil,
vDSP_Length(n),
.INVERSE)!
var legacyOutputReal = [Double](repeating: -1, count: n / 2)
var legacyOutputImag = [Double](repeating: -1, count: n / 2)
vDSP_DFT_ExecuteD(legacySetup,
inputReal,
inputImag,
&legacyOutputReal,
&legacyOutputImag)
expectTrue(outputReal.elementsEqual(legacyOutputReal))
expectTrue(outputImag.elementsEqual(legacyOutputImag))
let returnedResult = fwdDFT.transform(inputReal: inputReal,
inputImaginary: inputImag)
expectTrue(outputReal.elementsEqual(returnedResult.real))
expectTrue(outputImag.elementsEqual(returnedResult.imaginary))
}
}
//===----------------------------------------------------------------------===//
//
// vDSP Fast Fourier Transform Tests
//
//===----------------------------------------------------------------------===//
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
Accelerate_vDSPFourierTransformTests.test("vDSP/SinglePrecisionComplexConversions") {
func convert(splitComplexVector: DSPSplitComplex,
toInterleavedComplexVector interleavedComplexVector: inout [DSPComplex]) {
withUnsafePointer(to: splitComplexVector) {
vDSP_ztoc($0, 1,
&interleavedComplexVector, 2,
vDSP_Length(interleavedComplexVector.count))
}
}
func convert(interleavedComplexVector: [DSPComplex],
toSplitComplexVector splitComplexVector: inout DSPSplitComplex) {
vDSP_ctoz(interleavedComplexVector, 2,
&splitComplexVector, 1,
vDSP_Length(interleavedComplexVector.count))
}
var realSrc: [Float] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var imagSrc: [Float] = realSrc.reversed()
let splitSrc = DSPSplitComplex(realp: &realSrc,
imagp: &imagSrc)
var interleavedDest = [DSPComplex](repeating: DSPComplex(),
count: realSrc.count)
convert(splitComplexVector: splitSrc,
toInterleavedComplexVector: &interleavedDest)
var realDest = [Float](repeating: .nan, count: realSrc.count)
var imagDest = [Float](repeating: .nan, count: realSrc.count)
var splitDest = DSPSplitComplex(realp: &realDest,
imagp: &imagDest)
convert(interleavedComplexVector: interleavedDest,
toSplitComplexVector: &splitDest)
expectTrue(realSrc.elementsEqual(realDest))
expectTrue(imagSrc.elementsEqual(imagDest))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/DoublePrecisionComplexConversions") {
func convert(splitComplexVector: DSPDoubleSplitComplex,
toInterleavedComplexVector interleavedComplexVector: inout [DSPDoubleComplex]) {
withUnsafePointer(to: splitComplexVector) {
vDSP_ztocD($0, 1,
&interleavedComplexVector, 2,
vDSP_Length(interleavedComplexVector.count))
}
}
func convert(interleavedComplexVector: [DSPDoubleComplex],
toSplitComplexVector splitComplexVector: inout DSPDoubleSplitComplex) {
vDSP_ctozD(interleavedComplexVector, 2,
&splitComplexVector, 1,
vDSP_Length(interleavedComplexVector.count))
}
var realSrc: [Double] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var imagSrc: [Double] = realSrc.reversed()
let splitSrc = DSPDoubleSplitComplex(realp: &realSrc,
imagp: &imagSrc)
var interleavedDest = [DSPDoubleComplex](repeating: DSPDoubleComplex(),
count: realSrc.count)
convert(splitComplexVector: splitSrc,
toInterleavedComplexVector: &interleavedDest)
var realDest = [Double](repeating: .nan, count: realSrc.count)
var imagDest = [Double](repeating: .nan, count: realSrc.count)
var splitDest = DSPDoubleSplitComplex(realp: &realDest,
imagp: &imagDest)
convert(interleavedComplexVector: interleavedDest,
toSplitComplexVector: &splitDest)
expectTrue(realSrc.elementsEqual(realDest))
expectTrue(imagSrc.elementsEqual(imagDest))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/2DSinglePrecision") {
let width = 256
let height = 256
let pixelCount = width * height
let n = pixelCount / 2
let pixels: [Float] = (0 ..< pixelCount).map { i in
return abs(sin(Float(i) * 0.001 * 2))
}
var sourceImageReal = [Float](repeating: 0, count: n)
var sourceImageImaginary = [Float](repeating: 0, count: n)
var sourceImage = DSPSplitComplex(fromInputArray: pixels,
realParts: &sourceImageReal,
imaginaryParts: &sourceImageImaginary)
let pixelsRecreated = [Float](fromSplitComplex: sourceImage,
scale: 1, count: pixelCount)
expectTrue(pixelsRecreated.elementsEqual(pixels))
// Create FFT2D object
let fft2D = vDSP.FFT2D(width: 256,
height: 256,
ofType: DSPSplitComplex.self)!
// New style transform
var transformedImageReal = [Float](repeating: 0,
count: n)
var transformedImageImaginary = [Float](repeating: 0,
count: n)
var transformedImage = DSPSplitComplex(
realp: &transformedImageReal,
imagp: &transformedImageImaginary)
fft2D.transform(input: sourceImage,
output: &transformedImage,
direction: .forward)
// Legacy 2D FFT
let log2n = vDSP_Length(log2(Float(width * height)))
let legacySetup = vDSP_create_fftsetup(
log2n,
FFTRadix(kFFTRadix2))!
var legacyTransformedImageReal = [Float](repeating: -1,
count: n)
var legacyTransformedImageImaginary = [Float](repeating: -1,
count: n)
var legacyTransformedImage = DSPSplitComplex(
realp: &legacyTransformedImageReal,
imagp: &legacyTransformedImageImaginary)
vDSP_fft2d_zrop(legacySetup,
&sourceImage, 1, 0,
&legacyTransformedImage, 1, 0,
vDSP_Length(log2(Float(width))),
vDSP_Length(log2(Float(height))),
FFTDirection(kFFTDirection_Forward))
expectTrue(transformedImageReal.elementsEqual(legacyTransformedImageReal))
expectTrue(transformedImageImaginary.elementsEqual(legacyTransformedImageImaginary))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/2DDoublePrecision") {
let width = 256
let height = 256
let pixelCount = width * height
let n = pixelCount / 2
let pixels: [Double] = (0 ..< pixelCount).map { i in
return abs(sin(Double(i) * 0.001 * 2))
}
var sourceImageReal = [Double](repeating: 0, count: n)
var sourceImageImaginary = [Double](repeating: 0, count: n)
var sourceImage = DSPDoubleSplitComplex(fromInputArray: pixels,
realParts: &sourceImageReal,
imaginaryParts: &sourceImageImaginary)
let pixelsRecreated = [Double](fromSplitComplex: sourceImage,
scale: 1, count: pixelCount)
expectTrue(pixelsRecreated.elementsEqual(pixels))
// Create FFT2D object
let fft2D = vDSP.FFT2D(width: width,
height: height,
ofType: DSPDoubleSplitComplex.self)!
// New style transform
var transformedImageReal = [Double](repeating: 0,
count: n)
var transformedImageImaginary = [Double](repeating: 0,
count: n)
var transformedImage = DSPDoubleSplitComplex(
realp: &transformedImageReal,
imagp: &transformedImageImaginary)
fft2D.transform(input: sourceImage,
output: &transformedImage,
direction: .forward)
// Legacy 2D FFT
let log2n = vDSP_Length(log2(Float(width * height)))
let legacySetup = vDSP_create_fftsetupD(
log2n,
FFTRadix(kFFTRadix2))!
var legacyTransformedImageReal = [Double](repeating: -1,
count: n)
var legacyTransformedImageImaginary = [Double](repeating: -1,
count: n)
var legacyTransformedImage = DSPDoubleSplitComplex(
realp: &legacyTransformedImageReal,
imagp: &legacyTransformedImageImaginary)
vDSP_fft2d_zropD(legacySetup,
&sourceImage, 1, 0,
&legacyTransformedImage, 1, 0,
vDSP_Length(log2(Float(width))),
vDSP_Length(log2(Float(height))),
FFTDirection(kFFTDirection_Forward))
expectTrue(transformedImageReal.elementsEqual(legacyTransformedImageReal))
expectTrue(transformedImageImaginary.elementsEqual(legacyTransformedImageImaginary))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/1DSinglePrecision") {
let n = vDSP_Length(2048)
let frequencies: [Float] = [1, 5, 25, 30, 75, 100,
300, 500, 512, 1023]
let tau: Float = .pi * 2
let signal: [Float] = (0 ... n).map { index in
frequencies.reduce(0) { accumulator, frequency in
let normalizedIndex = Float(index) / Float(n)
return accumulator + sin(normalizedIndex * frequency * tau)
}
}
let halfN = Int(n / 2)
var forwardInputReal = [Float](repeating: 0, count: halfN)
var forwardInputImag = [Float](repeating: 0, count: halfN)
var forwardInput = DSPSplitComplex(fromInputArray: signal,
realParts: &forwardInputReal,
imaginaryParts: &forwardInputImag)
let log2n = vDSP_Length(log2(Float(n)))
// New API
guard let fft = vDSP.FFT(log2n: log2n,
radix: .radix2,
ofType: DSPSplitComplex.self) else {
fatalError("Can't create FFT.")
}
var outputReal = [Float](repeating: 0, count: halfN)
var outputImag = [Float](repeating: 0, count: halfN)
var forwardOutput = DSPSplitComplex(realp: &outputReal,
imagp: &outputImag)
fft.transform(input: forwardInput,
output: &forwardOutput,
direction: .forward)
// Legacy Style
let legacySetup = vDSP_create_fftsetup(log2n,
FFTRadix(kFFTRadix2))!
var legacyoutputReal = [Float](repeating: -1, count: halfN)
var legacyoutputImag = [Float](repeating: -1, count: halfN)
var legacyForwardOutput = DSPSplitComplex(realp: &legacyoutputReal,
imagp: &legacyoutputImag)
vDSP_fft_zrop(legacySetup,
&forwardInput, 1,
&legacyForwardOutput, 1,
log2n,
FFTDirection(kFFTDirection_Forward))
expectTrue(outputReal.elementsEqual(legacyoutputReal))
expectTrue(outputImag.elementsEqual(legacyoutputImag))
}
Accelerate_vDSPFourierTransformTests.test("vDSP/1DDoublePrecision") {
let n = vDSP_Length(2048)
let frequencies: [Double] = [1, 5, 25, 30, 75, 100,
300, 500, 512, 1023]
let tau: Double = .pi * 2
let signal: [Double] = (0 ... n).map { index in
frequencies.reduce(0) { accumulator, frequency in
let normalizedIndex = Double(index) / Double(n)
return accumulator + sin(normalizedIndex * frequency * tau)
}
}
let halfN = Int(n / 2)
var forwardInputReal = [Double](repeating: 0, count: halfN)
var forwardInputImag = [Double](repeating: 0, count: halfN)
var forwardInput = DSPDoubleSplitComplex(fromInputArray: signal,
realParts: &forwardInputReal,
imaginaryParts: &forwardInputImag)
let log2n = vDSP_Length(log2(Double(n)))
// New API
guard let fft = vDSP.FFT(log2n: log2n,
radix: .radix2,
ofType: DSPDoubleSplitComplex.self) else {
fatalError("Can't create FFT.")
}
var outputReal = [Double](repeating: 0, count: halfN)
var outputImag = [Double](repeating: 0, count: halfN)
var forwardOutput = DSPDoubleSplitComplex(realp: &outputReal,
imagp: &outputImag)
fft.transform(input: forwardInput,
output: &forwardOutput,
direction: .forward)
// Legacy Style
let legacySetup = vDSP_create_fftsetupD(log2n,
FFTRadix(kFFTRadix2))!
var legacyoutputReal = [Double](repeating: 0, count: halfN)
var legacyoutputImag = [Double](repeating: 0, count: halfN)
var legacyForwardOutput = DSPDoubleSplitComplex(realp: &legacyoutputReal,
imagp: &legacyoutputImag)
vDSP_fft_zropD(legacySetup,
&forwardInput, 1,
&legacyForwardOutput, 1,
log2n,
FFTDirection(kFFTDirection_Forward))
expectTrue(outputReal.elementsEqual(legacyoutputReal))
expectTrue(outputImag.elementsEqual(legacyoutputImag))
}
}
runAllTests()