我有以下代码,它使用Swift和Accelerate在斜坡上执行DFT
0 -> in (0.0000, 0.0000i) out (120.0000, 0.0000i)
1 -> in (1.0000, 0.0000i) out (-8.0000, 40.2187i)
2 -> in (2.0000, 0.0000i) out (-8.0000, 19.3137i)
3 -> in (3.0000, 0.0000i) out (-8.0000, 11.9728i)
4 -> in (4.0000, 0.0000i) out (-8.0000, 8.0000i)
5 -> in (5.0000, 0.0000i) out (-8.0000, 5.3454i)
6 -> in (6.0000, 0.0000i) out (-8.0000, 3.3137i)
7 -> in (7.0000, 0.0000i) out (-8.0000, 1.5913i)
8 -> in (8.0000, 0.0000i) out (-8.0000, 0.0000i)
9 -> in (9.0000, 0.0000i) out (-8.0000, -1.5913i)
10 -> in (10.0000, 0.0000i) out (-8.0000, -3.3137i)
11 -> in (11.0000, 0.0000i) out (-8.0000, -5.3454i)
12 -> in (12.0000, 0.0000i) out (-8.0000, -8.0000i)
13 -> in (13.0000, 0.0000i) out (-8.0000, -11.9728i)
14 -> in (14.0000, 0.0000i) out (-8.0000, -19.3137i)
15 -> in (15.0000, 0.0000i) out (-8.0000, -40.2187i)
输出
import Foundation
import Accelerate
let N = 16
let log2N = vDSP_Length(4)
var xdtar = UnsafeMutablePointer<Double>.allocate(capacity: N)
xdtar.initialize(to: 0.0, count: N )
var x = DSPDoubleSplitComplex(realp: xdtar, imagp: xdtar + N/2)
var ydtar = UnsafeMutablePointer<Double>.allocate(capacity: N/2)
var ydtai = UnsafeMutablePointer<Double>.allocate(capacity: N/2)
ydtar.initialize(to: 0.0, count: N )
ydtai.initialize(to: 0.0, count: N )
var y = DSPDoubleSplitComplex(realp: ydtar, imagp: ydtai)
for i in 0..<N {
xdtar[i] = Double(i)
}
let setup = vDSP_create_fftsetupD(log2N, Int32(2))
vDSP_fft_zropD(setup!, &x, vDSP_Stride(1), &y, vDSP_Stride(1), log2N, Int32(1))
vDSP_destroy_fftsetupD(setup)
for i in 0..<N/2 {
print(String(format: "%2d \t-> in \t(%5.4f, %5.4fi)\t out \t(%5.4f, %5.4fi)",
i, x.realp[i], x.imagp[i], ydtar[i], ydtai[i]))
}
xdtar.deinitialize(count: N); xdtar.deallocate(capacity: N)
ydtar.deinitialize(count: N/2); ydtar.deallocate(capacity: N/2)
ydtai.deinitialize(count: N/2); ydtai.deallocate(capacity: N/2)
我认为这是正确的。以上是复杂的复杂配方。基本上检查下面的代码是真实到复杂的FFT。
0 -> in (0.0000, 8.0000i) out (240.0000, -128.0000i)
1 -> in (1.0000, 9.0000i) out (-8.0000, 40.2187i)
2 -> in (2.0000, 10.0000i) out (-8.0000, 19.3137i)
3 -> in (3.0000, 11.0000i) out (-8.0000, 11.9728i)
4 -> in (4.0000, 12.0000i) out (-8.0000, 8.0000i)
5 -> in (5.0000, 13.0000i) out (-8.0000, 5.3454i)
6 -> in (6.0000, 14.0000i) out (-8.0000, 3.3137i)
7 -> in (7.0000, 15.0000i) out (-8.0000, 1.5913i)
它的输出是
=SUMPRODUCT(--(MOD(COLUMN(D2:O2)-COLUMN(D2),3)=0),D2:O2)
所以在我看来,入口零的打包输出应该是120,-8但不是。有人对这里发生了什么有任何建议吗?我正在探索这些功能,所以我很容易出错,但输出正确,我不理解打包的条目。
答案 0 :(得分:1)
基于非常草率的阅读,我看到两个可能的错误,这两个错误都在the documentation中讨论过。
具体来说,您的输入数据布局不正确(请参阅“实际FFT的数据打包”);所有偶数项应该在x的“实部”部分和“虚部”部分中的奇数项。解决之后,我得到:
0 -> in (0.0000, 1.0000i) out (240.0000, -16.0000i)
1 -> in (2.0000, 3.0000i) out (-16.0000, 80.4374i)
2 -> in (4.0000, 5.0000i) out (-16.0000, 38.6274i)
3 -> in (6.0000, 7.0000i) out (-16.0000, 23.9457i)
4 -> in (8.0000, 9.0000i) out (-16.0000, 16.0000i)
5 -> in (10.0000, 11.0000i) out (-16.0000, 10.6909i)
6 -> in (12.0000, 13.0000i) out (-16.0000, 6.6274i)
7 -> in (14.0000, 15.0000i) out (-16.0000, 3.1826i)
更好,但这只是两倍;如果我们看一下“Scaling for Fourier Transforms”,我们会看到这个注释:
为了提供最佳的执行速度,vDSP库的功能并不总是严格遵守傅立叶变换的教科书公式,因此必须进行相应的缩放。以下部分指定vDSP库实现的每种类型的傅里叶变换的缩放。缩放因子也在参考章节中的函数定义附带的公式中明确说明。
...
Real forward转换:RF_imp = RF_math * 2
这就是两个额外因素的来源。