-
Notifications
You must be signed in to change notification settings - Fork 152
Description
I noticed that if I calculate cetain remainders I get results that do not agree with what I calculate using other tools; for example, 10 % (5 + 7i) gives 10 as a result with this library but other tools (e.g. wolfram alpha) give me -2 - 2i. To corroborate wolfram's result just notice that |10| = 10 and |5 + 7i| ~ 8.6, while the modulus of the reminder should be smaller than the one of the divisor.
I found that the issue causing this is the way the remainder is computed using only integer types: the implementation always find the biggest multiplier of the divisor that is smaller than dividend, not the nearest mutiplier. If I rewrite the algorithm as follows I get the very same results as wolfram and other code of mine that depends on this calculation behaves correctly:
fn calc_mod(n: Complex<i32>, modulus: Complex<i32>) -> Complex<i32> {
// Transform to f32
let nf = Complex::new(n.re as f32, n.im as f32);
let modf = Complex::new(modulus.re as f32, modulus.im as f32);
// The usual complex division formula but applied to Complex<f32> instead of <Complex<i32>
let div = (nf * modf.conj()) / modf.norm_sqr();
// use round() to ensure closest multiplier is found
let rounded = Complex::new(div.re.round() as i32, div.im.round() as i32);
let nearest_mult = rounded * modulus;
return n - nearest_mult;
}