#![cfg_attr(feature = "use_simd", feature(portable_simd))]
#![cfg_attr(feature = "use_simd", feature(stdarch_x86_avx512))]
extern crate arrayvec;
#[cfg(feature = "use_gpu")]
extern crate clfft;
#[cfg(feature = "std")]
extern crate crossbeam;
#[cfg(feature = "std")]
#[macro_use]
extern crate lazy_static;
#[cfg(feature = "std")]
extern crate linreg;
extern crate num_complex;
#[cfg(feature = "std")]
extern crate num_cpus;
extern crate num_traits;
#[cfg(feature = "use_gpu")]
extern crate ocl;
extern crate rustfft;
#[macro_use]
mod simd_extensions;
pub mod conv_types;
pub mod meta;
mod multicore_support;
mod vector_types;
pub mod window_functions;
pub use crate::multicore_support::print_calibration;
pub use crate::multicore_support::MultiCoreSettings;
pub use crate::vector_types::*;
mod gpu_support;
mod inline_vector;
use crate::numbers::*;
use std::ops::Range;
pub mod numbers {
use crate::gpu_support::{Gpu32, Gpu64, GpuFloat, GpuRegTrait};
use crate::simd_extensions;
use crate::simd_extensions::*;
pub use num_complex::Complex;
use num_traits;
pub use num_traits::Float;
pub use num_traits::Num;
pub use num_traits::One;
use rustfft;
use std::fmt::Debug;
pub trait DspNumber:
Num
+ Copy
+ Clone
+ Send
+ Sync
+ ToSimd
+ Debug
+ num_traits::Signed
+ num_traits::FromPrimitive
+ rustfft::FftNum
+ 'static
{
}
impl<T> DspNumber for T where
T: Num
+ Copy
+ Clone
+ Send
+ Sync
+ ToSimd
+ Debug
+ num_traits::Signed
+ num_traits::FromPrimitive
+ rustfft::FftNum
+ 'static
{
}
pub trait ToSimd: Sized + Sync + Send {
type RegFallback: SimdGeneric<Self>;
type RegSse: SimdGeneric<Self>;
type RegAvx: SimdGeneric<Self>;
type RegAvx512: SimdGeneric<Self>;
type GpuReg: GpuRegTrait;
}
impl ToSimd for f32 {
type RegFallback = simd_extensions::fallback::f32x4;
#[cfg(all(feature = "use_sse2", target_feature = "sse2"))]
type RegSse = simd_extensions::sse::f32x4;
#[cfg(not(all(feature = "use_sse2", target_feature = "sse2")))]
type RegSse = simd_extensions::fallback::f32x4;
#[cfg(all(feature = "use_avx2"))]
type RegAvx = simd_extensions::avx::f32x8;
#[cfg(not(all(feature = "use_avx2")))]
type RegAvx = simd_extensions::fallback::f32x4;
#[cfg(feature = "use_avx512")]
type RegAvx512 = simd_extensions::avx512::f32x16;
#[cfg(not(feature = "use_avx512"))]
type RegAvx512 = simd_extensions::fallback::f32x4;
type GpuReg = Gpu32;
}
impl ToSimd for f64 {
type RegFallback = simd_extensions::fallback::f64x2;
#[cfg(all(feature = "use_sse2", target_feature = "sse2"))]
type RegSse = simd_extensions::sse::f64x2;
#[cfg(not(all(feature = "use_sse2", target_feature = "sse2")))]
type RegSse = simd_extensions::fallback::f64x2;
#[cfg(all(feature = "use_avx2", target_feature = "avx2"))]
type RegAvx = simd_extensions::avx::f64x4;
#[cfg(not(all(feature = "use_avx2", target_feature = "avx2")))]
type RegAvx = simd_extensions::fallback::f64x2;
#[cfg(feature = "use_avx512")]
type RegAvx512 = simd_extensions::avx512::f64x8;
#[cfg(not(feature = "use_avx512"))]
type RegAvx512 = simd_extensions::fallback::f64x2;
type GpuReg = Gpu64;
}
pub trait RealNumber: Float + DspNumber + GpuFloat + num_traits::FloatConst {}
impl<T> RealNumber for T where T: Float + DspNumber + GpuFloat + num_traits::FloatConst {}
pub trait Zero {
fn zero() -> Self;
}
impl<T> Zero for T
where
T: DspNumber,
{
fn zero() -> Self {
<Self as num_traits::Zero>::zero()
}
}
impl<T> Zero for Complex<T>
where
T: DspNumber,
{
fn zero() -> Self {
<Self as num_traits::Zero>::zero()
}
}
}
fn transmute_slice<S, D>(source: &[S]) -> &[D] {
let len = get_target_slice_len::<S, D>(source);
unsafe {
let trans: &[D] = &*(source as *const [S] as *const [D]);
std::slice::from_raw_parts(trans.as_ptr(), len)
}
}
fn transmute_slice_mut<S, D>(source: &mut [S]) -> &mut [D] {
let len = get_target_slice_len::<S, D>(source);
unsafe {
let trans: &mut [D] = &mut *(source as *mut [S] as *mut [D]);
std::slice::from_raw_parts_mut(trans.as_mut_ptr(), len)
}
}
fn get_target_slice_len<S, D>(source: &[S]) -> usize {
let to_larger_type = std::mem::size_of::<D>() >= std::mem::size_of::<S>();
if to_larger_type {
assert_eq!(std::mem::size_of::<D>() % std::mem::size_of::<S>(), 0);
let ratio = std::mem::size_of::<D>() / std::mem::size_of::<S>();
assert_eq!(source.len() % ratio, 0);
source.len() / ratio
} else {
assert_eq!(std::mem::size_of::<S>() % std::mem::size_of::<D>(), 0);
let ratio = std::mem::size_of::<S>() / std::mem::size_of::<D>();
source.len() * ratio
}
}
fn array_to_complex<T>(array: &[T]) -> &[Complex<T>] {
transmute_slice(array)
}
fn array_to_complex_mut<T>(array: &mut [T]) -> &mut [Complex<T>] {
transmute_slice_mut(array)
}
fn memcpy<T: Copy>(data: &mut [T], from: Range<usize>, to: usize) {
use std::ptr::copy;
assert!(from.start <= from.end);
assert!(from.end <= data.len());
assert!(to <= data.len() - (from.end - from.start));
unsafe {
let ptr = data.as_mut_ptr();
copy(ptr.add(from.start), ptr.add(to), from.end - from.start)
}
}
fn memzero<T: Copy>(data: &mut [T], range: Range<usize>) {
use std::ptr::write_bytes;
assert!(range.start <= range.end);
assert!(range.end <= data.len());
unsafe {
let ptr = data.as_mut_ptr();
write_bytes(ptr.add(range.start), 0, range.end - range.start);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::simd_extensions::Simd;
#[test]
fn to_simd_test() {
let reg = <f32 as ToSimd>::RegFallback::splat(1.0);
let sum = reg.sum_real();
assert!(sum > 0.0);
}
}