Transforms of Real Sequences
It is worth discussing the difference between DComplexFFTServer and DoubleFFTServer. Say you want to transform a real sequence of N points V(j), j=0, ..., N–1. Note that the transform of a real sequence is a complex conjugate-even sequence, that is, a sequence where C(j) = conj(C(–j)) = conj(C(N–j)). How can you calculate the transform? In general, you have two choices:
*Convert the real sequence to a complex sequence with imaginary parts set to 0 and transform that;
*Take advantage of the fact that the imaginary parts of the sequence are 0 and transform the N-point real sequence as an N/2-point complex sequence.
The DoubleFFTServer uses the second approach. Because the result is a complex conjugate-even sequence, the DoubleFFTServer returns only the lower half of the sequence, which saves considerable time. Here is an example illustrating the two approaches:
 
#include <rw/dfft.h>
#include <rw/cfft.h>
#include <iostream.h>
 
const unsigned npts = 12;
 
int main()
{
// Real sequence to be transformed (a linear ramp):
RWMathVec<double> V(npts, 0.0, 1.0);
 
// Print it out:
cout << "Original (real) sequence:\n" << V << "\n";
 
/***************** Approach 1 **********************/
RWMathVec<DComplex> Vcomplex(V); // Convert to complex
 
// Construct a complex FFT server:
DComplexFFTServer dcffts;
 
// Vtrans1 will be 12 points long
// and complex-conjugate even:
RWMathVec<DComplex> Vtrans1 = dcffts.fourier(Vcomplex);
 
/************ An alternative (approach 2) ***********/
DoubleFFTServer dffts; // Use a double FFT server
 
// Vtrans2 will be 7 points long: the
// lower half of Vtrans1:
RWMathVec<DComplex> Vtrans2 = dffts.fourier(V);
 
cout << "Transform using approach 1:\n" << Vtrans1;
cout << endl;
cout << "Transform using approach 2:\n" << Vtrans2;
cout << endl;
}
Program output (exact results depend on machine precision):
Original (real) sequence:
[
0 1 2 3 4
5 6 7 8 9
10 11
]
Transform using Approach 1:
[
(66, 0) (-6, 22.3923) (-6, 10.3923) (-6, 6) (-6, 3.4641)
(-6, 1.6077) (-6, 0) (-6, -1.6077) (-6, -3.4641) (-6, -6)
(-6, -10.3923) (-6, -22.3923)
]
Transform using Approach 2:
[
(66, 0) (-6, 22.3923) (-6, 10.3923) (-6, 6) (-6, 3.4641)
(-6, 1.6077) (-6, 0)
]
 
A close inspection shows that the full transformed sequence using the first approach is complex-conjugate even. The second approach, using the DoubleFFTServer, returns only the lower half of that sequence. The global function expandConjugateEven() can be used to expand it into the full N-point conjugate-even sequence. See the RWMathVec description in the SourcePro API Reference Guide for more information.