use crate::fft::FFTProcessor;
use std::os::raw::c_double;
use std::os::raw::c_int;
use std::os::raw::c_uint;
pub enum SpqliosImpl {}
extern "C" {
fn Spqlios_new(N: c_int) -> *mut SpqliosImpl;
fn Spqlios_destructor(spqlios: *mut SpqliosImpl);
fn Spqlios_ifft_lv1(spqlios: *mut SpqliosImpl, res: *mut c_double, src: *const c_uint);
fn Spqlios_fft_lv1(spqlios: *mut SpqliosImpl, res: *mut c_uint, src: *const c_double);
fn Spqlios_poly_mul_1024(
spqlios: *mut SpqliosImpl,
res: *mut c_uint,
src_a: *const c_uint,
src_b: *const c_uint,
);
}
pub struct SpqliosFFT {
raw: *mut SpqliosImpl,
n: usize,
}
impl FFTProcessor for SpqliosFFT {
fn new(n: usize) -> Self {
unsafe {
SpqliosFFT {
raw: Spqlios_new(n as i32),
n,
}
}
}
fn ifft<const N: usize>(&mut self, input: &[u32; N]) -> [f64; N] {
let mut res: [f64; N] = [0.0f64; N];
unsafe {
Spqlios_ifft_lv1(self.raw, res.as_mut_ptr(), input.as_ptr());
}
res.try_into().unwrap()
}
fn fft<const N: usize>(&mut self, input: &[f64; N]) -> [u32; N] {
let mut res: [u32; N] = [0u32; N];
unsafe {
Spqlios_fft_lv1(self.raw, res.as_mut_ptr(), input.as_ptr());
}
res.try_into().unwrap()
}
fn poly_mul<const N: usize>(&mut self, a: &[u32; N], b: &[u32; N]) -> [u32; N] {
let mut res: [u32; N] = [0u32; N];
let res_mut_ptr = res.as_mut_ptr() as *mut _;
unsafe {
Spqlios_poly_mul_1024(self.raw, res_mut_ptr, a.as_ptr(), b.as_ptr());
}
res.try_into().unwrap()
}
fn batch_ifft<const N: usize>(&mut self, inputs: &[[u32; N]]) -> Vec<[f64; N]> {
inputs.iter().map(|input| self.ifft::<N>(input)).collect()
}
fn batch_fft<const N: usize>(&mut self, inputs: &[[f64; N]]) -> Vec<[u32; N]> {
inputs.iter().map(|input| self.fft::<N>(input)).collect()
}
}
impl Drop for SpqliosFFT {
fn drop(&mut self) {
unsafe {
Spqlios_destructor(self.raw);
}
}
}