7.5 KiB
4.0 to 5.0 Upgrade Guide
RustFFT 5.0 has several breaking changes compared to 4.0. This document will guide users through the upgrade process, explaining each breaking change and how to upgrade code to fit the new style.
Each section is ordered by how likely they are to impact you: Things at the top are likely to affect every user of RustFFT, while things at the bottom are unlikely to affect most users.
Renaming Structs
Several structs and traits in RustFFT were renamed to follow the Rust API guidlines regarding acronyms:
In UpperCamelCase, acronyms and contractions of compound words count as one word: use Uuid rather than UUID, Usize rather than USize or Stdin rather than StdIn.
The following were renamed in RustFFT 5.0 to conform to this style:
- The
FFT
trait was renamed toFft
- The
FFTnum
trait was renamed toFftNum
- The
FFTplanner
struct was renamed toFftPlanner
- The
DFT
struct was renamed toDft
FFT Direction
In RustFFT 4.0, forward FFTs vs inverse FFTs were specified by a boolean. For example, the 4.0 FFTplanner
constructor expects a boolean parameter for direction: If you pass false
, the planner will plan forward FFTs. If you pass true
, the planner will plan inverse FFTs.
In 5.0, there is a new FftDirection
enum with Forward
and Inverse
variants. FFT algorithms that took a bool
for direction now take FftDirection
instead. For example, if you were constructing a Radix4
instance to compute a power-of-two FFT, you will have to change the parameters to the constructor:
// RustFFT 4.0
let fft_forward = Radix4::new(4096, false);
let fft_inverse = Radix4::new(4096, true);
// RustFFT 5.0
let fft_forward = Radix4::new(4096, FftDirection::Forward);
let fft_inverse = Radix4::new(4096, FftDirection::Inverse);
A few traits and methods were renamed to support the new FftDirection
trait:
- The
IsInverse
trait was renamed toDirection
IsInverse
's only method,is_inverse(&self) -> bool
, was renamed tofft_direction(&self) -> FftDirection
- The
Fft
trait inherited theIsInverse
trait, and now inherits theDirection
trait instead, so if you were callingis_inverse()
on aFft
instance you'll have to change that tofft_direction()
as well.
Finally, the way the FftPlanner
handles forward vs inverse FFTs has changed. In 4.0, the FFTplanner
took a direction in its constructor -- In 5.0, its constructor is empty, and it takes a direction in its plan_fft
method. This means a single planner can be used to plan both forward and inverse FFTs.
The FftPlanner
also has plan_fft_forward
and plan_fft_inverse
convenince methods so that you don't have to import the FftDirection enum.
// RustFFT 4.0
let planner_forward = FFTplanner::new(false);
let fft_forward = planner.plan_fft(1234);
let planner_inverse = FFTplanner::new(true);
let fft_inverse = planner.plan_fft(1234);
// RustFFT 5.0
let planner = FftPlanner::new();
let fft_forward1 = planner.plan_fft(1234, FftDirection::Forward);
let fft_forward2 = planner.plan_fft_forward(1234);
let fft_inverse1 = planner.plan_fft(1234, FftDirection::Inverse);
let fft_inverse2 = planner.plan_fft_inverse(1234);
Fft Trait Methods
In RustFFT 4.0, the Fft
trait has two methods:
FFT::process()
took an input and output buffer, and computed a single FFT, storing the result in the output buffer.FFT::process_multi()
took an input and output buffer, divided those buffers into chunks of sizefft.len()
, and computed a FFT on each chunk.
RustFFT 5.0 makes a few changes to this setup. First, there is no longer a distinction between "single" and "multi" FFT methods: All Fft
trait methods compute multiple FFTs if provided a buffer whose length is a multiple of the FFT length.
Second, the Fft
trait now has three methods. Most users will want the first method:
Fft::process()
takes a single buffer instead of two, and computes FFTs in-place. Internally, it allocates scratch space as needed.Fft::process_with_scratch()
takes two buffers: A data buffer, and a scratch buffer. It computes FFTs in-place on the data buffer, using the provided scratch space as needed.Fft::process_outofplace_with_scratch()
takes three buffers: An input buffer, an output buffer, and a scratch buffer. It computes FFTs from the input buffer and stores the results in the output buffer, using the provided scratch space as needed.
Example for users who want to use the new in-place process()
behavior:
// RustFFT 4.0
let fft = Radix4::new(4096, false);
let mut input : Vec<Complex<f32>> = get_my_input_data();
let mut output = vec![Complex::zero(); fft.len()];
fft.process(&mut input, &mut output);
// RustFFT 5.0
let fft = Radix4::new(4096, FftDirection::Forward);
let mut buffer : Vec<Complex<f32>> = get_my_input_data();
fft.process(&mut buffer);
Example for users who want to keep the old out-of-place process()
behavior from RustFFT 4.0:
// RustFFT 4.0
let fft = Radix4::new(4096, false);
let mut input : Vec<Complex<f32>> = get_my_input_data();
let mut output = vec![Complex::zero(); fft.len()];
fft.process(&mut input, &mut output);
// RustFFT 5.0
let fft = Radix4::new(4096, FftDirection::Forward);
let mut input : Vec<Complex<f32>> = get_my_input_data();
let mut output = vec![Complex::zero(); fft.len()];
let mut scratch = vec![Complex::zero(); fft.get_outofplace_scratch_len()];
fft.process_outofplace_with_scratch(&mut input, &mut output, &mut scratch);
Rader's Algorithm Constructor
The constructor for RadersAlgorithm
has changed. In RustFFT 4.0, its signature was pub fn new(len: usize, inner_fft: Arc<dyn FFT<T>>)
, and it asserted that len == inner_fft.len() + 1
RustFFT 5.0 removes the len: usize
parameter, and RadersAlgorithm
derives its FFT length from the inner FFT length instead.
// RustFFT 4.0
let inner_fft : Arc<dyn Fft<T>> = ...;
let fft = RadersAlgorithm::new(inner_fft.len() + 1, inner_fft);
// RustFFT 5.0
let inner_fft : Arc<dyn Fft<T>> = ...;
let fft = RadersAlgorithm::new(inner_fft);
Deleted the FFTButterfly
trait
In RustFFT 4.0, there was a trait called FFTbutterfly
. This trait has been deleted. It had two methods which were merged into the Fft
trait:
FFTButterfly::process_inplace
is replaced byFft::process_inplace
orFft::process_inplace_with_scratch
FFTButterfly::process_multi_inplace
is replaced byFft::process_inplace_multi
Two FFT algorithms relied on the deleted trait: MixedRadixDoubleButterfly
and GoodThomasAlgorithmDoubleButterfly
. They took FFTbutterfly
trait objects in their constructor. They've been renamed to MixedRadixSmall
and GoodThomasAlgorithmSmall
respectively, and take Fft
trait objects in their constructor.
// RustFFT 4.0
let butterfly8 : Arc<dyn FFTbutterfly<T>> = Arc::new(Butterfly8::new(false));
let butterfly3 : Arc<dyn FFTbutterfly<T>> = Arc::new(Butterfly3::new(false));
let fft1 = MixedRadixDoubleButterfly::new(Arc::clone(&butterfly8), Arc::clone(&butterfly3));
let fft2 = GoodThomasAlgorithmDoubleButterfly::new(Arc::clone(&butterfly8), Arc::clone(&butterfly3));
// RustFFT 5.0
let butterfly8 : Arc<dyn Fft<T>> = Arc::new(Butterfly8::new(FftDirection::Forward));
let butterfly3 : Arc<dyn Fft<T>> = Arc::new(Butterfly3::new(FftDirection::Forward));
let fft1 = MixedRadixSmall::new(Arc::clone(&butterfly8), Arc::clone(&butterfly3));
let fft2 = GoodThomasAlgorithmSmall::new(Arc::clone(&butterfly8), Arc::clone(&butterfly3));