Is there any reason why your package just can't return the original big.Int after pre-allocating: http://play.golang.org/p/WVYWQdtoV- . It doesn't look like your code has any extra functionality on-top of the pre-allocation, so there shouldn't be any need to create a structure where 99% of the code serves to delegate to the internal big.Int value.
It would be less fragile, as a significant change to math/big can easily break your package (or make it less useful due to missing functions), and since it is returning a *big.Int, there isn't the issue of interoperability with existing code that expects *big.Int (no need to pack/unpack big.Int into/from pre128.Int). Also no need for unsafe, and the lack of delegation means that it won't be potentially slower than big.Int.
As a side note, I'm not sure (one of the runtime devs can correct me if I'm wrong), but putting the big.Int(no pointer), and the array in the same struct, means that for the life-time of the big.Int, both the big.Int and the array must be allocated, even though if you have a big.Int big enough to exceed the space of your pre-allocation it cannot be collected. IE: putting a value larger than 2^128 inside a pre128.Int requires the big.Int code to allocate a new slice with more words than pre128's preallocation, but the preallocation can't be collected because it's part of a struct which is in use for the big.Int field. Therefore your code (and mine as well) will hold on to extra, unusable memory, should the pre-allocation not be large enough.
On Saturday, November 10, 2012 6:19:31 PM UTC-8, speter wrote:I have created a thin wrapper package for math/big (big.Int) that allocates an array together with a big.Int and uses it as the initial slice. With this package, "NewInt(x)" only uses one allocation instead of two, and "z.SetInt64(x)" on an uninitialized Int uses no allocations instead of one.
Programs and packages that use big.Int in a self-contained manner can use it as a drop-in replacement for math/big. In addition, NewIntBig(x), Int.SetBigInt(x), Int.BigInt() are provided for interoperability.
Install: go get speter.net/go/exp/math/big/pre128
Import: import big "speter.net/go/exp/math/big/pre128"
Docs: http://speter.net/go/exp/math/big/pre128
As the package name suggests, this version preallocates 128bits, but adjusting it to other sizes is trivial. I have adapted most of the tests for type Int in math/big and those pass but they are disabled for now as the results depend on the Go version (waiting for the build tag for go1.1).
Wrappers for type Rat are not implemented. Wrapping Word in a manner that is API-compatible with math/big requires unsafe; API-incompatible workaround implementations are provided for environments that disallow unsafe.
Whether this brings an overall improvement depends on application access patterns and is yet to be seen. However, use cases which allocate relatively many instances and do relatively few operations on each are more likely to benefit.
Any feedback is welcome.
Peter
--
x[i] = pre128.NewInt(0)
--
--
--
Unspecified behavior. The Go specification tries to be explicit about most properties of the language, but there are some aspects that are undefined. Programs that depend on such unspecified behavior may break in future releases.