#![allow(clippy::excessive_precision)]
#![deny(clippy::unwrap_used)]
#![cfg_attr(
all(feature = "fcma", target_arch = "aarch64"),
feature(stdarch_neon_fcma)
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#[cfg(all(target_arch = "x86_64", feature = "avx"))]
mod avx;
mod complex_arith;
mod cwt_executor;
mod cwt_filter;
mod err;
mod factory;
mod freqs;
mod mla;
#[cfg(all(target_arch = "aarch64", feature = "neon"))]
mod neon;
mod sample;
mod scale_bounds;
mod scales;
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), feature = "sse"))]
mod sse;
mod wavelets;
use crate::factory::create_cwt;
use crate::freqs::scale_to_frequencies_impl;
pub use cwt_filter::CwtWavelet;
pub use err::ScaletError;
use num_complex::Complex;
use std::sync::Arc;
pub use wavelets::{CmhatWavelet, GaborWavelet, HhhatWavelet, MorletWavelet};
#[derive(Debug, Copy, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct CwtOptions {
pub scale_type: ScaleType,
pub nv: usize,
pub l1_norm: bool,
pub full_cache: bool,
}
impl Default for CwtOptions {
fn default() -> Self {
Self {
nv: 32,
scale_type: ScaleType::Log,
l1_norm: true,
full_cache: false,
}
}
}
pub trait CwtExecutor<T>
where
[Complex<T>]: ToOwned<Owned = Vec<Complex<T>>>,
{
fn execute(&self, input: &[T]) -> Result<ScaletFrameMut<'_, Complex<T>>, ScaletError>;
fn execute_with_scratch(
&self,
input: &[T],
into_frame: &mut ScaletFrameMut<'_, Complex<T>>,
scratch: &mut [Complex<T>],
) -> Result<(), ScaletError>;
fn execute_complex(
&self,
input: &[Complex<T>],
) -> Result<ScaletFrameMut<'_, Complex<T>>, ScaletError>;
fn execute_complex_with_scratch(
&self,
input: &[Complex<T>],
into: &mut ScaletFrameMut<'_, Complex<T>>,
scratch: &mut [Complex<T>],
) -> Result<(), ScaletError>;
fn length(&self) -> usize;
fn view_scales(&self) -> &[T];
fn scratch_length(&self) -> usize;
}
pub struct Scalet {}
impl Scalet {
pub fn make_morlet_f32(
length: usize,
options: CwtOptions,
) -> Result<Arc<dyn CwtExecutor<f32> + Send + Sync>, ScaletError> {
create_cwt(
Arc::new(MorletWavelet::default()),
length,
options.scale_type,
options,
)
}
pub fn make_morlet_f64(
length: usize,
options: CwtOptions,
) -> Result<Arc<dyn CwtExecutor<f64> + Send + Sync>, ScaletError> {
create_cwt(
Arc::new(MorletWavelet::default()),
length,
options.scale_type,
options,
)
}
pub fn make_cwt_f32(
wavelet: Arc<dyn CwtWavelet<f32> + Send + Sync>,
length: usize,
options: CwtOptions,
) -> Result<Arc<dyn CwtExecutor<f32> + Send + Sync>, ScaletError> {
create_cwt(wavelet, length, options.scale_type, options)
}
pub fn make_cwt_f64(
wavelet: Arc<dyn CwtWavelet<f64> + Send + Sync>,
length: usize,
options: CwtOptions,
) -> Result<Arc<dyn CwtExecutor<f64> + Send + Sync>, ScaletError> {
create_cwt(wavelet, length, options.scale_type, options)
}
pub fn scales_to_frequencies_f32(
wavelet: Arc<dyn CwtWavelet<f32> + Send + Sync>,
scales: &[f32],
filter_length: usize,
sampling_frequency: f32,
) -> Result<Vec<f32>, ScaletError> {
scale_to_frequencies_impl(wavelet, scales, sampling_frequency, filter_length)
}
pub fn scales_to_frequencies_f64(
wavelet: Arc<dyn CwtWavelet<f64> + Send + Sync>,
scales: &[f64],
filter_length: usize,
sampling_frequency: f64,
) -> Result<Vec<f64>, ScaletError> {
scale_to_frequencies_impl(wavelet, scales, sampling_frequency, filter_length)
}
}
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum ScaleType {
Log,
Linear,
}
pub struct ScaletFrameMut<'a, T>
where
[T]: ToOwned,
{
pub data: BufferStoreMut<'a, T>,
pub width: usize,
pub height: usize,
}
pub struct ScaletFrame<'a, T>
where
[T]: ToOwned,
{
pub data: std::borrow::Cow<'a, [T]>,
pub width: usize,
pub height: usize,
}
pub enum BufferStoreMut<'a, T> {
Borrowed(&'a mut [T]),
Owned(Vec<T>),
}
impl<T> BufferStoreMut<'_, T> {
#[allow(clippy::should_implement_trait)]
pub fn borrow(&self) -> &[T] {
match self {
Self::Borrowed(p_ref) => p_ref,
Self::Owned(vec) => vec,
}
}
#[allow(clippy::should_implement_trait)]
pub fn borrow_mut(&mut self) -> &mut [T] {
match self {
Self::Borrowed(p_ref) => p_ref,
Self::Owned(vec) => vec,
}
}
}