1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
//
// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
//
use crate::paste::paste;
use crate::Value;
use ffi::FFI;
macro_rules! gsl_fft_wavetable {
($rust_name:ident, $name:ident, $complex_rust_name:ident, $complex_name:ident, $ty:ident $(, $extra:ident)?) => (
paste! {
ffi_wrapper!(
$rust_name,
*mut sys::[<$name _wavetable $($extra)?>],
[<$name _wavetable $($extra)? _free>]
);
impl $rust_name {
/// This function prepares a trigonometric lookup table for a complex FFT of length n. The
/// function returns a pointer to the newly allocated gsl_fft_complex_wavetable if no errors
/// were detected, and a null pointer in the case of error. The length n is factorized into a
/// product of subtransforms, and the factors and their trigonometric coefficients are stored in
/// the wavetable. The trigonometric coefficients are computed using direct calls to sin and
/// cos, for accuracy. Recursion relations could be used to compute the lookup table faster, but
/// if an application performs many FFTs of the same length then this computation is a one-off
/// overhead which does not affect the final throughput.
///
/// The wavetable structure can be used repeatedly for any transform of the same length. The
/// table is not modified by calls to any of the other FFT functions. The same wavetable can be
/// used for both forward and backward (or inverse) transforms of a given length.
#[doc(alias = $name _wavetable $($extra)? _alloc)]
pub fn new(n: usize) -> Option<Self> {
let tmp = unsafe { sys::[<$name _wavetable $($extra)? _alloc>](n) };
if tmp.is_null() {
None
} else {
Some(Self::wrap(tmp))
}
}
pub fn nf(&self) -> usize {
unsafe { (*self.unwrap_shared()).nf }
}
pub fn factor(&self) -> &[usize] {
unsafe { &(*self.unwrap_shared()).factor }
}
pub fn factor_mut(&mut self) -> &mut [usize] {
unsafe { &mut (*self.unwrap_unique()).factor }
}
}
ffi_wrapper!(
$complex_rust_name,
*mut sys::$complex_name,
[<$complex_name _free>]
);
impl $complex_rust_name {
/// This function allocates a workspace for a complex transform of length n.
#[doc(alias = $complex_name _alloc)]
pub fn new(n: usize) -> Option<Self> {
let tmp = unsafe { sys::[<$complex_name _alloc>](n) };
if tmp.is_null() {
None
} else {
Some(Self::wrap(tmp))
}
}
#[doc(alias = $name $($extra)? _forward)]
pub fn forward(
&mut self,
data: &mut [$ty],
stride: usize,
n: usize,
wavetable: &$rust_name,
) -> Result<(), Value> {
let ret = unsafe {
sys::[<$name $($extra)? _forward>](
data.as_mut_ptr(),
stride,
n,
wavetable.unwrap_shared(),
self.unwrap_unique(),
)
};
result_handler!(ret, ())
}
#[doc(alias = $name $($extra)? _transform)]
pub fn transform(
&mut self,
data: &mut [$ty],
stride: usize,
n: usize,
wavetable: &$rust_name,
sign: ::FftDirection,
) -> Result<(), Value> {
let ret = unsafe {
sys::[<$name $($extra)? _transform>](
data.as_mut_ptr(),
stride,
n,
wavetable.unwrap_shared(),
self.unwrap_unique(),
sign.into(),
)
};
result_handler!(ret, ())
}
#[doc(alias = $name $($extra)? _backward)]
pub fn backward(
&mut self,
data: &mut [$ty],
stride: usize,
n: usize,
wavetable: &$rust_name,
) -> Result<(), Value> {
let ret = unsafe {
sys::[<$name $($extra)? _backward>](
data.as_mut_ptr(),
stride,
n,
wavetable.unwrap_shared(),
self.unwrap_unique(),
)
};
result_handler!(ret, ())
}
#[doc(alias = $name $($extra)? _inverse)]
pub fn inverse(
&mut self,
data: &mut [$ty],
stride: usize,
n: usize,
wavetable: &$rust_name,
) -> Result<(), Value> {
let ret = unsafe {
sys::[<$name $($extra)? _inverse>](
data.as_mut_ptr(),
stride,
n,
wavetable.unwrap_shared(),
self.unwrap_unique(),
)
};
result_handler!(ret, ())
}
}
} // end of paste! block
); // end of macro block
}
gsl_fft_wavetable!(
FftComplexF64WaveTable,
gsl_fft_complex,
FftComplexF64Workspace,
gsl_fft_complex_workspace,
f64
);
gsl_fft_wavetable!(
FftComplexF32WaveTable,
gsl_fft_complex,
FftComplexF32Workspace,
gsl_fft_complex_workspace_float,
f32,
_float
);