Strange comparison behavior

Hi everyone,
I'm a student working on a small Rust project with a lookup table. I wrote a simple linear search function that, given a xq and a monotonic axis array, returns the interval indices (i0,i1) where xq lies. I also wanted to return (i,i) if xq is exactly equal to a breakpoint.

Here's a simplified version of my function:

fn index_search<T: FloatLike, const N: usize>(xq: &T, axis: &[T;N])-> (usize,usize){
    if *xq<=axis[0] {
        return (0,0);
    }
    if *xq>=axis[N-1] {
        return (N-1, N-1);
    }
    for i in 0..N-1 {
        let x0 = axis[i];
        let x1 = axis[i+1];
        if *xq==x0 {
            return (i, i);
        }
        if *xq>=x0 && *xq<=x1 {
            return (i, i+1);
        }
    }
    return (0,0)
}

The strange thing is: when I search for a value that exactly matches a breakpoint, it doesn't return (i,i) as expected.
Interestingly, if I change the interval check from >=/<= to >/<, the function works as intended.
I don“t fully understand why. Logically, if xq==x0, the first branch should return (i,i) before even reaching the interval check, right?

I know it might be a silly question, I'm still learning Rust but I'd love to understand why the original version behave differently and whether this is something about floating-point comparisons or Rust control flow.

Thanks a lot in advance for any explanations!

You test whether xq == x0, but not if xq == x1, before continuing with your xq >= x0 && xq <= x1 test. If xq == x1, you will thus return (i, i + 1) instead of (i + 1, i + 1) as intended. Making the upper bound check non-inclusive (i.e. xq >= x0 && xq < x1 instead of xq >= x0 && xq <= x1) does indeed fix this (x1 becomes x0 in the next iteration), as you already noticed.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.