extern crate libc;
extern crate num;
use self::libc::{c_double, c_float, c_int, c_longlong, c_uint, size_t};
use self::num::Complex;
use crate::array::Array;
use crate::defines::{AfError, ConvDomain, ConvMode, InterpType};
use crate::error::HANDLE_ERROR;
use crate::util::{AfArray, MutAfArray};
use crate::util::{ComplexFloating, FloatingPoint, HasAfEnum, RealFloating};
#[allow(dead_code)]
extern "C" {
fn af_approx1(
out: MutAfArray,
inp: AfArray,
pos: AfArray,
method: c_int,
off_grid: c_float,
) -> c_int;
fn af_approx2(
out: MutAfArray,
inp: AfArray,
pos0: AfArray,
pos1: AfArray,
method: c_int,
off_grid: c_float,
) -> c_int;
fn af_set_fft_plan_cache_size(cache_size: size_t) -> c_int;
fn af_fft(out: MutAfArray, arr: AfArray, nfac: c_double, odim0: c_longlong) -> c_int;
fn af_fft2(
out: MutAfArray,
arr: AfArray,
nfac: c_double,
odim0: c_longlong,
odim1: c_longlong,
) -> c_int;
fn af_fft3(
out: MutAfArray,
arr: AfArray,
nfac: c_double,
odim0: c_longlong,
odim1: c_longlong,
odim2: c_longlong,
) -> c_int;
fn af_ifft(out: MutAfArray, arr: AfArray, nfac: c_double, odim0: c_longlong) -> c_int;
fn af_ifft2(
out: MutAfArray,
arr: AfArray,
nfac: c_double,
odim0: c_longlong,
odim1: c_longlong,
) -> c_int;
fn af_ifft3(
out: MutAfArray,
arr: AfArray,
nfac: c_double,
odim0: c_longlong,
odim1: c_longlong,
odim2: c_longlong,
) -> c_int;
fn af_fft_inplace(arr: AfArray, nfac: c_double) -> c_int;
fn af_fft2_inplace(arr: AfArray, nfac: c_double) -> c_int;
fn af_fft3_inplace(arr: AfArray, nfac: c_double) -> c_int;
fn af_ifft_inplace(arr: AfArray, nfac: c_double) -> c_int;
fn af_ifft2_inplace(arr: AfArray, nfac: c_double) -> c_int;
fn af_ifft3_inplace(arr: AfArray, nfac: c_double) -> c_int;
fn af_fft_r2c(out: MutAfArray, arr: AfArray, nfac: c_double, pad0: c_longlong) -> c_int;
fn af_fft2_r2c(
out: MutAfArray,
arr: AfArray,
nfac: c_double,
pad0: c_longlong,
pad1: c_longlong,
) -> c_int;
fn af_fft3_r2c(
out: MutAfArray,
arr: AfArray,
nfac: c_double,
pad0: c_longlong,
pad1: c_longlong,
pad2: c_longlong,
) -> c_int;
fn af_fft_c2r(out: MutAfArray, input: AfArray, nfac: c_double, is_odd: c_int) -> c_int;
fn af_fft2_c2r(out: MutAfArray, input: AfArray, nfac: c_double, is_odd: c_int) -> c_int;
fn af_fft3_c2r(out: MutAfArray, input: AfArray, nfac: c_double, is_odd: c_int) -> c_int;
fn af_convolve1(out: MutAfArray, s: AfArray, f: AfArray, m: c_uint, d: c_uint) -> c_int;
fn af_convolve2(out: MutAfArray, s: AfArray, f: AfArray, m: c_uint, d: c_uint) -> c_int;
fn af_convolve3(out: MutAfArray, s: AfArray, f: AfArray, m: c_uint, d: c_uint) -> c_int;
fn af_convolve2_sep(o: MutAfArray, c: AfArray, r: AfArray, s: AfArray, m: c_uint) -> c_int;
fn af_fft_convolve1(out: MutAfArray, s: AfArray, f: AfArray, m: c_uint) -> c_int;
fn af_fft_convolve2(out: MutAfArray, s: AfArray, f: AfArray, m: c_uint) -> c_int;
fn af_fft_convolve3(out: MutAfArray, s: AfArray, f: AfArray, m: c_uint) -> c_int;
fn af_fir(out: MutAfArray, b: AfArray, x: AfArray) -> c_int;
fn af_iir(out: MutAfArray, b: AfArray, a: AfArray, x: AfArray) -> c_int;
}
#[allow(unused_mut)]
pub fn approx1<T, P>(
input: &Array<T>,
pos: &Array<P>,
method: InterpType,
off_grid: f32,
) -> Array<T>
where
T: HasAfEnum + FloatingPoint,
P: HasAfEnum + RealFloating,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_approx1(
&mut temp as MutAfArray,
input.get() as AfArray,
pos.get() as AfArray,
method as c_int,
off_grid as c_float,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
#[allow(unused_mut)]
pub fn approx2<T, P>(
input: &Array<T>,
pos0: &Array<P>,
pos1: &Array<P>,
method: InterpType,
off_grid: f32,
) -> Array<T>
where
T: HasAfEnum + FloatingPoint,
P: HasAfEnum + RealFloating,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_approx2(
&mut temp as MutAfArray,
input.get() as AfArray,
pos0.get() as AfArray,
pos1.get() as AfArray,
method as c_int,
off_grid as c_float,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn set_fft_plan_cache_size(cache_size: usize) {
unsafe {
let err_val = af_set_fft_plan_cache_size(cache_size as size_t);
HANDLE_ERROR(AfError::from(err_val));
}
}
#[allow(unused_mut)]
pub fn fft<T>(input: &Array<T>, norm_factor: f64, odim0: i64) -> Array<T::ComplexOutType>
where
T: HasAfEnum + FloatingPoint,
<T as HasAfEnum>::ComplexOutType: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fft(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
odim0 as c_longlong,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
#[allow(unused_mut)]
pub fn fft2<T>(
input: &Array<T>,
norm_factor: f64,
odim0: i64,
odim1: i64,
) -> Array<T::ComplexOutType>
where
T: HasAfEnum + FloatingPoint,
<T as HasAfEnum>::ComplexOutType: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fft2(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
odim0 as c_longlong,
odim1 as c_longlong,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
#[allow(unused_mut)]
pub fn fft3<T>(
input: &Array<T>,
norm_factor: f64,
odim0: i64,
odim1: i64,
odim2: i64,
) -> Array<T::ComplexOutType>
where
T: HasAfEnum + FloatingPoint,
<T as HasAfEnum>::ComplexOutType: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fft3(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
odim0 as c_longlong,
odim1 as c_longlong,
odim2 as c_longlong,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
#[allow(unused_mut)]
pub fn ifft<T>(input: &Array<T>, norm_factor: f64, odim0: i64) -> Array<T::ComplexOutType>
where
T: HasAfEnum + FloatingPoint,
<T as HasAfEnum>::ComplexOutType: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_ifft(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
odim0 as c_longlong,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
#[allow(unused_mut)]
pub fn ifft2<T>(
input: &Array<T>,
norm_factor: f64,
odim0: i64,
odim1: i64,
) -> Array<T::ComplexOutType>
where
T: HasAfEnum + FloatingPoint,
<T as HasAfEnum>::ComplexOutType: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_ifft2(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
odim0 as c_longlong,
odim1 as c_longlong,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
#[allow(unused_mut)]
pub fn ifft3<T>(
input: &Array<T>,
norm_factor: f64,
odim0: i64,
odim1: i64,
odim2: i64,
) -> Array<T::ComplexOutType>
where
T: HasAfEnum + FloatingPoint,
<T as HasAfEnum>::ComplexOutType: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_ifft3(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
odim0 as c_longlong,
odim1 as c_longlong,
odim2 as c_longlong,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
macro_rules! conv_func_def {
($doc_str: expr, $fn_name:ident, $ffi_name: ident) => {
#[doc=$doc_str]
#[allow(unused_mut)]
pub fn $fn_name<T, F>(
signal: &Array<T>,
filter: &Array<F>,
mode: ConvMode,
domain: ConvDomain,
) -> Array<T>
where
T: HasAfEnum,
F: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = $ffi_name(
&mut temp as MutAfArray,
signal.get() as AfArray,
filter.get() as AfArray,
mode as c_uint,
domain as c_uint,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
};
}
conv_func_def!("1d convolution", convolve1, af_convolve1);
conv_func_def!("2d convolution", convolve2, af_convolve2);
conv_func_def!("3d convolution", convolve3, af_convolve3);
#[allow(unused_mut)]
pub fn convolve2_sep<T, F>(
cfilt: &Array<F>,
rfilt: &Array<F>,
signal: &Array<T>,
mode: ConvMode,
) -> Array<T>
where
T: HasAfEnum,
F: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_convolve2_sep(
&mut temp as MutAfArray,
cfilt.get() as AfArray,
rfilt.get() as AfArray,
signal.get() as AfArray,
mode as c_uint,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
macro_rules! fft_conv_func_def {
($doc_str: expr, $fn_name:ident, $ffi_name: ident) => {
#[doc=$doc_str]
#[allow(unused_mut)]
pub fn $fn_name<T, F>(signal: &Array<T>, filter: &Array<F>, mode: ConvMode) -> Array<T>
where
T: HasAfEnum,
F: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = $ffi_name(
&mut temp as MutAfArray,
signal.get() as AfArray,
filter.get() as AfArray,
mode as c_uint,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
};
}
fft_conv_func_def!(
"1d convolution using fast-fourier transform",
fft_convolve1,
af_fft_convolve1
);
fft_conv_func_def!(
"2d convolution using fast-fourier transform",
fft_convolve2,
af_fft_convolve2
);
fft_conv_func_def!(
"3d convolution using fast-fourier transform",
fft_convolve3,
af_fft_convolve3
);
#[allow(unused_mut)]
pub fn fir<B, X>(b: &Array<B>, x: &Array<X>) -> Array<X>
where
B: HasAfEnum,
X: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fir(
&mut temp as MutAfArray,
b.get() as AfArray,
x.get() as AfArray,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
#[allow(unused_mut)]
pub fn iir<T: HasAfEnum>(b: &Array<T>, a: &Array<T>, x: &Array<T>) -> Array<T> {
let mut temp: i64 = 0;
unsafe {
let err_val = af_iir(
&mut temp as MutAfArray,
b.get() as AfArray,
a.get() as AfArray,
x.get() as AfArray,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn fft_inplace<T>(input: &mut Array<T>, norm_factor: f64)
where
T: HasAfEnum + ComplexFloating,
{
unsafe {
let err_val = af_fft_inplace(input.get() as AfArray, norm_factor as c_double);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn fft2_inplace<T>(input: &mut Array<T>, norm_factor: f64)
where
T: HasAfEnum + ComplexFloating,
{
unsafe {
let err_val = af_fft2_inplace(input.get() as AfArray, norm_factor as c_double);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn fft3_inplace<T>(input: &mut Array<T>, norm_factor: f64)
where
T: HasAfEnum + ComplexFloating,
{
unsafe {
let err_val = af_fft3_inplace(input.get() as AfArray, norm_factor as c_double);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn ifft_inplace<T>(input: &mut Array<T>, norm_factor: f64)
where
T: HasAfEnum + ComplexFloating,
{
unsafe {
let err_val = af_ifft_inplace(input.get() as AfArray, norm_factor as c_double);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn ifft2_inplace<T>(input: &mut Array<T>, norm_factor: f64)
where
T: HasAfEnum + ComplexFloating,
{
unsafe {
let err_val = af_ifft2_inplace(input.get() as AfArray, norm_factor as c_double);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn ifft3_inplace<T>(input: &mut Array<T>, norm_factor: f64)
where
T: HasAfEnum + ComplexFloating,
{
unsafe {
let err_val = af_ifft3_inplace(input.get() as AfArray, norm_factor as c_double);
HANDLE_ERROR(AfError::from(err_val));
}
}
pub fn fft_r2c<T>(input: &Array<T>, norm_factor: f64, pad0: i64) -> Array<Complex<T>>
where
T: HasAfEnum + RealFloating,
Complex<T>: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fft_r2c(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
pad0 as c_longlong,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn fft2_r2c<T>(input: &Array<T>, norm_factor: f64, pad0: i64, pad1: i64) -> Array<Complex<T>>
where
T: HasAfEnum + RealFloating,
Complex<T>: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fft2_r2c(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
pad0 as c_longlong,
pad1 as c_longlong,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn fft3_r2c<T>(
input: &Array<T>,
norm_factor: f64,
pad0: i64,
pad1: i64,
pad2: i64,
) -> Array<Complex<T>>
where
T: HasAfEnum + RealFloating,
Complex<T>: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fft3_r2c(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
pad0 as c_longlong,
pad1 as c_longlong,
pad2 as c_longlong,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn fft_c2r<T>(input: &Array<T>, norm_factor: f64, is_odd: bool) -> Array<T::BaseType>
where
T: HasAfEnum + ComplexFloating,
<T as HasAfEnum>::BaseType: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fft_c2r(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
is_odd as c_int,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn fft2_c2r<T>(input: &Array<T>, norm_factor: f64, is_odd: bool) -> Array<T::BaseType>
where
T: HasAfEnum + ComplexFloating,
<T as HasAfEnum>::BaseType: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fft2_c2r(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
is_odd as c_int,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn fft3_c2r<T>(input: &Array<T>, norm_factor: f64, is_odd: bool) -> Array<T::BaseType>
where
T: HasAfEnum + ComplexFloating,
<T as HasAfEnum>::BaseType: HasAfEnum,
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_fft3_c2r(
&mut temp as MutAfArray,
input.get() as AfArray,
norm_factor as c_double,
is_odd as c_int,
);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}