Skip to content

Commit

Permalink
Convert drfti1 to a safe version
Browse files Browse the repository at this point in the history
I am still not satisfied with this, but at least it can be a decent
starting point for improvements. My points are:
1. Variable names are still unintelligible, mainly because I do not have
a clear vision of the algorithm. Maybe someone better than me can be
able to grasp the meaning of each variable and to git them a decent
name.
2. The first loop is still unidiomatic. Everything I thought involves an
additional check to exit the outer loop, and at the current state (no
benchmarks) I am not sure about the best approch.

Nevertheless, cast checks that were not present in the original code
should be helpful to find strange edge cases, and they should have a
negligible cost due to the cpu branch predictor.
  • Loading branch information
dodomorandi committed Feb 22, 2020
1 parent f7abf1e commit f1a0dc9
Showing 1 changed file with 62 additions and 91 deletions.
153 changes: 62 additions & 91 deletions fft/src/smallft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
unused_mut
)]

use std::os::raw::{c_double, c_float, c_int};
use std::{
convert::TryInto,
os::raw::{c_double, c_float, c_int},
};

/* *******************************************************************
* *
Expand Down Expand Up @@ -86,109 +89,77 @@ last mod: $Id: smallft.c,v 1.19 2003/10/08 05:12:37 jm Exp $
* it follows R_0, R_1, I_1, R_2, I_2 ... R_n-1, I_n-1, I_n like the
* FORTRAN version
*/
unsafe extern "C" fn drfti1(wa: &mut [f32], ifac: &mut [i32]) {
extern "C" fn drfti1(wa: &mut [f32], ifac: &mut [i32]) {
const NTRYH: [i32; 4] = [4, 2, 3, 5];
const TPI: f32 = 6.283_185_5;

static mut ntryh: [c_int; 4] = [4 as c_int, 2 as c_int, 3 as c_int, 5 as c_int];
static mut tpi: c_float = 6.28318530717958648f32;
let n = wa.len().try_into().unwrap();
let ifac: &mut [i32; 32] = ifac.try_into().unwrap();

let mut n = wa.len() as i32;
let mut wa = wa.as_mut_ptr();
let mut ifac = ifac.as_mut_ptr();
let mut nf = 0;
let mut nl = n;

let mut arg: c_float = 0.;
let mut argh: c_float = 0.;
let mut argld: c_float = 0.;
let mut fi: c_float = 0.;
let mut ntry: c_int = 0 as c_int;
let mut i: c_int = 0;
let mut j: c_int = -(1 as c_int);
let mut k1: c_int = 0;
let mut l1: c_int = 0;
let mut l2: c_int = 0;
let mut ib: c_int = 0;
let mut ld: c_int = 0;
let mut ii: c_int = 0;
let mut ip: c_int = 0;
let mut is: c_int = 0;
let mut nq: c_int = 0;
let mut nr: c_int = 0;
let mut ido: c_int = 0;
let mut ipm: c_int = 0;
let mut nfm1: c_int = 0;
let mut nl: c_int = n;
let mut nf: c_int = 0 as c_int;
'c_10244: loop {
j += 1;
if j < 4 as c_int {
ntry = ntryh[j as usize]
} else {
ntry += 2 as c_int
}
'out: for ntry in NTRYH
.iter()
.copied()
.chain(((NTRYH.last().unwrap() + 2)..).step_by(2))
{
loop {
nq = nl / ntry;
nr = nl - ntry * nq;
if nr != 0 as c_int {
let nq = nl / ntry;
let nr = nl - ntry * nq;
if nr != 0 {
break;
}

nf += 1;
*ifac.offset((nf + 1 as c_int) as isize) = ntry;
nl = nq;
if !(ntry != 2 as c_int) {
if !(nf == 1 as c_int) {
i = 1 as c_int;
while i < nf {
ib = nf - i + 1 as c_int;
*ifac.offset((ib + 1 as c_int) as isize) = *ifac.offset(ib as isize);
i += 1
}
*ifac.offset(2 as c_int as isize) = 2 as c_int
}
ifac[nf + 1] = ntry;
if ntry == 2 && nf != 1 {
ifac[1..nf]
.rchunks_exact_mut(2)
.for_each(|chunk| chunk[1] = chunk[0]);
ifac[2] = 2;
}
if !(nl != 1 as c_int) {
break 'c_10244;

nl = nq;
if nl == 1 {
break 'out;
}
}
}
*ifac.offset(0 as c_int as isize) = n;
*ifac.offset(1 as c_int as isize) = nf;
argh = tpi / n as c_float;
is = 0 as c_int;
nfm1 = nf - 1 as c_int;
l1 = 1 as c_int;
if nfm1 == 0 as c_int {
let nf = nf;

ifac[0] = n;
ifac[1] = nf.try_into().unwrap();
if nf == 0 {
return;
}
k1 = 0 as c_int;
while k1 < nfm1 {
ip = *ifac.offset((k1 + 2 as c_int) as isize);
ld = 0 as c_int;
l2 = l1 * ip;
ido = n / l2;
ipm = ip - 1 as c_int;
j = 0 as c_int;
while j < ipm {
ld += l1;
i = is;
argld = ld as c_float * argh;
fi = 0.0f32;
ii = 2 as c_int;
while ii < ido {
fi += 1.0f32;
arg = fi * argld;
let fresh0 = i;
i = i + 1;
*wa.offset(fresh0 as isize) = f64::cos(arg as c_double) as c_float;
let fresh1 = i;
i = i + 1;
*wa.offset(fresh1 as isize) = f64::sin(arg as c_double) as c_float;
ii += 2 as c_int
}
is += ido;
j += 1
}
l1 = l2;
k1 += 1
}

let argh = TPI / wa.len() as f32;
ifac[2..=nf]
.iter()
.map(|&ip| ip.try_into().unwrap())
.fold((0, 1), |(is, l1), ip: usize| {
let l2 = l1 * ip;
let ido = wa.len() / l2;
let ipm = ip - 1;

wa[is..]
.chunks_exact_mut(ido)
.zip((l1..).step_by(l1).map(|ld| ld as f32 * argh))
.take(ipm)
.for_each(|(chunk, argld)| {
chunk[..(ido - 2).try_into().unwrap_or(0)]
.chunks_exact_mut(2)
.fold(1f32, |fi, chunk| {
let arg = (fi * argld) as f64;
chunk[0] = f64::cos(arg) as f32;
chunk[1] = f64::sin(arg) as f32;
fi + 1.
});
});

(is + ipm * ido, l2)
});
}
unsafe extern "C" fn fdrffti(n: usize, wsave: &mut [f32], mut ifac: &mut [i32]) {
if n == 1 {
Expand Down

0 comments on commit f1a0dc9

Please sign in to comment.