Skip to content

Commit

Permalink
fix cexpf function on ARM
Browse files Browse the repository at this point in the history
  • Loading branch information
andresv committed Oct 3, 2015
1 parent dcdf34f commit b79dd85
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 12 deletions.
5 changes: 3 additions & 2 deletions src/complex.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ typedef struct {
float imag;
} RustComplex;

RustComplex ccexpf(const RustComplex* a) {
void ccexpf(RustComplex* a) {
printf("cplx sizeof=%i and addr %p\n", sizeof(RustComplex), a);
printf("cplx in1: %f %fi\n", a->real, a->imag);
float complex input = a->real + a->imag * I;
printf("cplx in2: %f %fi\n", creal(input), cimag(input));

float complex cout = cexpf(input);
RustComplex rout = {.real=creal(cout), .imag=cimag(cout)};
a->real = creal(cout);
a->imag = cimag(cout);
printf("cplx out: %f %fi\n", creal(cout), cimag(cout));
return rout;
}
27 changes: 17 additions & 10 deletions src/dsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ use std::mem;
// https://github.com/rust-lang/rfcs/issues/793
// Therefore this workaround is needed.
//
// LiquidComplex32 is used here because num::complex::Complex does not have #[repr(C)]
// ccexpf is implemented in complex.c
// Type `LiquidComplex32` is used here because standard `num::complex::Complex` does not have #[repr(C)].
// Function `ccexpf` is implemented in complex.c
//
// Notice that `ccexpf` does not return value, it just changes `z` value in place.
// For some reson it did not work correctly on ARM (BeagleBoneBlack) if `ccexpf` returned
// calculated `LiquidComplex32` struct. Although it worked on Mac OS X and 64/32 bit X86 Ubuntu.
extern {
pub fn ccexpf(z: *const LiquidComplex32) -> LiquidComplex32;
pub fn ccexpf(z: *mut LiquidComplex32);
}

use std::f32::consts::PI;
Expand All @@ -55,19 +59,23 @@ fn test_cexpf() {
// cargo test -- --nocapture
// to see prints

let a: Complex<f32> = unsafe {mem::transmute(ccexpf(mem::transmute(&LiquidComplex32{real:0.0, imag:0.0})))};
let mut a = Complex::<f32>::new(0.0, 0.0);
unsafe {ccexpf(mem::transmute(&mut a))};
assert_eq_delta(a.re, 1.0, 0.000001);
assert_eq_delta(a.im, 0.0, 0.000001);

let a: Complex<f32> = unsafe {mem::transmute(ccexpf(mem::transmute(&LiquidComplex32{real:1.0, imag:1.0})))};
let mut a = Complex::<f32>::new(1.0, 1.0);
unsafe {ccexpf(mem::transmute(&mut a))};
assert_eq_delta(a.re, 1.468694, 0.000001);
assert_eq_delta(a.im, 2.2873552, 0.000001);

let a: Complex<f32> = unsafe {mem::transmute(ccexpf(mem::transmute(&LiquidComplex32{real:70.0, imag:70.0})))};
let mut a = Complex::<f32>::new(70.0, 70.0);
unsafe {ccexpf(mem::transmute(&mut a))};
assert_eq_delta(a.re, 1593075600000000000000000000000f32, 0.000001);
assert_eq_delta(a.im, 1946674600000000000000000000000f32, 0.000001);

let a: Complex<f32> = unsafe {mem::transmute(ccexpf(mem::transmute(&LiquidComplex32{real:1_000_000.0, imag:1_000_000.0})))};
let mut a = Complex::<f32>::new(1_000_000.0, 1_000_000.0);
unsafe {ccexpf(mem::transmute(&mut a))};
assert_eq!(a.re, std::f32::INFINITY);
assert_eq!(a.im, -std::f32::INFINITY);

Expand Down Expand Up @@ -110,9 +118,8 @@ pub fn shift_frequency(inbuf: &[Complex<f32>], samplenum: &mut u64, shift_hz: f6
let mut output = Vec::<Complex<f32>>::with_capacity(inbuf.len());

for sample in inbuf {
let corrector: Complex<f32> = unsafe { mem::transmute(ccexpf(
& LiquidComplex32{real:0., imag: -2. * PI * (shift_hz as f64 / samplerate as f64 * *samplenum as f64) as f32})
)};
let mut corrector = Complex::<f32>::new(0.0, -2. * PI * (shift_hz as f64 / samplerate as f64 * *samplenum as f64) as f32);
unsafe { ccexpf(mem::transmute(&mut corrector))};

output.push(sample * corrector);
*samplenum += 1;
Expand Down

0 comments on commit b79dd85

Please sign in to comment.