-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there any plan to implement signed types i2 .. i127 #14
Comments
Thanks for the bug report. I'm planning on doing them eventually, though I haven't had the need yet. There are also some non-trivial design questions. For example, should Maybe the answer is two functions? |
I would go for two functions too (but the inner value will still need to be one of both, sounds like something we could maybe benchmark or just use the easier one). |
It would be nice if |
Not sure if benchmarks would help much, as it depends on your use-case:
Most likely, the difference will be incredibly tiny anyway |
You're right, benchmark was the wrong word, the easier one should be used |
I was thinking of trying to implement this. My gut instinct would be to "optimize" for arithmetic operations, since if the only use case is as a bitfield you can probably make it work with an unsigned type if the tiny difference is actually important? Adding masking overhead (however little) to arithmetic operations on a signed type seems like it's contrary to the point of using one, and would be a purely ergonomic change. |
Awesome, happy to take a patch if it fits within the overall design. Given the previous discussions I'd suggest the following:
By the way: The easiest way I can think of to mask (while retaining the sign) is to shift like this: For example, the addition of two i5 would look something like this:
|
Hmm there is one more complication: Do we want Reason I'm asking: For unsigned ints, So maybe we should make this symmetrical? To make it less error prone, we could make |
To be honest, I still don't quite like it. Seems unbalanced. What do you two think? |
I took at the look at the uX crate and they don't seem to have a distinction at all, based on the documentation. |
Let's think about the basic case if rust would support arbints. |
I was thinking about the possibility of expanding signed to be constructed from unsigned as well, but I don't know how sold I am on it. One problem I noticed before I got too far is the I was thinking this should probably be behind the |
I think the issue is do we represent |
I'm imagining in other words, I think |
The API question can be independent from the underlying representation. We might decide to change between signed/unsigned later, but the behavior of the library should be the same. I agree that That means we should another pair of functions for the unsigned representation. |
So I was thinking about the ways to go about including all of the implementations, and one thing to consider is that the
The third option would essentially represent every arbitrary int as a sign-extended byte aligned type, and the bounds checking would work largely similarly I think? Option 2 is almost certainly the sanest approach, but I think there's a certain elegance to 3. |
I can just comment two more thoughts:
|
I mean, I think |
To be clearer: if we did 3., wouldn't that mean |
Nothing makes me think it should lead to UB naively, |
I'd prefer to not use transmute as it's unsafe. The safe alternative is simply to do a cast here: |
As to @vortexofdoom 's suggestions: third: could be done in a way that's not a breaking change, but I don't see how it would help. We can change the backing store (and mostly things would be identical), but we might have to change some operations like Add to restore the previous behavior. second: Won't work unfortunately as Rust's generics don't support const. So once we introduce something like first: I think this is the way to go unfortunately. One silver lining here is that there are currently two Number implementations (one using const_trait and one using stable). As Rust itself has dropped const_trait, we don't need to have the const-version for the SignedNumber. I'll file a separate task to remove that. |
Yeah, to put what I was trying to say another way, |
You know I'm using this functionality and probably also know that they've just temporarily removed it. Please don't. |
Filed #22 . Let's discuss the const-trait over there? |
I wanted to make some more changes to Number anyway. For example, Number can easily require Add, Sub, Shl etc to be implemented. The downside of that though is that it would be a slightly breaking change (in the unlikely case that someone else implements Number). So it might be a good idea to bundle API changes together and make a 2.0. |
Sorry, I got busy with other things but have recently been thinking about getting back to this. One thing that originally slowed me down is that lib.rs is pretty unwieldy already, and having alternating signed/unsigned impls or two big blocks both felt pretty bad for both readability and maintainability. It feels weird to have a file just for signed types, so I'd probably break out both types into their own files, and maybe only keep the Number trait(s?) in lib.rs. Speaking of Number, I think it would be a good idea to make it sealed if we're implementing all types from from 1 to 128 bits. There's not really a use case for users to implement it on external types, and that ability is probably not something we want to guarantee long term. Probably something to be filed in a separate issue, but it might add some implementation flexibility here. In case someone picks this up before I do, one thought I had is that a major benefit to implementing with the underlying type being signed is that right shifts are sign-extending. This would make it pretty easy to cast between the unsigned "bits" and signed internal formats by first left shifting until the sign bit lines up with the underlying primitive and then switching to the other and right shifting again. |
zig becomes more and more popular, so zigs defaults may be good to go (hoping rust will also adopt these in future). i mean storage vs arith for negative numbers. storage also for u nums is relevant. |
It would be useful to implement signed types i2 .. i127
The text was updated successfully, but these errors were encountered: