Skip to content

Commit

Permalink
Merge cbf9434 into 3f2840e
Browse files Browse the repository at this point in the history
  • Loading branch information
chalharu committed Sep 9, 2019
2 parents 3f2840e + cbf9434 commit d1868ee
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 244 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "chfft"
version = "0.3.0"
version = "0.3.1"
authors = ["Mitsuharu Seki <mitsu1986@gmail.com>"]
repository = "https://github.com/chalharu/chfft"
keywords = ["fft", "numerics", "dsp", "mathematics"]
Expand Down
198 changes: 65 additions & 133 deletions src/cfft1d.rs
Expand Up @@ -16,23 +16,8 @@ use num_traits::identities::{one, zero};
use num_traits::{cast, NumAssign};

enum WorkData<T> {
MixedRadix {
ids: Vec<usize>,
omega: Vec<Complex<T>>,
omega_back: Vec<Complex<T>>,
factors: Vec<Factor>,
ids_inplace: Option<Vec<usize>>,
},
ChirpZ {
level: usize,
ids: Vec<usize>,
omega: Vec<Complex<T>>,
omega_back: Vec<Complex<T>>,
src_omega: Vec<Complex<T>>,
rot_conj: Vec<Complex<T>>,
rot_ft: Vec<Complex<T>>,
pow2len_inv: T,
},
MixedRadix(mixed_radix::MixedRadixData<T>),
ChirpZ(chirpz::ChirpzData<T>),
None,
}

Expand Down Expand Up @@ -125,7 +110,7 @@ impl<T: Float + FloatConst + NumAssign> CFft1D<T> {

// 素因数分解
let factors = prime_factorization::prime_factorization(len, MAX_PRIME);
if factors.len() == 0 {
if factors.is_empty() {
// Chrip-Z
let pow2len = len.next_power_of_two() << 1;
let lv = pow2len.trailing_zeros() as usize;
Expand Down Expand Up @@ -155,27 +140,26 @@ impl<T: Float + FloatConst + NumAssign> CFft1D<T> {
rot.push(t);
}

match &mut self.work {
&mut WorkData::ChirpZ {
level,
ref ids,
ref omega,
omega_back: _,
src_omega: ref mut org_src_omega,
rot_conj: ref mut org_rot_conj,
rot_ft: ref mut org_rot_ft,
ref pow2len_inv,
} => {
if level == lv {
*org_src_omega = src_omega;
*org_rot_conj = rot_conj;
chirpz::convert_rad2_inplace(&mut rot, lv, ids, omega, false, *pow2len_inv);
*org_rot_ft = rot;
return;
}
if let WorkData::ChirpZ(chirpz::ChirpzData {
level,
ref ids,
ref omega,
src_omega: ref mut org_src_omega,
rot_conj: ref mut org_rot_conj,
rot_ft: ref mut org_rot_ft,
ref pow2len_inv,
..
}) = self.work
{
if level == lv {
*org_src_omega = src_omega;
*org_rot_conj = rot_conj;
chirpz::convert_rad2_inplace(&mut rot, lv, ids, omega, false, *pow2len_inv);
*org_rot_ft = rot;
return;
}
_ => {}
}

// ビットリバースの計算
let ids = precompute_utils::calc_bitreverse2inplace(precompute_utils::calc_bitreverse(
len,
Expand All @@ -191,34 +175,34 @@ impl<T: Float + FloatConst + NumAssign> CFft1D<T> {
],
));
let omega = precompute_utils::calc_omega(pow2len);
let omega_back = omega.iter().rev().map(|x| *x).collect::<Vec<_>>();
let omega_back = omega.iter().rev().copied().collect::<Vec<_>>();
let pow2len_inv = T::one() / cast(pow2len).unwrap();
chirpz::convert_rad2_inplace(&mut rot, lv, &ids, &omega, false, pow2len_inv);

self.work = WorkData::ChirpZ {
self.work = WorkData::ChirpZ(chirpz::ChirpzData {
level: lv,
ids: ids,
omega: omega,
omega_back: omega_back,
src_omega: src_omega,
rot_conj: rot_conj,
ids,
omega,
omega_back,
src_omega,
rot_conj,
rot_ft: rot,
pow2len_inv: pow2len_inv,
};
pow2len_inv,
});
} else {
// Mixed-Radix

// ωの事前計算
let omega = precompute_utils::calc_omega(len);
let omega_back = omega.iter().rev().map(|x| *x).collect::<Vec<_>>();
let omega_back = omega.iter().rev().copied().collect::<Vec<_>>();

self.work = WorkData::MixedRadix {
self.work = WorkData::MixedRadix(mixed_radix::MixedRadixData {
ids: precompute_utils::calc_bitreverse(len, &factors),
omega: omega,
omega_back: omega_back,
factors: factors,
omega,
omega_back,
factors,
ids_inplace: None,
}
});
}
}

Expand All @@ -235,39 +219,13 @@ impl<T: Float + FloatConst + NumAssign> CFft1D<T> {
}

match &self.work {
&WorkData::MixedRadix {
ref ids,
ref omega,
ref omega_back,
ref factors,
ids_inplace: _,
} => mixed_radix::convert_mixed(
source, len, ids, omega, omega_back, factors, is_back, scaler,
),
&WorkData::ChirpZ {
level,
ref ids,
ref omega,
ref omega_back,
ref src_omega,
ref rot_conj,
ref rot_ft,
ref pow2len_inv,
} => chirpz::convert_chirpz(
source,
len,
level,
ids,
omega,
omega_back,
src_omega,
rot_conj,
rot_ft,
is_back,
*pow2len_inv,
scaler,
),
&WorkData::None => source.to_vec(),
WorkData::MixedRadix(ref data) => {
mixed_radix::convert_mixed(source, len, is_back, scaler, data)
}
WorkData::ChirpZ(ref data) => {
chirpz::convert_chirpz(source, len, is_back, scaler, data)
}
WorkData::None => source.to_vec(),
}
}
}
Expand All @@ -282,55 +240,17 @@ impl<T: Float + FloatConst + NumAssign> CFft1D<T> {
self.setup(len);
}

match &mut self.work {
&mut WorkData::MixedRadix {
ref ids,
ref omega,
ref omega_back,
ref factors,
ref mut ids_inplace,
} => {
match ids_inplace {
&mut Option::None => {
*ids_inplace =
Some(precompute_utils::calc_bitreverse2inplace(ids.to_vec()))
}
_ => {}
};
mixed_radix::convert_mixed_inplace(
source,
len,
ids_inplace.as_ref().unwrap(),
omega,
omega_back,
factors,
is_back,
scaler,
);
match self.work {
WorkData::MixedRadix(ref mut data) => {
if data.ids_inplace.is_none() {
data.ids_inplace =
Some(precompute_utils::calc_bitreverse2inplace(data.ids.to_vec()))
}
mixed_radix::convert_mixed_inplace(source, len, is_back, scaler, data);
}
WorkData::ChirpZ(ref data) => {
chirpz::convert_chirpz_inplace(source, len, is_back, scaler, data)
}
&mut WorkData::ChirpZ {
level,
ref ids,
ref omega,
ref omega_back,
ref src_omega,
ref rot_conj,
ref rot_ft,
ref pow2len_inv,
} => chirpz::convert_chirpz_inplace(
source,
len,
level,
ids,
omega,
omega_back,
src_omega,
rot_conj,
rot_ft,
is_back,
*pow2len_inv,
scaler,
),
_ => {}
};
}
Expand Down Expand Up @@ -502,6 +422,18 @@ impl<T: Float + FloatConst + NumAssign> CFft1D<T> {
}
}

impl<T: Float + FloatConst + NumAssign> Default for CFft1D<T> {
/// Returns a instances to execute FFT
///
/// ```rust
/// use chfft::CFft1D;
/// let mut fft = CFft1D::<f64>::default();
/// ```
fn default() -> Self {
Self::new()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
30 changes: 21 additions & 9 deletions src/cfft2d.rs
Expand Up @@ -95,8 +95,8 @@ impl<T: Float + FloatConst + NumAssign> CFft2D<T> {
/// ```
pub fn with_len(len_m: usize, len_n: usize) -> Self {
Self {
len_m: len_m,
len_n: len_n,
len_m,
len_n,
scaler_n: T::one() / cast(len_m * len_n).unwrap(),
scaler_u: T::one() / cast::<_, T>(len_m * len_n).unwrap().sqrt(),
fft_m: CFft1D::with_len(len_m),
Expand All @@ -121,7 +121,7 @@ impl<T: Float + FloatConst + NumAssign> CFft2D<T> {
self.scaler_u = self.scaler_n.sqrt();
self.fft_m.setup(len_m);
self.fft_n.setup(len_n);
if self.work.len() != len_n || (self.work.len() > 0 && self.work[0].len() != len_m) {
if self.work.len() != len_n || (!self.work.is_empty() && self.work[0].len() != len_m) {
self.work = vec![vec![zero(); len_m]; len_n];
}
}
Expand Down Expand Up @@ -333,21 +333,21 @@ impl<T: Float + FloatConst + NumAssign> CFft2D<T> {
is_back: bool,
scaler: T,
) -> Vec<Vec<Complex<T>>> {
if source.len() == 0 {
if source.is_empty() {
return Vec::new();
}
if source.len() != self.len_m || source[0].len() != self.len_n {
self.setup(source.len(), source[0].len());
}

for i in 0..source.len() {
for (i, si) in source.iter().enumerate() {
let work = if is_back {
self.fft_m.backward0(&source[i])
self.fft_m.backward0(si)
} else {
self.fft_m.forward0(&source[i])
self.fft_m.forward0(si)
};
for j in 0..work.len() {
self.work[j][i] = work[j];
for (j, &wi) in work.iter().enumerate() {
self.work[j][i] = wi;
}
}

Expand All @@ -366,6 +366,18 @@ impl<T: Float + FloatConst + NumAssign> CFft2D<T> {
}
}

impl<T: Float + FloatConst + NumAssign> Default for CFft2D<T> {
/// Returns a instances to execute FFT
///
/// ```rust
/// use chfft::CFft2D;
/// let mut fft = CFft2D::<f64>::default();
/// ```
fn default() -> Self {
Self::new()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit d1868ee

Please sign in to comment.