-
Notifications
You must be signed in to change notification settings - Fork 149
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
Feature request: two's complement #73
Comments
I'm not sure what do you mean? |
I meant that internally you don't need to change any representation. Just keep storing numbers as you do and have the However I would be happy to have a method to load negative numbers in two's complement representation into BN and to dump them in the same representation from BN. For output, an easy extension would be adding a new argument to For input, perhaps a new method is needed as extending the constructor might be too much of a change. |
May I ask you to post a code sample that will demonstrate it? |
Demonstrate the implementation in BN, or how I would imagine using it? |
Just API with inputs and results |
Was thinking a bit about this in the past days. I'm using BN.js to handle numbers between 8 and 256bits for the Ethereum ABI in http://github.com/axic/ethereumjs-abi. It supports signed (two's complement) and unsigned representations. Currently I have two helper functions ( function toTwos(num, width) {
if (num.isNeg())
num = new BN(1).iushln(width).isub(num.iabs());
// Or bitwise negate + plus 1
return num;
}
function fromTwos(num, width) {
if (num.testn(width - 1)) // top bit set => negative number
num = new BN(1).iushln(width).isub(num).ineg();
// Or bitwise negate + plus 1
return num;
} Perhaps I would suggest to have the following API:
e.g.
Works as the previous one, only touches the bottom |
@axic sorry, but I'm not convinced that it could be useful for general developers. Thanks for taking time to explain to me! |
@indutny And DER is, as far as I can tell, the primary encoding method for most people using this library? |
Mmm... tell me about that ;) https://github.com/indutny/asn1.js/blob/75383bad77c869bde876db6a799badfcee9b2a1f/lib/asn1/encoders/der.js#L174-L192 Doesn't seem like anything similar. |
@indutny forget the code. DER in ASN.1 is literally defined as encoding a twos complement integer.
See https://en.wikipedia.org/wiki/Two%27s_complement, the table on the right should be obvious enough to recognize as a set of DER encoded integers. edit: I'm not saying this PR is the right way to do so, but, the feature request is real enough. |
That said, what @axic has written above is a bit odd. Two's complement is strictly a way of encoding integers in binary. |
Well what I've written uses code what's available. Once there's bitwise negation (#72) you could use it. Sample usage of the proposed methods:
Also you could change Similarly, the functionality of Sample usage of extending the current functions (where the last boolean is true for two's complement):
Hiding them in the proper places would add code duplication and perhaps more complexity to those methods, while keeping the behaviour clean for the user. I'm not sure which one of these two are more desired. Then again you could make my suggested methods internal and use them in About usability: most of the serialization methods support both signed and unsigned integers and I've yet to see a mainstream serializer not using two's complement for negative numbers. Next to DER (used by bitcoin), all the ethereum javascript libraries implement their own helpers for the above. My other reason of having this in the library: in the future it could be well optimised with having access to internals (e.g. using bitwise negation or doing other shortcuts). |
@axic I'll have a deeper look into this. Want to set up a PR branch we can both work on? |
@dcousens happy to do that, should I create a branch on my repo? |
@axic sounds like a plan |
@dcousens sorry it took a while to find the time, it is in the Added a somewhat extensive number of tests and the simple implementation from above, which works by returning a new BN instance. |
Awesome @axic, I'll have a look through it soon 👍 |
@dcousens I've just created a PR (#77) for bitwise NOT, which can be used for the two's complement. It is much faster. Substraction based:
Using bitwise not:
|
Awesome @axic 👍 |
@axic the strangeness of the above solution is that a |
@dcousens There are just too many options already (String, Array and hopefully Buffer will be the third soon) and that would pollute the conversion code. Having a parameter or tons of alternate versions looks ugly to me. And the same applies to My reasoning is that users of this library are knowledgable and can handle I know two's is most commonly part of the serialization process, but it is just another number. |
@axic IMHO its only really used as an encoding format, but, sure. |
@dcousens to argue its not only an encoding format: many CPUs would keep negative numbers in two's complement in registers/memory and that is one of the reasons there is a differentiation between arithmetic and logical shift instructions |
But is that ever likely to be a reasonable expectation for someone in user land? |
@dcousens sorry, I don't entirely get you? Writing assembly is part of userland. |
I meant in terms of this library. For example, if I took the |
twosComplement of 1 is 1 :) |
How about |
@dcousens honestly I do not see much difference, but I am really open to see your suggestion how it should be presented to the user |
@dcousens I gave some extra thought about this and I think for your ideal situation to happen, you would need to change bn.js in its entirety to work based off two's complement arithmetic, e.g. change all the methods to work based off that representation instead of the |
An idea if we don't want a major change: currently the How about keeping numeral arguments as they are today (e.g. base-16 with a negative sign), while reserving |
Well, breaking change is a breaking change. So it will cause a semver-major anyway. I don't think that we want to default to twos-complement. I'd rather go for a separate API methods... |
This exists, see |
It would be nice to support two's complement representation for toArray() and perhaps a new way of loading a two's complement representation into BN.
The text was updated successfully, but these errors were encountered: