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
//
// A rust binding for the GSL library by Guillaume Gomez (guillaume1.gomez@gmail.com)
//

use ffi;
use c_vec::CSlice;

pub struct FftComplexWaveTable {
    w: *mut ffi::gsl_fft_complex_wavetable,
    f: CSlice<usize>
}

impl FftComplexWaveTable {
    /// 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.
    pub fn new(n: usize) -> Option<FftComplexWaveTable> {
        let tmp = unsafe { ffi::gsl_fft_complex_wavetable_alloc(n) };

        if tmp.is_null() {
            None
        } else {
            unsafe {
                Some(FftComplexWaveTable {
                    w: tmp,
                    f: CSlice::new((*tmp).factor.as_mut_ptr(), 64usize)
                })
            }
        }
    }

    pub fn factor<'r>(&'r mut self) -> &'r mut [usize] {
        self.f.as_mut()
    }
}

impl Drop for FftComplexWaveTable {
    fn drop(&mut self) {
        unsafe { ffi::gsl_fft_complex_wavetable_free(self.w) };
        self.w = ::std::ptr::null_mut();
    }
}

impl ffi::FFI<ffi::gsl_fft_complex_wavetable> for FftComplexWaveTable {
    fn wrap(w: *mut ffi::gsl_fft_complex_wavetable) -> FftComplexWaveTable {
        unsafe {
            FftComplexWaveTable {
                w: w,
                f: CSlice::new((*w).factor.as_mut_ptr(), 64usize)
            }
        }
    }

    fn soft_wrap(w: *mut ffi::gsl_fft_complex_wavetable) -> FftComplexWaveTable {
        Self::wrap(w)
    }

    fn unwrap_shared(w: &FftComplexWaveTable) -> *const ffi::gsl_fft_complex_wavetable {
        w.w as *const _
    }

    fn unwrap_unique(w: &mut FftComplexWaveTable) -> *mut ffi::gsl_fft_complex_wavetable {
        w.w
    }
}

pub struct FftComplexWorkspace {
    w: *mut ffi::gsl_fft_complex_workspace
}

impl FftComplexWorkspace {
    /// This function allocates a workspace for a complex transform of length n.
    pub fn new(n: usize) -> Option<FftComplexWorkspace> {
        let tmp = unsafe { ffi::gsl_fft_complex_workspace_alloc(n) };

        if tmp.is_null() {
            None
        } else {
            Some(FftComplexWorkspace {
                w: tmp
            })
        }
    }
}

impl Drop for FftComplexWorkspace {
    fn drop(&mut self) {
        unsafe { ffi::gsl_fft_complex_workspace_free(self.w) };
        self.w = ::std::ptr::null_mut();
    }
}

impl ffi::FFI<ffi::gsl_fft_complex_workspace> for FftComplexWorkspace {
    fn wrap(w: *mut ffi::gsl_fft_complex_workspace) -> FftComplexWorkspace {
        FftComplexWorkspace {
            w: w
        }
    }

    fn soft_wrap(w: *mut ffi::gsl_fft_complex_workspace) -> FftComplexWorkspace {
        Self::wrap(w)
    }

    fn unwrap_shared(w: &FftComplexWorkspace) -> *const ffi::gsl_fft_complex_workspace {
        w.w as *const _
    }

    fn unwrap_unique(w: &mut FftComplexWorkspace) -> *mut ffi::gsl_fft_complex_workspace {
        w.w
    }
}