I am trying to implement the CORDIC method in rust
using this c implementation as an example, however i am having rounding error issues when generating the table. Here is my code and the results.
fn generate_table () {
let pi: f32 = 3.1415926536897932384626;
let k1: f32 = 0.6072529350088812561694; // 1/k
let num_bits: uint = 32;
let num_elms: uint = num_bits;
let mul: f32 = 1073741824.000000; // 1<<(bits-2)
println!("Cordic sin in rust");
println!("num bits {}", num_bits);
println!("mul {}", mul);
println!("pi is {}", pi);
println!("k1 is {}", k1);
let shift: f32 = 2.0;
for ii in range(0, num_bits) {
let ipow: f32 = 1f32/shift.powi(ii as i32);
let cur: f32 = ipow.atan() * mul;
//println!("table values {:.10f}", cur);
println!("table values 0x{}", std::f32::to_str_hex(cur));
}
}
fn main() {
generate_table();
}
which gives me the following table, notice the first and last values to see the biggest errors.
table values 0x3243f6c0
table values 0x1dac6700
table values 0xfadbb00
table values 0x7f56ea8
table values 0x3feab78
table values 0x1ffd55c
table values 0xfffaab
table values 0x7fff55.8
table values 0x3fffea.c
table values 0x1ffffd.6
table values 0xfffff.b
table values 0x7ffff.f8
table values 0x40000
table values 0x20000
table values 0x10000
table values 0x8000
table values 0x4000
table values 0x2000
table values 0x1000
table values 0x800
table values 0x400
table values 0x200
table values 0x100
table values 0x80
table values 0x40
table values 0x20
table values 0x10
table values 0x8
table values 0x4
table values 0x2
table values 0x1
table values 0x0.8
Why am i getting these (rounding?) errors and how do i fix them?
The quick answer: How certain are you that you are feeding identical inputs into both computations? In particular, the C implementation you quote says:
int mul = (1<<(bits-2));
while you have hard-coded:
let mul: f32 = 1073741824.000000; // 1<<(bits-2)
Note 1: You have changed the type of
mul
from anint
to anf32
.Note 2: In the output I get when I run your program, I see this:
mul 1073741844
Notably, this is different from the hard-coded constant you wrote above; it is off by 20.
My usual way to debug a problem like this, and that I actually did in this case before I noticed the problem above, is to instrument both the C and the Rust versions of the code with printouts of the values of each intermediate expression, in order to identify where things start to differ and therefore narrow down which operation is introducing an "error."
In this case, it involved modifying the C code and the Rust code in parallel to print out a table of not just the
i
(orii
in the Rust version) and the outputc
, but also every intermediate result.Here is the code for each of those, along with the output tables I got in the end. (But then it was only analyzing those tables that I realized that the two
mul
values differed!)C code:
Rust code:
Tables generated: