Discrete Fourier transform: Difference between revisions
(Draft task and possible temporary problems with server used to handle LaTeX and/or proofreading issues) |
(julia example) |
||
Line 17: | Line 17: | ||
The inverse transform is given by: |
The inverse transform is given by: |
||
<math>x_n = \sum_{k=0}^{N-1} X_k\cdot e^{i \frac{2 \pi}{N} k n}</math> |
<math>x_n = \sum_{k=0}^{N-1} X_k\cdot e^{i \frac{2 \pi}{N} k n}</math> |
||
=={{header|Julia}}== |
|||
<lang julia>function dft(A::AbstractArray{T,N}) where {T,N} |
|||
F = zeros(complex(float(T)), size(A)...) |
|||
for k in CartesianIndices(F), n in CartesianIndices(A) |
|||
F[k] += cispi(-2 * sum(d -> (k[d] - 1) * (n[d] - 1) / |
|||
real(eltype(F))(size(A, d)), ntuple(identity, Val{N}()))) * A[n] |
|||
end |
|||
return F |
|||
end |
|||
function idft(A::AbstractArray{T,N}) where {T,N} |
|||
F = zeros(complex(float(T)), size(A)...) |
|||
for k in CartesianIndices(F), n in CartesianIndices(A) |
|||
F[k] += cispi(2 * sum(d -> (k[d] - 1) * (n[d] - 1) / |
|||
real(eltype(F))(size(A, d)), ntuple(identity, Val{N}()))) * A[n] |
|||
end |
|||
return F ./ length(A) |
|||
end |
|||
const seq = [2, 3, 5, 7, 11] |
|||
const fseq = dft(seq) |
|||
const newseq = idft(fseq) |
|||
println("$seq =>\n$fseq =>\n$newseq =>\n", Int.(round.(newseq))) |
|||
</lang>{{out}} |
|||
<pre> |
|||
[2, 3, 5, 7, 11] => |
|||
ComplexF64[28.0 + 0.0im, -3.3819660112501033 + 8.784022634946172im, -5.618033988749888 + 2.800168985749483im, -5.618033988749888 - 2.800168985749483im, -3.381966011250112 - 8.78402263494618im] => |
|||
ComplexF64[2.0000000000000013 - 1.4210854715202005e-15im, 2.999999999999996 + 7.993605777301127e-16im, 5.000000000000002 + 2.1316282072803005e-15im, 6.999999999999998 - 8.881784197001252e-16im, 11.0 + 0.0im] => |
|||
[2, 3, 5, 7, 11] |
|||
</pre> |
Revision as of 06:52, 27 April 2021
The discrete Fourier transform is a linear, invertible transformation which transforms an arbitrary sequence of complex numbers to another sequence of complex numbers of the same length. The Fast Fourier transform (FFT) is an efficient implementation of this mechanism, but one which only works for sequences which have a length which is a power of 2.
The discrete Fourier transform is a useful testing mechanism to verify the correctness of code bases which use or implement the FFT.
For this task:
- Implement the discrete fourier transform
- Implement the inverse fourier transform
- (optional) implement a cleaning mechanism to remove small errors introduced by floating point representation.
- Verify the correctness of your implementation using a small sequence of integers, such as 2 3 5 7 11
The fourier transform of a sequence of length is given by:
The inverse transform is given by:
Julia
<lang julia>function dft(A::AbstractArray{T,N}) where {T,N}
F = zeros(complex(float(T)), size(A)...) for k in CartesianIndices(F), n in CartesianIndices(A) F[k] += cispi(-2 * sum(d -> (k[d] - 1) * (n[d] - 1) / real(eltype(F))(size(A, d)), ntuple(identity, Val{N}()))) * A[n] end return F
end
function idft(A::AbstractArray{T,N}) where {T,N}
F = zeros(complex(float(T)), size(A)...) for k in CartesianIndices(F), n in CartesianIndices(A) F[k] += cispi(2 * sum(d -> (k[d] - 1) * (n[d] - 1) / real(eltype(F))(size(A, d)), ntuple(identity, Val{N}()))) * A[n] end return F ./ length(A)
end
const seq = [2, 3, 5, 7, 11]
const fseq = dft(seq)
const newseq = idft(fseq)
println("$seq =>\n$fseq =>\n$newseq =>\n", Int.(round.(newseq)))
</lang>
- Output:
[2, 3, 5, 7, 11] => ComplexF64[28.0 + 0.0im, -3.3819660112501033 + 8.784022634946172im, -5.618033988749888 + 2.800168985749483im, -5.618033988749888 - 2.800168985749483im, -3.381966011250112 - 8.78402263494618im] => ComplexF64[2.0000000000000013 - 1.4210854715202005e-15im, 2.999999999999996 + 7.993605777301127e-16im, 5.000000000000002 + 2.1316282072803005e-15im, 6.999999999999998 - 8.881784197001252e-16im, 11.0 + 0.0im] => [2, 3, 5, 7, 11]