use std::ptr::NonNull;
#[doc(alias = "vDSP_Length")]
pub type Len = usize;
#[doc(alias = "vDSP_Stride")]
pub type Stride = isize;
#[inline]
fn with<R>(f: impl FnOnce(*mut R)) -> R {
let mut res = std::mem::MaybeUninit::uninit();
f(res.as_mut_ptr());
unsafe { res.assume_init() }
}
#[doc(alias = "FFTDirection")]
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[repr(i32)]
pub enum FftDirection {
Forward = 1,
Inverse = -1,
}
#[doc(alias = "FFTRadix")]
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[repr(i32)]
pub enum FftRadix {
_2 = 0,
_3 = 1,
_5 = 2,
}
#[doc(alias = "DSPComplex")]
#[doc(alias = "DSPDoubleComplex")]
#[derive(Debug, Default, Copy, Clone)]
#[repr(C)]
pub struct Complex<T> {
pub re: T,
pub im: T,
}
#[doc(alias = "DSPSplitComplex")]
#[doc(alias = "DSPDoubleSplitComplex")]
#[derive(Debug)]
#[repr(C)]
pub struct SplitComplex<'r, 'i, T> {
re: *mut T,
im: *mut T,
life_times: std::marker::PhantomData<(&'r T, &'i T)>,
}
impl<'r, 'i, T> SplitComplex<'r, 'i, T> {
pub fn new(re: &'r [T], im: &'i [T]) -> Self {
assert_eq!(re.len(), im.len());
Self {
re: re.as_ptr() as _,
im: im.as_ptr() as _,
life_times: std::marker::PhantomData,
}
}
pub fn new_mut(re: &'r mut [T], im: &'i mut [T]) -> Self {
assert_eq!(re.len(), im.len());
Self {
re: re.as_mut_ptr(),
im: im.as_mut_ptr(),
life_times: std::marker::PhantomData,
}
}
}
impl<'r, 'i> SplitComplex<'r, 'i, f32> {
pub fn new_f32(re: &'r mut [f32], im: &'i mut [f32]) -> Self {
assert_eq!(re.len(), im.len());
Self {
re: re.as_ptr() as _,
im: im.as_ptr() as _,
life_times: std::marker::PhantomData,
}
}
}
#[doc(alias = "OpaqueFFTSetup")]
#[doc(alias = "OpaqueFFTSetupD")]
#[repr(transparent)]
pub struct FftSetup<T>(std::ffi::c_void, std::marker::PhantomData<T>);
struct FftVt<T> {
transform_io: unsafe extern "C-unwind" fn(
_setup: *mut FftSetup<T>,
_c: *mut SplitComplex<T>,
_ic: Stride,
_log2n: Len,
_direction: FftDirection,
),
transform: unsafe extern "C-unwind" fn(
_setup: *mut FftSetup<T>,
_c: *const SplitComplex<T>,
_ic: Stride,
_buffer: *mut SplitComplex<T>,
_log2n: Len,
_direction: FftDirection,
),
zrip: unsafe extern "C-unwind" fn(
_setup: *mut FftSetup<T>,
_c: *const SplitComplex<T>,
_ic: Stride,
_log2n: Len,
_direction: FftDirection,
),
destroy: unsafe extern "C-unwind" fn(*mut FftSetup<T>),
}
impl FftVt<f32> {
pub fn new_f32() -> Self {
Self {
transform_io: _fft_zip_f32,
transform: _fft_zipt_f32,
zrip: _fft_zrip_f32,
destroy: _destroy_fftsetup_f32,
}
}
}
impl FftVt<f64> {
pub fn new_f64() -> Self {
Self {
transform_io: _fft_zip_f64,
transform: _fft_zipt_f64,
zrip: _fft_zrip_f64,
destroy: _destroy_fftsetup_f64,
}
}
}
pub struct Fft<T>(NonNull<FftSetup<T>>, FftVt<T>);
impl<T> Fft<T> {
#[inline]
pub fn zr_io(&mut self, re_io: &mut [T], im_io: &mut [T], direction: FftDirection) {
let log2n = (re_io.len() as f64).log2().ceil();
let mut split = SplitComplex::new_mut(re_io, im_io);
unsafe { (self.1.zrip)(self.0.as_mut(), &mut split, 1, log2n as _, direction) }
}
#[inline]
pub fn transform_io(&mut self, re_io: &mut [T], im_io: &mut [T], direction: FftDirection) {
let log2n = (re_io.len() as f64).log2().ceil();
let mut split = SplitComplex::new_mut(re_io, im_io);
unsafe { (self.1.transform_io)(self.0.as_mut(), &mut split, 1, log2n as _, direction) }
}
#[inline]
pub fn forward_io(&mut self, re_io: &mut [T], im_io: &mut [T]) {
self.transform_io(re_io, im_io, FftDirection::Forward)
}
#[inline]
pub fn inverse_io(&mut self, re_io: &mut [T], im_io: &mut [T]) {
self.transform_io(re_io, im_io, FftDirection::Inverse)
}
#[inline]
pub fn transform(
&mut self,
re: &mut [T],
im: &mut [T],
tmp_re: &mut [T],
tmp_im: &mut [T],
direction: FftDirection,
) {
let n = re.len();
let log2n = (n as f64).log2().ceil();
let c = SplitComplex::new_mut(re, im);
let mut buf = SplitComplex::new_mut(tmp_re, tmp_im);
unsafe { (self.1.transform)(self.0.as_mut(), &c, 1, &mut buf, log2n as _, direction) }
}
#[inline]
pub fn forward(&mut self, re: &mut [T], im: &mut [T], tmp_re: &mut [T], tmp_im: &mut [T]) {
self.transform(re, im, tmp_re, tmp_im, FftDirection::Forward)
}
#[inline]
pub fn inverse(&mut self, re: &mut [T], im: &mut [T], buf_re: &mut [T], buf_im: &mut [T]) {
self.transform(re, im, buf_re, buf_im, FftDirection::Inverse)
}
}
impl Fft<f32> {
#[inline]
pub fn new_f32(log2n: Len, radix: FftRadix) -> Option<Self> {
let setup = unsafe { _create_fftsetup_f32(log2n, radix) };
setup.map(|v| Self(v, FftVt::new_f32()))
}
}
impl Fft<f64> {
pub fn new_f64(log2n: Len, radix: FftRadix) -> Option<Self> {
let setup = unsafe { _create_fftsetup_f64(log2n, radix) };
setup.map(|v| Self(v, FftVt::new_f64()))
}
}
impl<T> Drop for Fft<T> {
fn drop(&mut self) {
unsafe { (self.1.destroy)(self.0.as_ptr()) };
}
}
#[doc(alias = "vDSP_vadd")]
#[inline]
pub fn add_f32(a: &[f32], b: &[f32], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _add_f32(a.as_ptr(), 1, b.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vaddD")]
#[inline]
pub fn add_f64(a: &[f64], b: &[f64], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _add_f64(a.as_ptr(), 1, b.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vaddi")]
#[inline]
pub fn add_i32(a: &[i32], b: &[i32], c: &mut [i32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _add_i32(a.as_ptr(), 1, b.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsub")]
#[inline]
pub fn sub_f32(a: &[f32], b: &[f32], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _sub_f32(b.as_ptr(), 1, a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsubD")]
#[inline]
pub fn sub_f64(a: &[f64], b: &[f64], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _sub_f64(b.as_ptr(), 1, a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsubi")]
#[inline]
pub fn sub_i32(a: &[i32], b: &[i32], c: &mut [i32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _sub_i32(b.as_ptr(), 1, a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vmul")]
#[inline]
pub fn mul_f32(a: &[f32], b: &[f32], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _mul_f32(a.as_ptr(), 1, b.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vmulD")]
#[inline]
pub fn mul_f64(a: &[f64], b: &[f64], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _mul_f64(a.as_ptr(), 1, b.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsub")]
#[inline]
pub fn div_f32(a: &[f32], b: &[f32], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _div_f32(b.as_ptr(), 1, a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsubD")]
#[inline]
pub fn div_f64(a: &[f64], b: &[f64], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _div_f64(b.as_ptr(), 1, a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsubi")]
#[inline]
pub fn div_i32(a: &[i32], b: &[i32], c: &mut [i32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _div_i32(b.as_ptr(), 1, a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsmul")]
#[inline]
pub fn smul_f32(a: &[f32], b: &f32, c: &mut [f32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _smul_f32(a.as_ptr(), 1, b, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsmulD")]
#[inline]
pub fn smul_f64(a: &[f64], b: &f64, c: &mut [f64]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _smul_f64(a.as_ptr(), 1, b, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsq")]
#[inline]
pub fn sq_f32(a: &[f32], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _sq_f32(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsqD")]
#[inline]
pub fn sq_f64(a: &[f64], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _sq_f64(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsq")]
#[inline]
pub fn sq_io_f32(io: &mut [f32]) {
let n = io.len();
unsafe { _sq_f32(io.as_ptr(), 1, io.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsqD")]
#[inline]
pub fn sq_io_f64(io: &mut [f64]) {
let n = io.len();
unsafe { _sq_f64(io.as_ptr(), 1, io.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vssq")]
#[inline]
pub fn ssq_f32(a: &[f32], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _ssq_f32(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vssqD")]
#[inline]
pub fn ssq_f64(a: &[f64], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _ssq_f64(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vssq")]
#[inline]
pub fn ssq_io_f32(io: &mut [f32]) {
let n = io.len();
unsafe { _ssq_f32(io.as_ptr(), 1, io.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vssqD")]
#[inline]
pub fn ssq_io_f64(io: &mut [f64]) {
let n = io.len();
unsafe { _ssq_f64(io.as_ptr(), 1, io.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_meanv")]
#[inline]
pub fn mean_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _mean_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_meanv")]
#[inline]
pub fn mean_stride_f32(a: &[f32], stride: usize) -> f32 {
let mut n = a.len();
if stride > 1 {
n /= stride;
}
with(|r| unsafe { _mean_f32(a.as_ptr(), stride as _, r, n) })
}
#[doc(alias = "vDSP_meanvD")]
#[inline]
pub fn mean_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _mean_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_measqv")]
#[inline]
pub fn mean_sq_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _meansq_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_measqvD")]
#[inline]
pub fn mean_sq_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _meansq_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_distancesq")]
pub fn distance_sq_f32(a: &[f32], b: &[f32]) -> f32 {
let n = a.len();
assert_eq!(n, b.len());
with(|r| unsafe { _distance_sq_f32(a.as_ptr(), 1, b.as_ptr(), 1, r, n) })
}
#[doc(alias = "vDSP_distancesqD")]
pub fn distance_sq_f64(a: &[f64], b: &[f64]) -> f64 {
let n = a.len();
assert_eq!(n, b.len());
with(|r| unsafe { _distance_sq_f64(a.as_ptr(), 1, b.as_ptr(), 1, r, n) })
}
#[doc(alias = "vDSP_dotpr")]
#[inline]
pub fn dotpr_f32(a: &[f32], b: &[f32]) -> f32 {
let n = a.len();
assert_eq!(n, b.len());
with(|r| unsafe { _dotpr_f32(a.as_ptr(), 1, b.as_ptr(), 1, r, n) })
}
#[doc(alias = "vDSP_dotprD")]
#[inline]
pub fn dotpr_f64(a: &[f64], b: &[f64]) -> f64 {
let n = a.len();
assert_eq!(n, b.len());
with(|r| unsafe { _dotpr_f64(a.as_ptr(), 1, b.as_ptr(), 1, r, n) })
}
#[doc(alias = "vDSP_vam")]
#[inline]
pub fn am_f32(a: &[f32], b: &[f32], c: &[f32], d: &mut [f32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
assert_eq!(n, d.len());
unsafe {
_am_f32(
a.as_ptr(),
1,
b.as_ptr(),
1,
c.as_ptr(),
1,
d.as_mut_ptr(),
1,
n,
)
}
}
#[doc(alias = "vDSP_vamD")]
#[inline]
pub fn am_f64(a: &[f64], b: &[f64], c: &[f64], d: &mut [f64]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
assert_eq!(n, d.len());
unsafe {
_am_f64(
a.as_ptr(),
1,
b.as_ptr(),
1,
c.as_ptr(),
1,
d.as_mut_ptr(),
1,
n,
)
}
}
#[doc(alias = "vDSP_vma")]
#[inline]
pub fn ma_f32(a: &[f32], b: &[f32], c: &[f32], d: &mut [f32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
assert_eq!(n, d.len());
unsafe {
_ma_f32(
a.as_ptr(),
1,
b.as_ptr(),
1,
c.as_ptr(),
1,
d.as_mut_ptr(),
1,
n,
)
}
}
#[doc(alias = "vDSP_vmaD")]
#[inline]
pub fn ma_f64(a: &[f64], b: &[f64], c: &[f64], d: &mut [f64]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
assert_eq!(n, d.len());
unsafe {
_ma_f64(
a.as_ptr(),
1,
b.as_ptr(),
1,
c.as_ptr(),
1,
d.as_mut_ptr(),
1,
n,
)
}
}
#[doc(alias = "vDSP_vdpsp")]
#[inline]
pub fn f64_f32(a: &[f64], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _f64_f32(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vspdp")]
#[inline]
pub fn f32_f64(a: &[f32], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _f32_f64(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vabs")]
#[inline]
pub fn abs_f32(a: &[f32], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _abs_f32(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vabs")]
#[inline]
pub fn abs_io_f32(io: &mut [f32]) {
let n = io.len();
unsafe { _abs_f32(io.as_ptr(), 1, io.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vabsD")]
#[inline]
pub fn abs_f64(a: &[f64], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _abs_f64(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vabsD")]
#[inline]
pub fn abs_io_f64(io: &mut [f64]) {
let n = io.len();
unsafe { _abs_f64(io.as_ptr(), 1, io.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vabsi")]
#[inline]
pub fn abs_i32(a: &[i32], c: &mut [i32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _abs_i32(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vabsi")]
#[inline]
pub fn abs_io_i32(io: &mut [i32]) {
let n = io.len();
unsafe { _abs_i32(io.as_ptr(), 1, io.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_veqvi")]
#[inline]
pub fn eqv_i32(a: &[i32], b: &[i32], c: &mut [i32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _eqv_i32(a.as_ptr(), 1, b.as_ptr(), 1, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vfill")]
#[inline]
pub fn fill_f32(a: &f32, c: &mut [f32]) {
let n = c.len();
unsafe { _fill_f32(a, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vfillD")]
#[inline]
pub fn fill_f64(a: &f64, c: &mut [f64]) {
let n = c.len();
unsafe { _fill_f64(a, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vfilli")]
#[inline]
pub fn fill_i32(a: &i32, c: &mut [i32]) {
let n = c.len();
unsafe { _fill_i32(a, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vclr")]
#[inline]
pub fn clr_f32(c: &mut [f32]) {
unsafe { _clr_f32(c.as_mut_ptr(), 1, c.len()) }
}
#[doc(alias = "vDSP_vclrD")]
#[inline]
pub fn clr_f64(c: &mut [f64]) {
unsafe { _clr_f64(c.as_mut_ptr(), 1, c.len()) }
}
#[doc(alias = "vDSP_vsadd")]
#[inline]
pub fn sadd_f32(a: &[f32], b: &f32, c: &mut [f32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _sadd_f32(a.as_ptr(), 1, b, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsaddD")]
#[inline]
pub fn sadd_f64(a: &[f64], b: &f64, c: &mut [f64]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _sadd_f64(a.as_ptr(), 1, b, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_vsaddD")]
#[inline]
pub fn sadd_i32(a: &[i32], b: &i32, c: &mut [i32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _sadd_i32(a.as_ptr(), 1, b, c.as_mut_ptr(), 1, n) }
}
#[doc(alias = "vDSP_sve")]
#[inline]
pub fn se_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _se_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_sve")]
#[inline]
pub fn se_stride_f32(a: &[f32], stride: usize) -> f32 {
let mut n = a.len();
if stride > 1 {
n /= stride;
}
with(|r| unsafe { _se_f32(a.as_ptr(), stride as _, r, n) })
}
#[doc(alias = "vDSP_sveD")]
#[inline]
pub fn se_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _se_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_sveD")]
#[inline]
pub fn se_stride_f64(a: &[f64], stride: usize) -> f64 {
let mut n = a.len();
if stride > 1 {
n /= stride;
}
with(|r| unsafe { _se_f64(a.as_ptr(), stride as _, r, n) })
}
#[doc(alias = "vDSP_svemg")]
#[inline]
pub fn semg_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _semg_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_svemgD")]
#[inline]
pub fn semg_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _semg_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_svesq")]
#[inline]
pub fn sesq_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _sesq_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_svesqD")]
#[inline]
pub fn sesq_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _sesq_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_svs")]
#[inline]
pub fn svs_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _svs_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_svsD")]
#[inline]
pub fn svs_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _svs_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_maxmgv")]
#[inline]
pub fn maxmg_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _maxmg_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_maxmgvD")]
#[inline]
pub fn maxmg_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _maxmg_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_minmgv")]
#[inline]
pub fn minmg_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _minmg_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_minmgvD")]
#[inline]
pub fn minmg_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _minmg_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_minv")]
#[inline]
pub fn min_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _min_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_minv")]
#[inline]
pub fn min_stride_f32(a: &[f32], stride: usize) -> f32 {
let mut n = a.len();
if stride > 1 {
n /= stride;
}
with(|r| unsafe { _min_f32(a.as_ptr(), stride as isize, r, n) })
}
#[doc(alias = "vDSP_minvD")]
#[inline]
pub fn min_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _min_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_maxv")]
#[inline]
pub fn max_f32(a: &[f32]) -> f32 {
with(|r| unsafe { _max_f32(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_maxv")]
#[inline]
pub fn max_stride_f32(a: &[f32], stride: usize) -> f32 {
let mut n = a.len();
if stride > 1 {
n /= stride;
}
with(|r| unsafe { _max_f32(a.as_ptr(), stride as isize, r, n) })
}
#[doc(alias = "vDSP_maxvD")]
#[inline]
pub fn max_f64(a: &[f64]) -> f64 {
with(|r| unsafe { _max_f64(a.as_ptr(), 1, r, a.len()) })
}
#[doc(alias = "vDSP_vgen")]
#[inline]
pub fn gen_f32(a: &f32, b: &f32, c: &mut [f32]) {
unsafe { _gen_f32(a, b, c.as_mut_ptr(), 1, c.len()) }
}
#[doc(alias = "vDSP_vgenD")]
#[inline]
pub fn gen_f64(a: &f64, b: &f64, c: &mut [f64]) {
unsafe { _gen_f64(a, b, c.as_mut_ptr(), 1, c.len()) }
}
#[doc(alias = "vDSP_vramp")]
#[inline]
pub fn ramp_f32(a: &f32, b: &f32, c: &mut [f32]) {
unsafe { _ramp_f32(a, b, c.as_mut_ptr(), 1, c.len()) }
}
#[doc(alias = "vDSP_vrampD")]
#[inline]
pub fn ramp_f64(a: &f64, b: &f64, c: &mut [f64]) {
unsafe { _ramp_f64(a, b, c.as_mut_ptr(), 1, c.len()) }
}
#[doc(alias = "vDSP_vrampmul")]
#[inline]
pub fn rampmul_f32(i: &[f32], start: &mut f32, step: &f32, o: &mut [f32]) {
let n = i.len();
assert_eq!(n, o.len());
unsafe { _rampmul_f32(i.as_ptr(), 1, start, step, o.as_mut_ptr(), 1, n) };
}
#[doc(alias = "vDSP_vrampmulD")]
#[inline]
pub fn rampmul_f64(i: &[f64], start: &mut f64, step: &f64, o: &mut [f64]) {
let n = i.len();
assert_eq!(n, o.len());
unsafe { _rampmul_f64(i.as_ptr(), 1, start, step, o.as_mut_ptr(), 1, n) };
}
#[doc(alias = "vDSP_vrampmul")]
#[inline]
pub fn rampmul_io_f32(io: &mut [f32], start: &mut f32, step: &f32) {
unsafe { _rampmul_f32(io.as_ptr(), 1, start, step, io.as_mut_ptr(), 1, io.len()) };
}
#[doc(alias = "vDSP_vrampmulD")]
#[inline]
pub fn rampmul_io_f64(io: &mut [f64], start: &mut f64, step: &f64) {
unsafe { _rampmul_f64(io.as_ptr(), 1, start, step, io.as_mut_ptr(), 1, io.len()) };
}
#[doc(alias = "vDSP_vrampmul2")]
#[inline]
pub fn rampmul2_f32(
i0: &[f32],
i1: &[f32],
start: &mut f32,
step: &f32,
o0: &mut [f32],
o1: &mut [f32],
) {
let n = i0.len();
assert_eq!(n, i1.len());
assert_eq!(n, o0.len());
assert_eq!(n, o1.len());
unsafe {
_rampmul2_f32(
i0.as_ptr(),
i1.as_ptr(),
1,
start,
step,
o0.as_mut_ptr(),
o1.as_mut_ptr(),
1,
n,
)
}
}
#[doc(alias = "vDSP_vrampmul2")]
#[inline]
pub fn rampmul2_io_f32(io0: &mut [f32], io1: &mut [f32], start: &mut f32, step: &f32) {
let n = io0.len();
assert_eq!(n, io1.len());
unsafe {
_rampmul2_f32(
io0.as_ptr(),
io1.as_ptr(),
1,
start,
step,
io0.as_mut_ptr(),
io1.as_mut_ptr(),
1,
n,
)
}
}
#[doc(alias = "vDSP_vrampmul2D")]
#[inline]
pub fn rampmul2_f64(
i0: &[f64],
i1: &[f64],
start: &mut f64,
step: &f64,
o0: &mut [f64],
o1: &mut [f64],
) {
let n = i0.len();
assert_eq!(n, i1.len());
assert_eq!(n, o0.len());
assert_eq!(n, o1.len());
unsafe {
_rampmul2_f64(
i0.as_ptr(),
i1.as_ptr(),
1,
start,
step,
o0.as_mut_ptr(),
o1.as_mut_ptr(),
1,
n,
)
}
}
#[doc(alias = "vDSP_vrampmul2D")]
#[inline]
pub fn rampmul2_io_f64(io0: &mut [f64], io1: &mut [f64], start: &mut f64, step: &f64) {
let n = io0.len();
assert_eq!(n, io1.len());
unsafe {
_rampmul2_f64(
io0.as_ptr(),
io1.as_ptr(),
1,
start,
step,
io0.as_mut_ptr(),
io1.as_mut_ptr(),
1,
n,
)
}
}
#[doc(alias = "vDSP_vneg")]
#[inline]
pub fn neg_f32(a: &[f32], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _neg_f32(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) };
}
#[doc(alias = "vDSP_vneg")]
#[inline]
pub fn neg_io_f32(io: &mut [f32]) {
let n = io.len();
unsafe { _neg_f32(io.as_ptr(), 1, io.as_mut_ptr(), 1, n) };
}
#[doc(alias = "vDSP_vnegD")]
#[inline]
pub fn neg_f64(a: &[f64], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _neg_f64(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) };
}
#[doc(alias = "vDSP_vnegD")]
#[inline]
pub fn neg_io_f64(io: &mut [f64]) {
let n = io.len();
unsafe { _neg_f64(io.as_ptr(), 1, io.as_mut_ptr(), 1, n) };
}
#[doc(alias = "vDSP_vtmerg")]
#[inline]
pub fn tmerg_f32(a: &[f32], b: &[f32], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _tmerg_f32(a.as_ptr(), 1, b.as_ptr(), 1, c.as_mut_ptr(), 1, n) };
}
#[doc(alias = "vDSP_vtmerg")]
#[inline]
pub fn tmerg_f64(a: &[f64], b: &[f64], c: &mut [f64]) {
let n = a.len();
assert_eq!(n, b.len());
assert_eq!(n, c.len());
unsafe { _tmerg_f64(a.as_ptr(), 1, b.as_ptr(), 1, c.as_mut_ptr(), 1, n) };
}
#[doc(alias = "vDSP_zaspec")]
#[inline]
pub fn zaspec_f32(a: &SplitComplex<f32>, c: &mut [f32]) {
unsafe { _zaspec_f32(a, c.as_mut_ptr(), c.len()) }
}
#[doc(alias = "vDSP_zaspecD")]
#[inline]
pub fn zaspec_f64(a: &SplitComplex<f64>, c: &mut [f64]) {
unsafe { _zaspec_f64(a, c.as_mut_ptr(), c.len()) }
}
#[doc(alias = "vDSP_ctoz")]
#[inline]
pub fn ctoz_f32(c: &[Complex<f32>], z_re: &mut [f32], z_im: &mut [f32]) {
let n = c.len();
assert_eq!(n, z_re.len());
assert_eq!(n, z_im.len());
unsafe {
let split = SplitComplex::new_mut(z_re, z_im);
_ctoz_f32(c.as_ptr(), 2, &split, 1, n)
}
}
#[doc(alias = "vDSP_ctoz")]
#[inline]
pub fn actoz_f32(a: &[f32], z_re: &mut [f32], z_im: &mut [f32]) {
let n = a.len() / 2;
assert_eq!(n, z_re.len());
assert_eq!(n, z_im.len());
let c = a.as_ptr() as *const Complex<f32>;
let split = SplitComplex::new_mut(z_re, z_im);
unsafe { _ctoz_f32(c, 2, &split, 1, n) }
}
#[doc(alias = "vDSP_ctozD")]
#[inline]
pub fn ctoz_f64(c: &[Complex<f64>], z_re: &mut [f64], z_im: &mut [f64]) {
let n = c.len();
assert_eq!(n, z_re.len());
assert_eq!(n, z_im.len());
unsafe {
let split = SplitComplex::new_mut(z_re, z_im);
_ctoz_f64(c.as_ptr(), 2, &split, 1, n)
}
}
#[doc(alias = "vDSP_ztoc")]
#[inline]
pub fn ztoc_f32(re: &[f32], im: &[f32], c: &mut [Complex<f32>]) {
let n = re.len();
assert_eq!(n, im.len());
assert_eq!(n, c.len());
let split = SplitComplex::new(re, im);
unsafe { _ztoc_f32(&split, 1, c.as_mut_ptr(), 2, n) };
}
#[doc(alias = "vDSP_ztocD")]
#[inline]
pub fn ztoc_f64(re: &[f64], im: &[f64], c: &mut [Complex<f64>]) {
let n = re.len();
assert_eq!(n, im.len());
assert_eq!(n, c.len());
let split = SplitComplex::new(re, im);
unsafe { _ztoc_f64(&split, 1, c.as_mut_ptr(), 2, n) };
}
#[doc(alias = "vDSP_vflt16")]
#[inline]
pub fn i16_f32(a: &[i16], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _i16_f32(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) };
}
#[doc(alias = "vDSP_vfltu16")]
#[inline]
pub fn u16_f32(a: &[u16], c: &mut [f32]) {
let n = a.len();
assert_eq!(n, c.len());
unsafe { _u16_f32(a.as_ptr(), 1, c.as_mut_ptr(), 1, n) };
}
#[link(name = "Accelerate", kind = "framework")]
unsafe extern "C-unwind" {
#[link_name = "vDSP_vadd"]
pub fn _add_f32(
__A: *const f32,
__IA: Stride,
__B: *const f32,
__IB: Stride,
__C: *mut f32,
__IC: Stride,
__N: Len,
);
#[link_name = "vDSP_vaddD"]
pub fn _add_f64(
__A: *const f64,
__IA: Stride,
__B: *const f64,
__IB: Stride,
__C: *mut f64,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vaddi")]
#[link_name = "vDSP_vaddi"]
pub fn _add_i32(
__A: *const i32,
__IA: Stride,
__B: *const i32,
__IB: Stride,
__C: *mut i32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vsub")]
#[link_name = "vDSP_vsub"]
pub fn _sub_f32(
__B: *const f32,
__IB: Stride,
__A: *const f32,
__IA: Stride,
__C: *mut f32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vsubD")]
#[link_name = "vDSP_vsubD"]
pub fn _sub_f64(
__B: *const f64,
__IB: Stride,
__A: *const f64,
__IA: Stride,
__C: *mut f64,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vsubi")]
#[link_name = "vDSP_vsubi"]
pub fn _sub_i32(
__B: *const i32,
__IB: Stride,
__A: *const i32,
__IA: Stride,
__C: *mut i32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vmul")]
#[link_name = "vDSP_vmul"]
pub fn _mul_f32(
__A: *const f32,
__IA: Stride,
__B: *const f32,
__IB: Stride,
__C: *mut f32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vmulD")]
#[link_name = "vDSP_vmulD"]
pub fn _mul_f64(
__A: *const f64,
__IA: Stride,
__B: *const f64,
__IB: Stride,
__C: *mut f64,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vdiv")]
#[link_name = "vDSP_vdiv"]
pub fn _div_f32(
__B: *const f32,
__IB: Stride,
__A: *const f32,
__IA: Stride,
__C: *mut f32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vdivD")]
#[link_name = "vDSP_vdivD"]
pub fn _div_f64(
__B: *const f64,
__IB: Stride,
__A: *const f64,
__IA: Stride,
__C: *mut f64,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vdivi")]
#[link_name = "vDSP_vdivi"]
pub fn _div_i32(
__B: *const i32,
__IB: Stride,
__A: *const i32,
__IA: Stride,
__C: *mut i32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vsmul")]
#[link_name = "vDSP_vsmul"]
pub fn _smul_f32(
__A: *const f32,
__IA: Stride,
__B: &f32,
__C: *mut f32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vsmulD")]
#[link_name = "vDSP_vsmulD"]
pub fn _smul_f64(
__A: *const f64,
__IA: Stride,
__B: &f64,
__C: *mut f64,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vsq")]
#[link_name = "vDSP_vsq"]
pub fn _sq_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vsqD")]
#[link_name = "vDSP_vsqD"]
pub fn _sq_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vssq")]
#[link_name = "vDSP_vssq"]
pub fn _ssq_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vssqD")]
#[link_name = "vDSP_vssqD"]
pub fn _ssq_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_meanv")]
#[link_name = "vDSP_meanv"]
pub fn _mean_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_meanvD")]
#[link_name = "vDSP_meanvD"]
pub fn _mean_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_measqv")]
#[link_name = "vDSP_measqv"]
pub fn _meansq_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_measqvD")]
#[link_name = "vDSP_measqvD"]
pub fn _meansq_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_distancesq")]
#[link_name = "vDSP_distancesq"]
pub fn _distance_sq_f32(
__A: *const f32,
__IA: Stride,
__B: *const f32,
__IB: Stride,
__C: *mut f32,
__N: Len,
);
#[doc(alias = "vDSP_distancesqD")]
#[link_name = "vDSP_distancesqD"]
pub fn _distance_sq_f64(
__A: *const f64,
__IA: Stride,
__B: *const f64,
__IB: Stride,
__C: *mut f64,
__N: Len,
);
#[doc(alias = "vDSP_dotpr")]
#[link_name = "vDSP_dotpr"]
pub fn _dotpr_f32(
__A: *const f32,
__IA: Stride,
__B: *const f32,
__IB: Stride,
__C: *mut f32,
__N: Len,
);
#[doc(alias = "vDSP_dotprD")]
#[link_name = "vDSP_dotprD"]
pub fn _dotpr_f64(
__A: *const f64,
__IA: Stride,
__B: *const f64,
__IB: Stride,
__C: *mut f64,
__N: Len,
);
#[doc(alias = "vDSP_vam")]
#[link_name = "vDSP_vam"]
pub fn _am_f32(
__A: *const f32,
__IA: Stride,
__B: *const f32,
__IB: Stride,
__C: *const f32,
__IC: Stride,
__D: *mut f32,
__ID: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vamD")]
#[link_name = "vDSP_vamD"]
pub fn _am_f64(
__A: *const f64,
__IA: Stride,
__B: *const f64,
__IB: Stride,
__C: *const f64,
__IC: Stride,
__D: *mut f64,
__ID: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vma")]
#[link_name = "vDSP_vma"]
pub fn _ma_f32(
__A: *const f32,
__IA: Stride,
__B: *const f32,
__IB: Stride,
__C: *const f32,
__IC: Stride,
__D: *mut f32,
__ID: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vmaD")]
#[link_name = "vDSP_vmaD"]
pub fn _ma_f64(
__A: *const f64,
__IA: Stride,
__B: *const f64,
__IB: Stride,
__C: *const f64,
__IC: Stride,
__D: *mut f64,
__ID: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vdpsp")]
#[link_name = "vDSP_vdpsp"]
pub fn _f64_f32(__A: *const f64, __IA: Stride, __C: *mut f32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vspdp")]
#[link_name = "vDSP_vspdp"]
pub fn _f32_f64(__A: *const f32, __IA: Stride, __C: *mut f64, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vabs")]
#[link_name = "vDSP_vabs"]
pub fn _abs_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vabsD")]
#[link_name = "vDSP_vabsD"]
pub fn _abs_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vabsi")]
#[link_name = "vDSP_vabsi"]
pub fn _abs_i32(__A: *const i32, __IA: Stride, __C: *mut i32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_veqvi")]
#[link_name = "vDSP_veqvi"]
pub fn _eqv_i32(
__A: *const i32,
__IA: Stride,
__B: *const i32,
__IB: Stride,
__C: *mut i32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vfill")]
#[link_name = "vDSP_vfill"]
pub fn _fill_f32(__A: &f32, __C: *mut f32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vfillD")]
#[link_name = "vDSP_vfillD"]
pub fn _fill_f64(__A: &f64, __C: *mut f64, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vfilli")]
#[link_name = "vDSP_vfilli"]
pub fn _fill_i32(__A: &i32, __C: *mut i32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vclr")]
#[link_name = "vDSP_vclr"]
pub fn _clr_f32(__C: *mut f32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vclrD")]
#[link_name = "vDSP_vclrD"]
pub fn _clr_f64(__C: *mut f64, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vsadd")]
#[link_name = "vDSP_vsadd"]
pub fn _sadd_f32(
__A: *const f32,
__IA: Stride,
__B: &f32,
__C: *mut f32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vsaddD")]
#[link_name = "vDSP_vsaddD"]
pub fn _sadd_f64(
__A: *const f64,
__IA: Stride,
__B: &f64,
__C: *mut f64,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vsaddi")]
#[link_name = "vDSP_vsaddi"]
pub fn _sadd_i32(
__A: *const i32,
__IA: Stride,
__B: &i32,
__C: *mut i32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_sve")]
#[link_name = "vDSP_sve"]
pub fn _se_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_sveD")]
#[link_name = "vDSP_sveD"]
pub fn _se_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_svemg")]
#[link_name = "vDSP_svemg"]
pub fn _semg_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_svemgD")]
#[link_name = "vDSP_svemgD"]
pub fn _semg_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_svesq")]
#[link_name = "vDSP_svesq"]
pub fn _sesq_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_svesqD")]
#[link_name = "vDSP_svesqD"]
pub fn _sesq_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_svs")]
#[link_name = "vDSP_svs"]
pub fn _svs_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_svsD")]
#[link_name = "vDSP_svsD"]
pub fn _svs_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_maxmgv")]
#[link_name = "vDSP_maxmgv"]
pub fn _maxmg_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_maxmgvD")]
#[link_name = "vDSP_maxmgvD"]
pub fn _maxmg_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_minmgv")]
#[link_name = "vDSP_minmgv"]
pub fn _minmg_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_minmgvD")]
#[link_name = "vDSP_minmgvD"]
pub fn _minmg_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_maxv")]
#[link_name = "vDSP_maxv"]
pub fn _max_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_maxvD")]
#[link_name = "vDSP_maxvD"]
pub fn _max_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_minv")]
#[link_name = "vDSP_minv"]
pub fn _min_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_minvD")]
#[link_name = "vDSP_minvD"]
pub fn _min_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_vgen")]
#[link_name = "vDSP_vgen"]
pub fn _gen_f32(__A: &f32, __B: &f32, __C: *mut f32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vgenD")]
#[link_name = "vDSP_vgenD"]
pub fn _gen_f64(__A: &f64, __B: &f64, __C: *mut f64, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vramp")]
#[link_name = "vDSP_vramp"]
pub fn _ramp_f32(__A: &f32, __B: &f32, __C: *mut f32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vrampD")]
#[link_name = "vDSP_vrampD"]
pub fn _ramp_f64(__A: &f64, __B: &f64, __C: *mut f64, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vrampmul")]
#[link_name = "vDSP_vrampmul"]
pub fn _rampmul_f32(
__I: *const f32,
__IS: Stride,
__Start: &mut f32,
__Step: &f32,
__O: *mut f32,
__OS: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vrampmulD")]
#[link_name = "vDSP_vrampmulD"]
pub fn _rampmul_f64(
__I: *const f64,
__IS: Stride,
__Start: &mut f64,
__Step: &f64,
__O: *mut f64,
__OS: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vrampmul2")]
#[link_name = "vDSP_vrampmul2"]
pub fn _rampmul2_f32(
__I0: *const f32,
__I1: *const f32,
__IS: Stride,
__Start: &mut f32,
__Step: &f32,
__O0: *mut f32,
__O1: *mut f32,
__OS: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vrampmul2D")]
#[link_name = "vDSP_vrampmul2D"]
pub fn _rampmul2_f64(
__I0: *const f64,
__I1: *const f64,
__IS: Stride,
__Start: &mut f64,
__Step: &f64,
__O0: *mut f64,
__O1: *mut f64,
__OS: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vneg")]
#[link_name = "vDSP_vneg"]
pub fn _neg_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vnegD")]
#[link_name = "vDSP_vnegD"]
pub fn _neg_f64(__A: *const f64, __IA: Stride, __C: *mut f64, __IC: Stride, __N: Len);
#[doc(alias = "vDSP_vtmerg")]
#[link_name = "vDSP_vtmerg"]
pub fn _tmerg_f32(
__A: *const f32,
__IA: Stride,
__B: *const f32,
__IB: Stride,
__C: *mut f32,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vtmergD")]
#[link_name = "vDSP_vtmergD"]
pub fn _tmerg_f64(
__A: *const f64,
__IA: Stride,
__B: *const f64,
__IB: Stride,
__C: *mut f64,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_ctoz")]
#[link_name = "vDSP_ctoz"]
pub fn _ctoz_f32(
__C: *const Complex<f32>,
__IC: Stride,
__Z: *const SplitComplex<f32>,
__IZ: Stride,
__N: Len,
);
#[doc(alias = "vDSP_ctozD")]
#[link_name = "vDSP_ctozD"]
pub fn _ctoz_f64(
__C: *const Complex<f64>,
__IC: Stride,
__Z: *const SplitComplex<f64>,
__IZ: Stride,
__N: Len,
);
#[doc(alias = "vDSP_ztoc")]
#[link_name = "vDSP_ztoc"]
pub fn _ztoc_f32(
__Z: *const SplitComplex<f32>,
__IZ: Stride,
__C: *mut Complex<f32>,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_ztocD")]
#[link_name = "vDSP_ztocD"]
pub fn _ztoc_f64(
__Z: *const SplitComplex<f64>,
__IZ: Stride,
__C: *mut Complex<f64>,
__IC: Stride,
__N: Len,
);
#[doc(alias = "vDSP_create_fftsetup")]
#[link_name = "vDSP_create_fftsetup"]
pub fn _create_fftsetup_f32(__Log2n: Len, __Radix: FftRadix) -> Option<NonNull<FftSetup<f32>>>;
#[doc(alias = "vDSP_create_fftsetupD")]
#[link_name = "vDSP_create_fftsetupD"]
pub fn _create_fftsetup_f64(__Log2n: Len, __Radix: FftRadix) -> Option<NonNull<FftSetup<f64>>>;
#[doc(alias = "vDSP_destroy_fftsetup")]
#[link_name = "vDSP_destroy_fftsetup"]
pub fn _destroy_fftsetup_f32(setup: *mut FftSetup<f32>);
#[doc(alias = "vDSP_destroy_fftsetupD")]
#[link_name = "vDSP_destroy_fftsetupD"]
pub fn _destroy_fftsetup_f64(setup: *mut FftSetup<f64>);
#[doc(alias = "vDSP_fft_zip")]
#[link_name = "vDSP_fft_zip"]
pub fn _fft_zip_f32(
__Setup: *mut FftSetup<f32>,
__C: *mut SplitComplex<f32>,
__IC: Stride,
__Log2N: Len,
__Direction: FftDirection,
);
#[doc(alias = "vDSP_fft_zipD")]
#[link_name = "vDSP_fft_zipD"]
pub fn _fft_zip_f64(
__Setup: *mut FftSetup<f64>,
__C: *mut SplitComplex<f64>,
__IC: Stride,
__Log2N: Len,
__Direction: FftDirection,
);
#[doc(alias = "vDSP_fft_zipt")]
#[link_name = "vDSP_fft_zipt"]
pub fn _fft_zipt_f32(
__Setup: *mut FftSetup<f32>,
__C: *const SplitComplex<f32>,
__IC: Stride,
__Buffer: *mut SplitComplex<f32>,
__Log2N: Len,
__Direction: FftDirection,
);
#[doc(alias = "vDSP_fft_ziptD")]
#[link_name = "vDSP_fft_ziptD"]
pub fn _fft_zipt_f64(
__Setup: *mut FftSetup<f64>,
__C: *const SplitComplex<f64>,
__IC: Stride,
__Buffer: *mut SplitComplex<f64>,
__Log2N: Len,
__Direction: FftDirection,
);
#[doc(alias = "vDSP_fft_zrip")]
#[link_name = "vDSP_fft_zrip"]
pub fn _fft_zrip_f32(
__Setup: *mut FftSetup<f32>,
__C: *const SplitComplex<f32>,
__IC: Stride,
__Log2N: Len,
__Direction: FftDirection,
);
#[doc(alias = "vDSP_fft_zripD")]
#[link_name = "vDSP_fft_zripD"]
pub fn _fft_zrip_f64(
__Setup: *mut FftSetup<f64>,
__C: *const SplitComplex<f64>,
__IC: Stride,
__Log2N: Len,
__Direction: FftDirection,
);
#[doc(alias = "vDSP_zaspec")]
#[link_name = "vDSP_zaspec"]
pub fn _zaspec_f32(__A: *const SplitComplex<f32>, __C: *mut f32, __N: Len);
#[doc(alias = "vDSP_zaspecD")]
#[link_name = "vDSP_zaspecD"]
pub fn _zaspec_f64(__A: *const SplitComplex<f64>, __C: *mut f64, __N: Len);
#[doc(alias = "vDSP_vflt16")]
#[link_name = "vDSP_vflt16"]
pub fn _i16_f32(__A: *const i16, __IA: Stride, __C: *mut f32, __CI: Stride, __N: Len);
#[doc(alias = "vDSP_vfltu16")]
#[link_name = "vDSP_vfltu16"]
pub fn _u16_f32(__A: *const u16, __IA: Stride, __C: *mut f32, __CI: Stride, __N: Len);
#[doc(alias = "vDSP_vdbcon")]
#[link_name = "vDSP_vdbcon"]
pub fn _dbcon_f32(
__A: *const f32,
__IA: Stride,
__B: *const f32,
__C: *mut f32,
__CI: Stride,
__N: Len,
__F: u32,
);
#[doc(alias = "vDSP_vdbconD")]
#[link_name = "vDSP_vdbconD"]
pub fn _dbcon_f64(
__A: *const f64,
__IA: Stride,
__B: *const f64,
__C: *mut f64,
__CI: Stride,
__N: Len,
__F: u32,
);
#[doc(alias = "vDSP_vclip")]
#[link_name = "vDSP_vclip"]
pub fn _clip_f32(
__A: *const f32,
__IA: Stride,
__B: *const f32,
__C: *const f32,
__D: *mut f32,
__ID: Stride,
__N: Len,
);
#[doc(alias = "vDSP_vclipD")]
#[link_name = "vDSP_vclipD"]
pub fn _clip_f64(
__A: *const f64,
__IA: Stride,
__B: *const f64,
__C: *const f64,
__D: *mut f64,
__ID: Stride,
__N: Len,
);
#[doc(alias = "vDSP_rmsqv")]
#[link_name = "vDSP_rmsqv"]
pub fn _rmsq_f32(__A: *const f32, __IA: Stride, __C: *mut f32, __N: Len);
}
#[cfg(test)]
mod tests {
use std::f32::consts::TAU;
use crate::vdsp::{self, SplitComplex};
#[test]
fn add_sub() {
const N: usize = 1_000;
let a = vec![1f32; N];
let b = vec![2f32; N];
let mut c = vec![0f32; N];
let mut r = vec![3f32; N];
vdsp::add_f32(&a, &b, &mut c);
assert_eq!(c, r);
vdsp::sub_f32(&c, &b, &mut r);
assert_eq!(r, a);
}
#[test]
fn basics() {
const N: usize = 1_000;
let a = vec![1f32; N];
let b = vec![2f32; N];
let mut c = vec![0f32; N];
let mut d = vec![0f32; N];
vdsp::mul_f32(&a, &b, &mut c);
assert_eq!(b, c);
vdsp::div_f32(&c, &b, &mut d);
assert_eq!(d, a);
vdsp::smul_f32(&a, &-0.5, &mut c);
assert_eq!(vec![-0.5f32; N], c);
vdsp::ssq_f32(&c, &mut d);
assert_eq!(vec![-0.25f32; N], d);
vdsp::sq_f32(&c, &mut d);
assert_eq!(vec![0.25f32; N], d);
let dist_sq = vdsp::distance_sq_f32(&a, &b);
assert_eq!(1000.0, dist_sq);
let dot_pr = vdsp::dotpr_f32(&a, &b);
assert_eq!(2000.0, dot_pr);
vdsp::am_f32(&a, &b, &c, &mut d);
assert_eq!(vec![-1.5f32; N], d);
vdsp::abs_f32(&d, &mut c);
assert_eq!(vec![1.5f32; N], c);
vdsp::fill_f32(&1.0, &mut c);
assert_eq!(a, c);
vdsp::clr_f32(&mut c);
assert_eq!(0.0, vdsp::se_f32(&c));
assert_eq!(0.0, vdsp::semg_f32(&c));
assert_eq!(0.0, vdsp::sesq_f32(&c));
assert_eq!(4.0 * N as f32, vdsp::sesq_f32(&b));
vdsp::sadd_f32(&c, &2.0, &mut d);
assert_eq!(b, d);
vdsp::gen_f32(&0.0, &1.0, &mut c[..3]);
assert_eq!(&[0.0, 0.5, 1.0], &c[..3]);
}
#[test]
fn stereo() {
let mut l = vec![10.0f32, 100.0, 10.0, 100.0, 10.0, 100.0, 10.0, 100.0];
let mut r = vec![10.0f32, 100.0, 10.0, 100.0, 10.0, 100.0, 10.0, 100.0];
vdsp::neg_io_f32(&mut r);
let mut start = 0.0f32;
let step = 1.0f32;
vdsp::rampmul2_io_f32(&mut l, &mut r, &mut start, &step);
assert_eq!(start, step * l.len() as f32);
assert_eq!(vdsp::maxmg_f32(&l), 700.0);
assert_eq!(vdsp::maxmg_f32(&r), 700.0);
assert_eq!(vdsp::minmg_f32(&l), 0.0);
assert_eq!(vdsp::minmg_f32(&r), 0.0);
assert_eq!(vdsp::min_f32(&l), 0.0);
assert_eq!(vdsp::min_f32(&r), -700.0);
}
fn synth_signal(freq_amp_pairs: &[(f32, f32)], len: usize) -> Vec<f32> {
let mut res = vec![0.0f32; len];
for i in 0..len {
let n_index = (i as f32) / ((len - 1) as f32);
res[i] = freq_amp_pairs.iter().fold(0.0f32, |acc, pair| {
println!("{pair:?}");
let r = acc + (n_index + pair.0 * TAU).sin() * pair.1;
println!("{r:?}");
r
});
}
res
}
#[test]
fn fft() {
let n = 32usize;
let signal = synth_signal(&[(2.0, 1.0)], n);
println!("{signal:?}");
let log2n: usize = n.ilog2() as _;
let mut ffi = vdsp::Fft::new_f32(log2n, vdsp::FftRadix::_5).unwrap();
let half_n: usize = n / 2;
let mut i_re = vec![0.0f32; half_n];
let mut i_im = vec![0.0f32; half_n];
vdsp::actoz_f32(&signal, &mut i_re, &mut i_im);
println!("{signal:?}");
ffi.zr_io(&mut i_re, &mut i_im, vdsp::FftDirection::Forward);
println!("{i_re:?}");
println!("{i_im:?}");
let mut spec = vec![0.0f32; half_n];
let split = SplitComplex::new(&i_re, &i_im);
vdsp::zaspec_f32(&split, &mut spec);
}
#[test]
fn ztoc() {
let re = [1.0, 2.0, 3.0];
let im = [4.0, 5.0, 6.0];
let mut c = vec![vdsp::Complex::<f32>::default(); 3];
vdsp::ztoc_f32(&re, &im, &mut c);
println!("{c:?}");
assert_eq!(c[0].re, 1.0);
assert_eq!(c[0].im, 4.0);
assert_eq!(c[1].re, 2.0);
assert_eq!(c[1].im, 5.0);
assert_eq!(c[2].re, 3.0);
assert_eq!(c[2].im, 6.0);
}
}