Skip to content

Complex remainder doesn't find the nearest multiplicator of the divider due to approximations #445

@Astrac

Description

@Astrac

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;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions