-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
proposal: math/big: add Int.AddInt64, Int.CmpInt64 #29951
Comments
You can declare some package variables called one, two, etc. and use them throughout.
This also lets you do things like
|
Admittedly, being able to perform arithmetic with a big.Int would be beneficial: https://github.com/ericlagergren/decimal/blob/master/internal/arith/arith_amd64.go https://github.com/ericlagergren/decimal/blob/master/internal/c/const.go |
@robpike Yes, package variables are one way of how to approach (although each package would have to possibly allocate the same |
Int.AddInt64 seems strictly better than Inc/Dec and matches the Int64 and SetInt64 methods. (Probably don't need SubInt64 if we have a general AddInt64. Also probably don't need AddUint64, SubUint64.) But what else would it require adding? And? AndNot? Cmp? Div? DivMod? Mod? Mul? Or? Quo? QuoRem? Rem? Sub after all? Xor? Just declaring a few globals with the constants you need seems to be the right answer most of the time. It's not clear that doubling the API surface is a significant enough win. |
Perhaps And, AndNot, Xor are not really necessary, Cmp can be worked around with Sign, IsInt64, Int64. So if I may summarize this gives 4 options:
|
Talked to @griesemer, who is inclined to start with just AddInt64 and CmpInt64 and wait for more compelling needs for any of the others. Those are clearly the most common. |
I would start with none of them. If you add one, you'll end up adding them all, or at best dealing with a string of proposals to add them piecemeal. Please hold the line. |
@rsc If I understood correctly, AddInt64 would need to distinguish positive and negative values as the internal implementation of big.Int uses big.nat, i.e. to add a negative number it subtracts its absolute value. If there would indeed be such mechanism, why not expose it, i.e. to add both AddUint64 and SubUint64? (With or without AddInt64?) It is similar to Int.SetInt64/Int.SetUint64, Rat.SetInt64/Rat.SetUint64, I think unsigned 64-bits are useful. |
I don't understand the need for adding these methods to the standard library. As @robpike mentioned, package level variables already handle the proposed use case very well and the big.Int API is already very large. |
Since AddInt64(x) would need to distinguish the sign and conver x to nat we can’t save much on allocations. And may be even more harmful for memory to do so in case of making increment functions. Only convenience I see is symantics. But I think std libs should follow: KISS. Solution like
are way better approach to issue. |
I shall punt to Go1.14 as the jury is still hung on whether to implement it or not, but also there hasn't been movement. |
The methods |
Despite this proposal being accepted we have not moved ahead yet. @robpike is likely correct that this will simply invite piecemeal additions of more little helpers. There may be ways to improve performance of the existing code w/o changing the API. |
Since there doesn't appear to be a clear consensus on this addition to math/big, should this be moved back into active discussion, with the Accepted label removed? |
Change https://golang.org/cl/334885 mentions this issue: |
Can someone clean the "Proposal-Accepted" label as it seems to not really being accepted? Having crossed paths with
The only improvement I see that could be done is advising in the docs not to do If someone really needs to save allocations and/or improvement performance a fixed-precision package should be used and/or hacks which are just that, hacks. If you really need a hack check https://github.com/vpereira01/biigist/blob/master/bigintinc.go |
Looks like that won't quite work, at least currently, because we haven't fixed #7921. Doing
Causes |
If NewInt was as simple as: func NewInt(x int64) *Int { I think that would inline and not escape. So we just have to figure out how to preserve that with setting neg and negating x. Maybe sign shifting tricks are enough. On 32-bit it might be harder because sometimes you need two words, but maybe we don't care as much if 32-bit can't be made non-allocating. |
That doesn't work either, unfortunately. The |
I'm probably missing something but can you double check that? My simple test seems to indicate that
|
The |
Is the [1]Word heap-allocated because of Add? |
Ah yes, that's the problem. |
Change https://go.dev/cl/411254 mentions this issue: |
OK, so it sounds like we don't need any new API here once this change lands. |
Thanks @randall77! |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
Mark the assembly routines as not escaping their arguments. Add a special case to NewInt that, when inlined, can do all of its allocations (a big.Int and a [1]Word) on the stack. Update #29951 Change-Id: I9bd38c262eb97df98c0ed9874da7daac381243ea Reviewed-on: https://go-review.googlesource.com/c/go/+/411254 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Run-TryBot: Keith Randall <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
Change https://go.dev/cl/422039 mentions this issue: |
Since when that test requires inlining, which is disabled on noopt builder. Updates #29951 Change-Id: I9d7a0a64015a30d3bfb5ad5d806ea0955657fda3 Reviewed-on: https://go-review.googlesource.com/c/go/+/422039 Run-TryBot: Cuong Manh Le <[email protected]> Auto-Submit: Cuong Manh Le <[email protected]> Reviewed-by: Than McIntosh <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
Mark the assembly routines as not escaping their arguments. Add a special case to NewInt that, when inlined, can do all of its allocations (a big.Int and a [1]Word) on the stack. Update golang#29951 Change-Id: I9bd38c262eb97df98c0ed9874da7daac381243ea Reviewed-on: https://go-review.googlesource.com/c/go/+/411254 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Keith Randall <[email protected]> Run-TryBot: Keith Randall <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
Since when that test requires inlining, which is disabled on noopt builder. Updates golang#29951 Change-Id: I9d7a0a64015a30d3bfb5ad5d806ea0955657fda3 Reviewed-on: https://go-review.googlesource.com/c/go/+/422039 Run-TryBot: Cuong Manh Le <[email protected]> Auto-Submit: Cuong Manh Le <[email protected]> Reviewed-by: Than McIntosh <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]>
Please consider adding big.Int methods
Inc
andDec
which would increase or decrease the given Int by one. It would be similar to the following code, except for the allocation:The motivation is that it is quite common operation and the code using it would be simpler and saving one allocation.
Alternatively, please consider
AddInt(64)
andSubInt(64)
, which would still save one allocation when knowing the increment/decrement fits a (64-bit) machine word.Cursory look at Go source shows that the first alternative could be useful here and here, and the second one here.
Yet another alternative would be to expose intOne from int.go.
The text was updated successfully, but these errors were encountered: