Extreme Optimization >
QuickStart Samples >
FFT/Fourier Transforms QuickStart Sample (F#)
Extreme Optimization QuickStart Samples
FFT / Fourier Transforms QuickStart Sample (F#)
Illustrates how to compute the forward and inverse Fourier transform
of a real or complex signal
using classes in the Extreme.Mathematics.SignalProcessing namespace in
F#.
C# code VB.NET code Back
to QuickStart Samples
#light
open System
open Extreme.Mathematics
// We'll need real vectors...
open Extreme.Mathematics.LinearAlgebra
// and complex vectors...
open Extreme.Mathematics.LinearAlgebra.Complex
// The FFT classes reside in the Extreme.Mathematics.SignalProcessing
// namespace.
open Extreme.Mathematics.SignalProcessing
/// <summary>
/// Illustrates the use of the FftProvider and Fft classes for computing
/// the Fourier transform of real and complex signals.
/// </summary>
// This QuickStart sample shows how to compute the Fouier
// transform of real and complex signals.
// A quick helper to construct complex numbers.
let complex a b = new DoubleComplex(a, b)
// Some vectors to play with:
let r1 = new GeneralVector(1000)
for i = 0 to r1.Length -1 do
r1.Item(i) <- 1.0 / (1.0 + float i)
let c1 = new ComplexGeneralVector(1000)
for i = 0 to c1.Length -1 do
c1.Item(i) <- new DoubleComplex(Math.Sin(0.03 * float i), Math.Cos(0.07 * float i))
let r2 = new GeneralVector([|1.0; 2.0; 3.0; 4.0|])
let c2 = new ComplexGeneralVector([|complex 1.0 2.0; complex 3.0 4.0; complex 5.0 6.0; complex 7.0 8.0|])
//
// One-time FFT's
//
// The Vector and ComplexVector classes have static methods to compute FFT's:
let c3 = Vector.FourierTransform(r2)
let r3 = Vector.InverseFourierTransform(c3)
Console.WriteLine("fft(r2) = {0:F3}", c3)
Console.WriteLine("ifft(fft(r2)) = {0:F3}", r3)
// The ComplexConjugateSignalVector type represents a complex vector
// that is the Fourier transform of a real signal.
// It enforces certain symmetry properties:
Console.WriteLine("c3.Item(i) == conj(c3[N-i]): {0} == conj({1})", c3.Item(1), c3.Item(3))
//
// FFT Providers
//
// FFT's require a fair bit of pre-computation. Using the FftProvider class,
// you can get an Fft object that caches these computations.
// Here, we create an FFT implementation for a real signal:
let realFft = FftProvider.ManagedProvider.Create1DRealFft(r1.Length)
// For a complex to complex transform:
let complexFft = FftProvider.ManagedProvider.Create1DComplexFft(c1.Length)
// You can set the scale factor for the forward transform.
// The default is 1/N.
realFft.ForwardScaleFactor <- 1.0 / Math.Sqrt(float c1.Length)
// and the backward transform, with default 1:
realFft.BackwardScaleFactor <- realFft.ForwardScaleFactor
// The ForwardTransform method performs a forward transform:
let c4 = realFft.ForwardTransform(r1)
Console.WriteLine("First 5 terms of fft(r1):")
for i = 0 to 4 do
Console.WriteLine(" {0}: {1}", i, c4.Item(i))
let c5 = complexFft.ForwardTransform(c1)
Console.WriteLine("First 5 terms of fft(c1):")
for i = 0 to 4 do
Console.WriteLine(" {0}: {1}", i, c5.Item(i))
// ForwardTransform has many overloads for real to complex and
// complex to complex transforms.
// A one-sided transform returns only the first half of the FFT of
// a real signal. The rest can be deduced from the symmetry properties.
// Here's how to compute a one-sided FFT:
let c6 = new ComplexGeneralVector(r1.Length / 2 + 1)
realFft.ForwardTransform(r1, c6, RealFftFormat.OneSided)
// The BackwardTransform method has a similar set of overloads:
let r4 = new GeneralVector(r1.Length)
realFft.BackwardTransform(c6, r4, RealFftFormat.OneSided)
//
// 2D transforms
//
// A 2D FFT is computed as a series of FFT's in one direction followed by
// a series of FFT's in the other. For the forward transform:
let m = new GeneralMatrix(36, 56)
for i = 0 to m.RowCount - 1 do
for j = 0 to m.ColumnCount - 1 do
m.Item(i, j) <- Math.Exp(-0.1 * float i) * Math.Sin(0.01 * float (i * i + j * j - i * j))
let mFft = new ComplexGeneralMatrix(m.RowCount, m.ColumnCount)
// With a open statement, we make sure Dispose is called automatically.
let rowFft = FftProvider.Current.Create1DRealFft(m.ColumnCount)
let columnFft = FftProvider.Current.Create1DComplexFft(m.RowCount)
for k = 0 to m.RowCount - 1 do
rowFft.ForwardTransform(m.GetRow(k), mFft.GetRow(k))
columnFft.InPlace <- true
for col in mFft.Columns do
columnFft.ForwardTransformInPlace(col)
Console.WriteLine("First few terms of fft(m):")
for i = 0 to 3 do
for j = 0 to 3 do
if (j > 0) then Console.Write(", ")
Console.Write("{0}", mFft.Item(i, j).ToString("F4"))
Console.WriteLine()
// and the backward transform:
for col in mFft.Columns do
columnFft.BackwardTransformInPlace(col)
for k = 0 to m.RowCount - 1 do
rowFft.BackwardTransform(mFft.GetRow(k), m.GetRow(k))
Console.Write("Press Enter key to exit...")
Console.ReadLine()
Copyright 2004-2007,
Extreme Optimization. All rights reserved.
Extreme Optimization, Complexity made simple, M#, and M
Sharp are trademarks of ExoAnalytics Inc.
Microsoft, Visual C#, Visual Basic, Visual Studio, and Visual
Studio.NET are registered trademarks of Microsoft Corporation