Skip to main content

rustfft/
fft_helper.rs

1use crate::{
2    array_utils,
3    common::{fft_error_immut, fft_error_inplace, fft_error_outofplace},
4};
5
6// A utility that validates the provided FFT parameters, executes the FFT if validation succeeds, or panics with a hopefully helpful error message if validation fails
7// Since this implementation is basically always the same across all algorithms, this helper keeps us from having to duplicate it
8#[inline(always)]
9pub fn fft_helper_inplace<T>(
10    buffer: &mut [T],
11    scratch: &mut [T],
12    chunk_size: usize,
13    required_scratch: usize,
14    chunk_fn: impl FnMut(&mut [T], &mut [T]),
15) {
16    if chunk_size == 0 {
17        return;
18    }
19
20    let result =
21        array_utils::validate_and_iter(buffer, scratch, chunk_size, required_scratch, chunk_fn);
22
23    if result.is_err() {
24        // We want to trigger a panic, because the passed parameters failed validation in some way.
25        // But we want to avoid doing it in this function to reduce code size, so call a function marked cold and inline(never) that will do it for us
26        fft_error_inplace(chunk_size, buffer.len(), required_scratch, scratch.len());
27    }
28}
29
30// A utility that validates the provided FFT parameters, executes the FFT if validation succeeds, or panics with a hopefully helpful error message if validation fails
31// Since this implementation is basically always the same across all algorithms, this helper keeps us from having to duplicate it
32#[allow(dead_code)]
33#[inline(always)]
34pub fn fft_helper_inplace_unroll2x<T>(
35    buffer: &mut [T],
36    chunk_size: usize,
37    chunk2x_fn: impl FnMut(&mut [T]),
38    chunk_fn: impl FnMut(&mut [T]),
39) {
40    if chunk_size == 0 {
41        return;
42    }
43
44    let result = array_utils::validate_and_iter_unroll2x(buffer, chunk_size, chunk2x_fn, chunk_fn);
45
46    if result.is_err() {
47        // We want to trigger a panic, because the passed parameters failed validation in some way.
48        // But we want to avoid doing it in this function to reduce code size, so call a function marked cold and inline(never) that will do it for us
49        fft_error_inplace(chunk_size, buffer.len(), 0, 0);
50    }
51}
52
53// A utility that validates the provided FFT parameters, executes the FFT if validation succeeds, or panics with a hopefully helpful error message if validation fails
54// Since this implementation is basically always the same across all algorithms, this helper keeps us from having to duplicate it
55#[inline(always)]
56pub fn fft_helper_immut<T>(
57    input: &[T],
58    output: &mut [T],
59    scratch: &mut [T],
60    chunk_size: usize,
61    required_scratch: usize,
62    chunk_fn: impl FnMut(&[T], &mut [T], &mut [T]),
63) {
64    if chunk_size == 0 {
65        return;
66    }
67
68    let result = array_utils::validate_and_zip(
69        input,
70        output,
71        scratch,
72        chunk_size,
73        required_scratch,
74        chunk_fn,
75    );
76
77    if result.is_err() {
78        // We want to trigger a panic, because the passed parameters failed validation in some way.
79        // But we want to avoid doing it in this function to reduce code size, so call a function marked cold and inline(never) that will do it for us
80        fft_error_immut(
81            chunk_size,
82            input.len(),
83            output.len(),
84            required_scratch,
85            scratch.len(),
86        );
87    }
88}
89
90// A utility that validates the provided FFT parameters, executes the FFT if validation succeeds, or panics with a hopefully helpful error message if validation fails
91// Since this implementation is basically always the same across all algorithms, this helper keeps us from having to duplicate it
92#[allow(dead_code)]
93#[inline(always)]
94pub fn fft_helper_immut_unroll2x<T>(
95    input: &[T],
96    output: &mut [T],
97    chunk_size: usize,
98    chunk2x_fn: impl FnMut(&[T], &mut [T]),
99    chunk_fn: impl FnMut(&[T], &mut [T]),
100) {
101    if chunk_size == 0 {
102        return;
103    }
104
105    let result =
106        array_utils::validate_and_zip_unroll2x(input, output, chunk_size, chunk2x_fn, chunk_fn);
107
108    if result.is_err() {
109        // We want to trigger a panic, because the passed parameters failed validation in some way.
110        // But we want to avoid doing it in this function to reduce code size, so call a function marked cold and inline(never) that will do it for us
111        fft_error_immut(chunk_size, input.len(), output.len(), 0, 0);
112    }
113}
114
115// A utility that validates the provided FFT parameters, executes the FFT if validation succeeds, or panics with a hopefully helpful error message if validation fails
116// Since this implementation is basically always the same across all algorithms, this helper keeps us from having to duplicate it
117#[inline(always)]
118pub fn fft_helper_outofplace<T>(
119    input: &mut [T],
120    output: &mut [T],
121    scratch: &mut [T],
122    chunk_size: usize,
123    required_scratch: usize,
124    chunk_fn: impl FnMut(&mut [T], &mut [T], &mut [T]),
125) {
126    if chunk_size == 0 {
127        return;
128    }
129
130    let result = array_utils::validate_and_zip_mut(
131        input,
132        output,
133        scratch,
134        chunk_size,
135        required_scratch,
136        chunk_fn,
137    );
138
139    if result.is_err() {
140        // We want to trigger a panic, because the passed parameters failed validation in some way.
141        // But we want to avoid doing it in this function to reduce code size, so call a function marked cold and inline(never) that will do it for us
142        fft_error_outofplace(
143            chunk_size,
144            input.len(),
145            output.len(),
146            required_scratch,
147            scratch.len(),
148        );
149    }
150}
151
152// A utility that validates the provided FFT parameters, executes the FFT if validation succeeds, or panics with a hopefully helpful error message if validation fails
153// Since this implementation is basically always the same across all algorithms, this helper keeps us from having to duplicate it
154#[allow(dead_code)]
155#[inline(always)]
156pub fn fft_helper_outofplace_unroll2x<T>(
157    input: &mut [T],
158    output: &mut [T],
159    chunk_size: usize,
160    chunk2x_fn: impl FnMut(&mut [T], &mut [T]),
161    chunk_fn: impl FnMut(&mut [T], &mut [T]),
162) {
163    if chunk_size == 0 {
164        return;
165    }
166
167    let result =
168        array_utils::validate_and_zip_mut_unroll2x(input, output, chunk_size, chunk2x_fn, chunk_fn);
169
170    if result.is_err() {
171        // We want to trigger a panic, because the passed parameters failed validation in some way.
172        // But we want to avoid doing it in this function to reduce code size, so call a function marked cold and inline(never) that will do it for us
173        fft_error_outofplace(chunk_size, input.len(), output.len(), 0, 0);
174    }
175}