4
$\begingroup$

Mathematica's Fourier function allows you to insert an arbitrary real number in the exponent of the discrete Fourier transform, via FourierParameters, so that the transform becomes something like $$ \sum_{j=1}^n u_j e^{2\pi i b (j-1)(k-1)/n} $$ with $b$ arbitrary.

I find this very useful in my work, but I don't understand how it works. The usual description of the FFT algorithm (e.g. as outlined in "Numerical Recipes") depends in an essential way on the $n$-periodicity of exponential factor. When I insert an arbitrary $b$ and call Fourier, am I still getting a fast Fourier transform? Or is it secretly doing a slow DFT? In the former case, how does Mathematica get around the need for a periodic exponential factor?

$\endgroup$
8
  • $\begingroup$ The documentation to Fourier in the "Details and Options" section clearly says "To ensure a unique inverse discrete Fourier transform, Abs[b] must be relatively prime to n. »" and "Some common choices for {a,b} are {0,1} (default), {-1,1} (data analysis), {1,-1} (signal processing). ". $\endgroup$
    – user64494
    Commented Oct 20, 2021 at 6:29
  • 1
    $\begingroup$ @user64494 That's not relevant to the question here though. Fourier still computes the transform of a sequence, even if the choice of parameters mean that the transform is not invertable. The question is how it does that, and in particular whether the transform is still "fast" ($O(n \log(n))$). Also, there are many values of FourierParameters which make the transform still invertable (i.e. no warning is shown), but would seem to break the naive FFT algorithm. If anything, this makes it even more mysterious how Fourier does what it does. $\endgroup$
    – Yly
    Commented Oct 20, 2021 at 7:33
  • $\begingroup$ I thinkFourier is simply meaningless in that case. Can you ground "Also, there are many values of FourierParameters which make the transform still invertable (i.e. no warning is shown), but would seem to break the naive FFT algorithm. "? TIA. $\endgroup$
    – user64494
    Commented Oct 20, 2021 at 10:00
  • $\begingroup$ There are references here I have used this to interpolate a Fourier spectrum. There is an example of using it in the Mathematica GuideBook for Numerics p 245 $\endgroup$
    – Hugh
    Commented Oct 20, 2021 at 15:48
  • 1
    $\begingroup$ A possible implementation can be based on ffrft (unit circle CZT) $\endgroup$
    – I.M.
    Commented Oct 21, 2021 at 6:50

2 Answers 2

1
$\begingroup$

Here is an example of how to use FourierParameters for interpolating a spectrum. First we generate some data, take the ordinary Fourier transform and plot.

data = Table[Sin[\[Pi] k/33], {k, 256}] // N;
ListLinePlot[data]
ft = Fourier[data, FourierParameters -> {-1, -1}];
ListLinePlot[Abs@ft[[1 ;; 128]], PlotRange -> All]
ListPlot[Abs@ft[[1 ;; 20]], PlotRange -> All]

enter image description here

enter image description here

enter image description here

The last, expanded view of the spectrum shows that there are rather few points defining the peak.

The following Dynamic enables the interpolation to be seen when FourierParameters are altered. The actual frequency and the magnitude of the Fourier peak should be

 (*   {0.0151515, 0.511146}   *)

DynamicModule[{b = 1, pos, a = 0, ft, freqs},
 ft = Abs@Fourier[data, FourierParameters -> {-1, b}];
 pos = Position[ft, Max[ft]][[1, 1]];
 freqs = Table[(n - 1)/Length[data], {n, Length[data]}];
 Column[{
   Dynamic[
    Row[{"Frequency (Hz) = ", a[[1]], "     Magnitude = ", a[[2]] }]],
   Dynamic@ListLinePlot[Transpose[{freqs, ft}], PlotRange -> All,
     Epilog -> {Red, PointSize[0.01], 
       Point[a = Transpose[{freqs, ft}][[pos]]]},
     ImageSize -> 12 72, Frame -> True, Mesh -> All],
   Slider[Dynamic[b, {b = #;
       ft = Abs@Fourier[data, FourierParameters -> {-1, b}];
       freqs = Table[b (n - 1)/Length[data], {n, Length[data]}];
       pos = Position[ft, Max[ft]][[1, 1]]
       } &], {0, 1}, Appearance -> "Labeled"]
   }]
 ]

enter image description here

As you can see we can get many more points into the peak and have thus interpolated the spectrum. Thus we can more accurately work out the frequency.

Hope that helps.

$\endgroup$
1
  • $\begingroup$ To clarify: I know how to do this. What I'm asking is not "How to use FourierParameters?", but rather "How does Mathematica implement FourierParameters without breaking the $n\log(n)$ scaling of the FFT algorithm?". I guess this reply is still helpful for clarifying to others what FourierParameters is capable of, but it does not answer the question. $\endgroup$
    – Yly
    Commented Oct 20, 2021 at 19:27
0
$\begingroup$

Here is an implementation based on Bailey's paper.

ClearAll[ffrft$set] ;
ffrft$set[length_, span_] := Block[
{trig, work},
trig =Exp[I*Pi*span/length*Range[0.0, length-1]^2] ;
work = Fourier[Flatten[{Conjugate[trig] , Exp[-I*Pi*span/length*Range[-length, -1.0]^2]}] , FourierParameters -> {1, 1} ];
{trig, work}
] ;

ClearAll[ffrft$get] ;
ffrft$get[length_, signal_, trig_, work_] := Block[
{ffrft},
ffrft = ConstantArray[0.0, 2*length]  ;
ffrft[[1;;length]] = trig*signal ;
ffrft = work*Fourier[ffrft, FourierParameters -> {1, 1} ] ;
ffrft =Fourier[ffrft, FourierParameters -> {1, -1} ][[1;;length]] ;
ffrft*trig/(2*length)
] ;

Example:

length = 1024 ;
signal = Sin[2*Pi*0.12345*Range[length]] ;
b = 1/Sqrt[2.0]  ;
{trig, work} = ffrft$set[length, b]  ;
ref = Fourier[signal, FourierParameters -> {1, b}] ;
res = ffrft$get[length, signal, trig, work] ;
ref-res // Chop // DeleteDuplicates
(* {0} *)

Timing:

length = 8192 ;
signal = Sin[2*Pi*0.12345*Range[length]] ;
b = 1/Sqrt[2.0]  ;
t$ref = First@RepeatedTiming[Fourier[signal, FourierParameters -> {1, b}] ];
t$res = First@RepeatedTiming[{trig, work} = ffrft$set[length, b]  ; ffrft$get[length, signal, trig, work] ];
t$ref/t$res

For FourierParameters -> {1, 1} WM is most likely uses FFT from MKL, while for FourierParameters -> {a, b} it is not clear. While it is possible to compute with n*log(n), I'm not sure it is the case in WM.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.