Fast Fourier transform: Difference between revisions
Content added Content deleted
SqrtNegInf (talk | contribs) m (→{{header|Perl}}: Fix link: Perl 6 --> Raku) |
(Add Swift) |
||
Line 3,285: | Line 3,285: | ||
| -2 2 | |
| -2 2 | |
||
+-----------------+</pre> |
+-----------------+</pre> |
||
=={{header|Swift}}== |
|||
{{libheader|Swift Numerics}} |
|||
{{trans|Kotlin}} |
|||
<lang swift>import Foundation |
|||
import Numerics |
|||
typealias Complex = Numerics.Complex<Double> |
|||
extension Complex { |
|||
var exp: Complex { |
|||
Complex(cos(imaginary), sin(imaginary)) * Complex(cosh(real), sinh(real)) |
|||
} |
|||
public var pretty: String { |
|||
let real2 = real != -0 ? real : 0.0 |
|||
let imag = imaginary != -0 ? imaginary : 0.0 |
|||
let fmt = { String(format: "%.3f", $0) } |
|||
let result = |
|||
(imag >= 0 ? "\(fmt(real2)) + \(fmt(imag))i" : "\(fmt(real2)) - \(fmt(-imag))i") |
|||
.replacingOccurrences(of: ".0 ", with: " ") |
|||
.replacingOccurrences(of: ".0i", with: "i") |
|||
.replacingOccurrences(of: " + 0i", with: "") |
|||
if result.hasPrefix("0 ") { |
|||
return result |
|||
.replacingOccurrences(of: "0 ", with: "") |
|||
.replacingOccurrences(of: " ", with: "") |
|||
} else { |
|||
return result |
|||
} |
|||
} |
|||
} |
|||
func fft(_ array: [Complex]) -> [Complex] { _fft(array, direction: Complex(0.0, 2.0), scalar: 1) } |
|||
func rfft(_ array: [Complex]) -> [Complex] { _fft(array, direction: Complex(0.0, -2.0), scalar: 2) } |
|||
private func _fft(_ arr: [Complex], direction: Complex, scalar: Double) -> [Complex] { |
|||
guard arr.count > 1 else { |
|||
return arr |
|||
} |
|||
let n = arr.count |
|||
let cScalar = Complex(scalar, 0) |
|||
precondition(n % 2 == 0, "The Cooley-Tukey FFT algorithm only works when the length of the input is even.") |
|||
var evens = [Complex]() |
|||
var odds = [Complex]() |
|||
for i in 0..<n { |
|||
if i & 1 == 1 { |
|||
odds.append(arr[i]) |
|||
} else { |
|||
evens.append(arr[i]) |
|||
} |
|||
} |
|||
evens = _fft(evens, direction: direction, scalar: scalar) |
|||
odds = _fft(odds, direction: direction, scalar: scalar) |
|||
let pairs = (0 ..< n / 2).map({i -> (Complex, Complex) in |
|||
let offset = (direction * Complex((.pi * Double(i) / Double(n)), 0)).exp * odds[i] / cScalar |
|||
let base = evens[i] / cScalar |
|||
return (base + offset, base - offset) |
|||
}) |
|||
var left = [Complex]() |
|||
var right = [Complex]() |
|||
for (l, r) in pairs { |
|||
left.append(l) |
|||
right.append(r) |
|||
} |
|||
return left + right |
|||
} |
|||
let dat = [Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0), Complex(1.0, 0.0), |
|||
Complex(0.0, 0.0), Complex(0.0, 2.0), Complex(0.0, 0.0), Complex(0.0, 0.0)] |
|||
print(fft(dat).map({ $0.pretty })) |
|||
print(rfft(f).map({ $0.pretty }))</lang> |
|||
{{out}} |
|||
<pre>["4.000 + 2.000i", "2.414 + 1.000i", "-2.000 + 0.000i", "2.414 + 1.828i", "0.000 - 2.000i", "-0.414 + 1.000i", "2.000 - 0.000i", "-0.414 - 3.828i"] |
|||
["1.000 + 0.000i", "1.000 + 0.000i", "1.000 + 0.000i", "1.000 + 0.000i", "0.000 + 0.000i", "0.000 + 2.000i", "0.000 - 0.000i", "0.000 + 0.000i"]</pre> |
|||
=={{header|SystemVerilog}}== |
=={{header|SystemVerilog}}== |