You next create "FFT objects." In VSIPL++, FFTs are objects, rather than operators. Typically (as in the example here), an application performs multiple FFTs on inputs with the same size. In that case, it is more computationally efficient to set up the FFT only once, since the set-up involves memory allocation and, potentially, other configuration. In VSIPL++, constructing the FFT object performs this set-up operation. VSIPL++ supports a variety of different kinds of FFT, so FFTs are themselves template classes. The template parameters tell VSIPL++ what kind of FFT is desired:
typedef Fft<const_Vector, T, T, fft_fwd, by_reference> fwd_fft_type; typedef Fft<const_Vector, T, T, fft_inv, by_reference> inv_fft_type; fwd_fft_type fwd_fft(N, 1.0f); inv_fft_type inv_fft(N, 1.0f / N);
The first two lines declare the types of the FFT objects; the last two lines perform the actual creation of the objects. The first parameter to the FFT constructor gives the number of elements over which the FFT will be performed; the second gives a "scaling factor" to apply to each element in the resulting FFT. For pragmatic computational reasons, both the forward and inverse FFTs scale by the product of the sqrt(N) and the explicit scaling factor. So if you apply a forward and inverse FFT in sequence, using a scaling factor of 1 both times, the output is N times larger than the input. Since you want the input and output to have the same scale, you divide the inverse FFT by N.
Then, to actually perform the computation:
for (length_type i = 0; i < M; ++i) { fwd_fft(inputs.row(i), outputs.row(i)); outputs.row(i) *= filters.row(i); inv_fft(outputs.row(i)); }
Here, you apply the forward FFT to the data gathered by a sensor, moving from the time domain to the frequency domain. (FFT objects can be called like functions, so even though they are objects, they look like operators after they have been created.) Next, use the *= operator on vectors to perform element-wise multiplication. (There is a separate function for computing the dot product of two vectors.) Finally, use the inverse-FFT to return to the time domain.
This example demonstrates how easy it is to write code with VSIPL++. It takes just a few lines to perform a useful computation, and the code corresponds closely to the mathematical or algorithmic description of the problem. The VSIPL++ code here almost looks like pseudocode, but it is actually a high-performance implementation of the algorithm.