Crate to compare integers of different sizes?

I have a situation where I need to compare if a u32 holds the same value as a usize. While it would be very convenient in this case if Rust provided such comparisons out of the box, I understand that some folks are concerned about performance gotchas (comparing an i64 with a u64 would require both a sign check and a comparison at the CPU level), and others believe that disallowing heterogeneous comparisons catches bugs and prevents more headaches than it causes.

Either way, I was surprised that I have not been able to find a crate that allows for easy comparison of heterogeneous integer types and automatically does the right thing. (E.g., losslessly promotes one to the other where possible, falling back to a sign check and comparison where necessary.)

Does such a crate exist?

The current approach that I would take for 2 unsigned integer values is to cast each value to the largest type that could be required, and then compare the cast results. In this case that would be u64 as usize is 64 bits on a 64-bit system.

So essentially it would look like this:


fn main() {
    let small = 0u32;
    let large = 42usize;
    assert!(small as u64 == large as u64);
} 

The same strategy can be taken for 2 signed integer values.

If you want to compare a signed with an unsigned value, one way or another you'll have to deal with the fact that signed integer types have values that are not representable in unsigned integer types, and vice versa.

As for why there's no crate (that I know of), the above kind of highlights the reason: in most cases it's easy so you neither need nor want a library, and when you're mixing types it really depends on your situation what the correct course of a action is (e.g. what should happen when you try to compare u8::MAX with i8::MIN?) so a library can't abstract that for you.

It could give an error when you run into a problematic case like I outlined above I suppose. But what would that gain you?

Indeed, I know I could handle each case manually as it comes up. I was hoping for a crate that provided generic comparisons between heterogeneous integers and automatically did the right thing based on the argument types.

Wasn't there some RISC chip where usize was 128 bit?
I think I read about it on some other forum post, but can't remember which one (I think the discussion derailed a bit from the original question at that point). In that case the code wouldn't work.

The solution there is obvious: cast to u128 rather than u64.

Not that I have heard of yet.

But RISC V does have specifications for 32, 64 and 128 bit word widths.

From what I understand they created the 128 bit spec. as something of a joke, apart from demonstrating the flexibility of the design.

But then some people dealing with seriously huge data sets expressed a serious interest. They want to give every byte of memory/storage across thousands of machines in data center it's own unique address, with bits to spare for other tasks like tagged data.

Interesting. But I wonder what the overhead is, superbroad pointers like that are generally considered extremely wasteful.

https://crates.io/crates/num-cmp provides this, though it requires this patch to support 128-bit numbers in stable Rust, and it supports usize and isize only on 32-bit and 64-bit platforms.

It appears to be unmaintained, so if you need these issues fixed you might need to fork it and fix them yourself.

1 Like

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.