11 个版本

0.4.1 2024年2月7日
0.4.0 2023年8月29日
0.3.5 2023年1月12日
0.3.2 2022年12月26日
0.1.0 2022年9月4日

#195 in 算法

Download history 147/week @ 2024-03-13 147/week @ 2024-03-20 121/week @ 2024-03-27 158/week @ 2024-04-03 170/week @ 2024-04-10 140/week @ 2024-04-17 137/week @ 2024-04-24 127/week @ 2024-05-01 133/week @ 2024-05-08 122/week @ 2024-05-15 96/week @ 2024-05-22 111/week @ 2024-05-29 174/week @ 2024-06-05 241/week @ 2024-06-12 198/week @ 2024-06-19 166/week @ 2024-06-26

每月下载量 807
用于 fftconvolve

MIT/Apache

55KB
818

easyfft

一个 Rust 库 crate,提供数组切片的 FFT API。这个 crate 包装了 rustfftrealfft crate,它们在幕后处理繁重的工作。

easyfft 实际上做什么?

  • 为您在线程本地存储中管理 FftPlanner 和擦除缓冲区。
  • 在数组和切片上公开扩展特质,以便简洁和舒适地表达底层逻辑。
  • 数组上的实现使用类型检查在编译时验证信号大小。
  • 为您完成实值信号的尺寸计算,所以您不会出错。
  • 包装结构(RealDftDynRealDft),这会强制您调用正确的 real_ifft 版本。

示例

依赖于 nightly 的功能被注释掉了。

// NOTE: Only required for real arrays
// #![allow(incomplete_features)]
// #![feature(generic_const_exprs)]

use easyfft::prelude::*;
use easyfft::num_complex::Complex;

// Complex arrays
let complex_array = [Complex::new(1.0, 0.0); 100];
let complex_array_dft = complex_array.fft();
let _complex_array_dft_idft = complex_array_dft.ifft();

// Real to complex arrays
let real_array = [1.0; 100];
let _real_array_dft = real_array.fft();

// // Real arrays
// let real_array = [1.0; 100];
// let real_array_dft = real_array.real_fft();
// let _real_array_dft_idft = real_array_dft.real_ifft();

// Complex slices
let complex_slice: &[_] = &[Complex::new(1.0, 0.0); 100];
let complex_slice_dft = complex_slice.fft();
let _complex_slice_dft_idft = complex_slice_dft.ifft();

// Real to complex slices
let real_slice: &[_] = &[1.0; 100];
let _real_slice_dft = real_slice.fft();

// Real slices
let real_slice: &[_] = &[1.0; 100];
let real_slice_dft = real_slice.real_fft();
let _real_slice_dft_idft = real_slice_dft.real_ifft();

// In-place mutation on complex -> complex transforms
let mut complex_slice = [Complex::new(1.0, 0.0); 100];
complex_slice.fft_mut();
complex_slice.ifft_mut();
let mut complex_array = [Complex::new(1.0, 0.0); 100];
complex_array.fft_mut();
complex_array.ifft_mut();

当前限制

  • const-realfft 功能需要 nightly 编译器,因为它依赖于 generic_const_exprs 功能。
  • 没有为复数到实数或实数到复数的转换提供就地变异方法。
  • easyfft 将 FftPlanner 和擦除缓冲区存储在线程本地存储中。这意味着它不适用于为每个 FFT 操作启动新线程的应用程序。它会工作,但会降低性能。

⚠️ 缩放 ⚠️

类似于 rustfftrealffteasyfft 并不重缩放输出!这是故意的,并且出于性能考虑。许多应用程序都会进行一次 fft,处理数据,然后在实际分析数据之前执行一次 ifft。两个归一化步骤(1/len().sqrt())可以合并为一步 1/len(),将昂贵的除法指令数量减半。

fallible 功能

DynRealDft 结构体有一些相关的操作可能会导致 panic。这是因为 Rust 语言在类型系统中无法编码切片长度的属性。如果 Rust 团队能够将 const generics 扩展到完全的 依赖类型,这可能会在未来成为可能。目前,我们只能使用数组,在这些数组中我们可以确保这些属性。如果你最关心的是安全性,我建议你退一步考虑,你是否真的需要用切片而不是数组来工作。许多应用程序可以在编译时知道它们信号的大小。你可以通过移除默认启用的 fallible 功能标志来退出这些可能引发 panic 的操作。

为什么使用预览全局导入?

我通常不喜欢全局导入,因为它使得代码更难推理。显式导入意味着你可以轻松地搜索项并查看它们来自哪个包。我相信有一个例外:特质。特质不允许你通过文本匹配来确定正在使用哪个特质以及它来自哪个包。由于它已经有点隐含且复杂,你可以利用单行导入所有特质的便利。

use easyfft::prelude::*;

因此,easyfft 只通过预览模块公开特质。

依赖项

~3.5–9.5MB
~77K SLoC