extern crate num_traits;
use num_traits::Float;
#[derive(Copy, Clone)]
pub struct IQOsc<T: Float> {
step: (T, T),
phase: (T, T),
}
impl<T: Float> IQOsc<T> {
pub fn new(phase: T, step: T) -> Self {
IQOsc {
step: step.sin_cos(),
phase: phase.sin_cos(),
}
}
pub fn set_step(&mut self, step: T) {
self.step = step.sin_cos();
}
pub fn set_phase(&mut self, phase: T) {
self.phase = phase.sin_cos();
}
pub fn next(&mut self) -> (T, T) {
let cur = self.phase;
self.phase = (
self.phase.0 * self.step.1 + self.phase.1 * self.step.0,
self.phase.1 * self.step.1 - self.phase.0 * self.step.0,
);
cur
}
}
#[cfg(test)]
mod test {
use super::*;
use std::f32::consts::PI as PI32;
use std::f64::consts::PI as PI64;
#[test]
fn test_osc() {
let mut o = IQOsc::new(0.0, PI32 / 2.0);
for _ in 0..100 {
let (sin, cos) = o.next();
assert!((sin - 0.0).abs() < 0.0001);
assert!((cos - 1.0).abs() < 0.0001);
let (sin, cos) = o.next();
assert!((sin - 1.0).abs() < 0.0001);
assert!((cos - 0.0).abs() < 0.0001);
let (sin, cos) = o.next();
assert!((sin - 0.0).abs() < 0.0001);
assert!((cos - -1.0).abs() < 0.0001);
let (sin, cos) = o.next();
assert!((sin - -1.0).abs() < 0.0001);
assert!((cos - 0.0).abs() < 0.0001);
}
}
#[test]
fn test_err_32() {
let mut o = IQOsc::new(0.0, PI32 / 20.0);
for _ in 0..1024 {
let (sin, cos) = o.next();
assert!((sin - 0.0).abs() < 1.0e-3);
assert!((cos - 1.0).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.15643446504023087).abs() < 1.0e-3);
assert!((cos - 0.98768834059513777).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.3090169943749474).abs() < 1.0e-3);
assert!((cos - 0.95105651629515353).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.45399049973954675).abs() < 1.0e-3);
assert!((cos - 0.8910065241883679).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.58778525229247314).abs() < 1.0e-3);
assert!((cos - 0.80901699437494745).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.70710678118654746).abs() < 1.0e-3);
assert!((cos - 0.70710678118654757).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.80901699437494745).abs() < 1.0e-3);
assert!((cos - 0.58778525229247314).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.89100652418836779).abs() < 1.0e-3);
assert!((cos - 0.4539904997395468).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.95105651629515353).abs() < 1.0e-3);
assert!((cos - 0.30901699437494745).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.98768834059513777).abs() < 1.0e-3);
assert!((cos - 0.15643446504023092).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 1.0).abs() < 1.0e-3);
assert!((cos - 0.0).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.98768834059513777).abs() < 1.0e-3);
assert!((cos - -0.15643446504023081).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.95105651629515364).abs() < 1.0e-3);
assert!((cos - -0.30901699437494734).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.8910065241883679).abs() < 1.0e-3);
assert!((cos - -0.45399049973954669).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.80901699437494745).abs() < 1.0e-3);
assert!((cos - -0.58778525229247303).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.70710678118654757).abs() < 1.0e-3);
assert!((cos - -0.70710678118654746).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.58778525229247325).abs() < 1.0e-3);
assert!((cos - -0.80901699437494734).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.45399049973954686).abs() < 1.0e-3);
assert!((cos - -0.89100652418836779).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.30901699437494751).abs() < 1.0e-3);
assert!((cos - -0.95105651629515353).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.15643446504023098).abs() < 1.0e-3);
assert!((cos - -0.98768834059513766).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - 0.0).abs() < 1.0e-3);
assert!((cos - -1.0).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.15643446504023073).abs() < 1.0e-3);
assert!((cos - -0.98768834059513777).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.30901699437494728).abs() < 1.0e-3);
assert!((cos - -0.95105651629515364).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.45399049973954669).abs() < 1.0e-3);
assert!((cos - -0.8910065241883679).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.58778525229247303).abs() < 1.0e-3);
assert!((cos - -0.80901699437494756).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.70710678118654746).abs() < 1.0e-3);
assert!((cos - -0.70710678118654768).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.80901699437494734).abs() < 1.0e-3);
assert!((cos - -0.58778525229247325).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.89100652418836779).abs() < 1.0e-3);
assert!((cos - -0.45399049973954692).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.95105651629515353).abs() < 1.0e-3);
assert!((cos - -0.30901699437494756).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.98768834059513766).abs() < 1.0e-3);
assert!((cos - -0.15643446504023104).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -1.0).abs() < 1.0e-3);
assert!((cos - 0.0).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.98768834059513777).abs() < 1.0e-3);
assert!((cos - 0.15643446504023067).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.95105651629515364).abs() < 1.0e-3);
assert!((cos - 0.30901699437494723).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.8910065241883679).abs() < 1.0e-3);
assert!((cos - 0.45399049973954664).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.80901699437494756).abs() < 1.0e-3);
assert!((cos - 0.58778525229247292).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.70710678118654768).abs() < 1.0e-3);
assert!((cos - 0.70710678118654735).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.58778525229247336).abs() < 1.0e-3);
assert!((cos - 0.80901699437494734).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.45399049973954697).abs() < 1.0e-3);
assert!((cos - 0.89100652418836779).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.30901699437494762).abs() < 1.0e-3);
assert!((cos - 0.95105651629515353).abs() < 1.0e-3);
let (sin, cos) = o.next();
assert!((sin - -0.15643446504023109).abs() < 1.0e-3);
assert!((cos - 0.98768834059513766).abs() < 1.0e-3);
}
}
#[test]
fn test_err_64() {
let mut o = IQOsc::new(0.0, PI64 / 20.0);
for _ in 0..8192 {
let (sin, cos) = o.next();
assert!((sin - 0.0).abs() < 1.0e-12);
assert!((cos - 1.0).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.15643446504023087).abs() < 1.0e-12);
assert!((cos - 0.98768834059513777).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.3090169943749474).abs() < 1.0e-12);
assert!((cos - 0.95105651629515353).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.45399049973954675).abs() < 1.0e-12);
assert!((cos - 0.8910065241883679).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.58778525229247314).abs() < 1.0e-12);
assert!((cos - 0.80901699437494745).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.70710678118654746).abs() < 1.0e-12);
assert!((cos - 0.70710678118654757).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.80901699437494745).abs() < 1.0e-12);
assert!((cos - 0.58778525229247314).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.89100652418836779).abs() < 1.0e-12);
assert!((cos - 0.4539904997395468).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.95105651629515353).abs() < 1.0e-12);
assert!((cos - 0.30901699437494745).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.98768834059513777).abs() < 1.0e-12);
assert!((cos - 0.15643446504023092).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 1.0).abs() < 1.0e-12);
assert!((cos - 0.0).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.98768834059513777).abs() < 1.0e-12);
assert!((cos - -0.15643446504023081).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.95105651629515364).abs() < 1.0e-12);
assert!((cos - -0.30901699437494734).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.8910065241883679).abs() < 1.0e-12);
assert!((cos - -0.45399049973954669).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.80901699437494745).abs() < 1.0e-12);
assert!((cos - -0.58778525229247303).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.70710678118654757).abs() < 1.0e-12);
assert!((cos - -0.70710678118654746).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.58778525229247325).abs() < 1.0e-12);
assert!((cos - -0.80901699437494734).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.45399049973954686).abs() < 1.0e-12);
assert!((cos - -0.89100652418836779).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.30901699437494751).abs() < 1.0e-12);
assert!((cos - -0.95105651629515353).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.15643446504023098).abs() < 1.0e-12);
assert!((cos - -0.98768834059513766).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - 0.0).abs() < 1.0e-12);
assert!((cos - -1.0).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.15643446504023073).abs() < 1.0e-12);
assert!((cos - -0.98768834059513777).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.30901699437494728).abs() < 1.0e-12);
assert!((cos - -0.95105651629515364).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.45399049973954669).abs() < 1.0e-12);
assert!((cos - -0.8910065241883679).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.58778525229247303).abs() < 1.0e-12);
assert!((cos - -0.80901699437494756).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.70710678118654746).abs() < 1.0e-12);
assert!((cos - -0.70710678118654768).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.80901699437494734).abs() < 1.0e-12);
assert!((cos - -0.58778525229247325).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.89100652418836779).abs() < 1.0e-12);
assert!((cos - -0.45399049973954692).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.95105651629515353).abs() < 1.0e-12);
assert!((cos - -0.30901699437494756).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.98768834059513766).abs() < 1.0e-12);
assert!((cos - -0.15643446504023104).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -1.0).abs() < 1.0e-12);
assert!((cos - 0.0).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.98768834059513777).abs() < 1.0e-12);
assert!((cos - 0.15643446504023067).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.95105651629515364).abs() < 1.0e-12);
assert!((cos - 0.30901699437494723).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.8910065241883679).abs() < 1.0e-12);
assert!((cos - 0.45399049973954664).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.80901699437494756).abs() < 1.0e-12);
assert!((cos - 0.58778525229247292).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.70710678118654768).abs() < 1.0e-12);
assert!((cos - 0.70710678118654735).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.58778525229247336).abs() < 1.0e-12);
assert!((cos - 0.80901699437494734).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.45399049973954697).abs() < 1.0e-12);
assert!((cos - 0.89100652418836779).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.30901699437494762).abs() < 1.0e-12);
assert!((cos - 0.95105651629515353).abs() < 1.0e-12);
let (sin, cos) = o.next();
assert!((sin - -0.15643446504023109).abs() < 1.0e-12);
assert!((cos - 0.98768834059513766).abs() < 1.0e-12);
}
}
#[test]
fn test_mult() {
let m = 120;
let common = 2.0 / 256 as f32 * PI32 * m as f32;
let mut osc = IQOsc::new(common * -104 as f32, common);
for n in -104..105 {
let inner = 2.0 / 256 as f32 * PI32 * m as f32 * n as f32;
let (sin, cos) = inner.sin_cos();
let (osin, ocos) = osc.next();
assert!((sin - osin).abs() < 0.0001);
assert!((cos - ocos).abs() < 0.0001);
}
}
}