1 个稳定版本
使用旧的Rust 2015
3.0.0 | 2018年1月2日 |
---|
#17 in #振荡器
22KB
318 行
iq_osc.rs – 无触发函数调用的I/Q振荡器
给定 f(t) = cos(θ0 + ωt) = cos Φ(t),在这里定义一个振荡器来按顺序计算 f(0),f(1),f(2),... 以生成正弦信号。此外,一个 正交 振荡器也在每一步计算 g(t) = sin Φ(t) 以生成正交信号。
在高采样率或紧密循环中对这些三角函数进行计算可能会非常昂贵。作为替代方案,这个crate实现了一个正交振荡器,在每个评估中将2个三角函数调用替换为6次算术运算(4次乘法,1次加法和1次减法)。
用法
可以通过在 Cargo.toml
中将其添加为依赖项,通过cargo使用此 crate。
[dependencies]
iq_osc = "3.0.0"
并在crate根目录中导入它
extern crate iq_osc;
lib.rs
:
无触发函数调用的I/Q振荡器。
给定
f(t) = cos(θ0 + ωt) = cos Φ(t),
在这里定义一个振荡器来按顺序计算 f(0),f(1),f(2),... 以生成正弦信号。此外,一个 正交 振荡器也在每一步计算 g(t) = sin Φ(t) 以生成正交信号。
在高采样率或紧密循环中对这些三角函数进行计算可能会非常昂贵。作为替代方案,这个crate实现了一个正交振荡器,在每个评估中将2个三角函数调用替换为6次算术运算(4次乘法,1次加法和1次减法)。
理论
使用上面定义的 f(t) = cos Φ(t),注意到
Φ(0) = θ0
Φ(1) = θ0 + ω = Φ(0) + ω
Φ(2) = θ0 + 2ω = Φ(1) + ω
一般来说,
Φ(t) = Φ(t - 1) + ω, t > 0
结合这一点和三角恒等式
cos(u + v) = cos(u)cos(v) - sin(u)sin(v)
sin(u + v) = sin(u)cos(v) + cos(u)sin(v)
我们可以将 f(t) 写作
f(t) = cos(Φ(t - 1) + ω) = cos(Φ(t - 1))cos(ω) - sin(Φ(t - 1))sin(ω)
对于正交信号,类似地
g(t) = sin(Φ(t - 1) + ω) = sin(Φ(t - 1))cos(ω) + cos(Φ(t - 1))sin(ω)
如果我们在初始化时计算 sin ω,cos ω,sin θ0 和 cos θ0,那么我们就可以使用上面的方程中的算术来计算 f(t) 和 g(t) 对于 t = 0,1,2,... 的值。
误差累积
由于浮点数舍入误差的累积,返回的正弦/余弦评估的精度会随着相位步长逐渐降低。使用非常小的相位步长或让 IQOsc
进行许多许多周期运行会使这个问题更加明显。作为解决方案,可以使用双精度 IQOsc<f64>
,它在相位步长上提供了显著的精度提升,并且对速度的影响相对较小——比较 bench_osc32
和 bench_osc64
在 cargo bench
输出中的结果(以下给出示例输出)。
test bench_osc32 ... bench: 55,043 ns/iter (+/- 4,479)
test bench_osc64 ... bench: 62,170 ns/iter (+/- 30,989)
test bench_trig32 ... bench: 490,407 ns/iter (+/- 90,148)
test bench_trig64 ... bench: 2,365,592 ns/iter (+/- 148,062)
依赖项
~240KB