While the original plan was to keep uint256 as a part of the primitives module, there has been interest in using the uint256 code now and the primitives module will not be complete and ready for release for quite some time. Also, after further discussion, the general preference is for a separate module that lives at math/uint256 for this code since the primitives module will ultimately be squarely aimed at Decred-specific things while math/uint256 is more generally useful, including many projects outside of Decred as well. Thus, this moves the new uint256 package from the internal staging area to math/uint256 where it will serve as a base for a new math/uint256 module release. Finally, it updates all relevant paths and package README.md accordingly.
1326 lines
35 KiB
Go
1326 lines
35 KiB
Go
// Copyright (c) 2021 The Decred developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package uint256
|
|
|
|
import (
|
|
"fmt"
|
|
"math/big"
|
|
"math/rand"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// These variables are used to help ensure the benchmarks do not elide code.
|
|
var (
|
|
noElideBool bool
|
|
noElideBytes []byte
|
|
noElideInt int
|
|
noElideUint16 uint16
|
|
noElideString string
|
|
)
|
|
|
|
// randBenchVal houses values used throughout the benchmarks that are randomly
|
|
// generated with each run to ensure they are not overfitted.
|
|
type randBenchVal struct {
|
|
buf1 [32]byte
|
|
buf2 [32]byte
|
|
n1 *Uint256
|
|
n2 *Uint256
|
|
n2Low64 *Uint256
|
|
bigN1 *big.Int
|
|
bigN2 *big.Int
|
|
bigN2Low64 *big.Int
|
|
}
|
|
|
|
// randBenchVals houses a slice of the aforementioned randomly-generated values
|
|
// to be used throughout the benchmarks to ensure they are not overfitted.
|
|
var randBenchVals = func() []randBenchVal {
|
|
// Use a unique random seed each benchmark instance.
|
|
seed := time.Now().Unix()
|
|
rng := rand.New(rand.NewSource(seed))
|
|
var zeroArr [32]byte
|
|
|
|
vals := make([]randBenchVal, 512)
|
|
for i := 0; i < len(vals); i++ {
|
|
val := &vals[i]
|
|
if _, err := rng.Read(val.buf1[:]); err != nil {
|
|
panic(fmt.Sprintf("failed to read random: %v", err))
|
|
}
|
|
for val.buf2 == zeroArr {
|
|
if _, err := rng.Read(val.buf2[:]); err != nil {
|
|
panic(fmt.Sprintf("failed to read random: %v", err))
|
|
}
|
|
}
|
|
|
|
val.n1 = new(Uint256).SetBytes(&val.buf1)
|
|
val.n2 = new(Uint256).SetBytes(&val.buf2)
|
|
val.n2Low64 = new(Uint256).SetUint64(val.n2.Uint64())
|
|
val.bigN1 = new(big.Int).SetBytes(val.buf1[:])
|
|
val.bigN2 = new(big.Int).SetBytes(val.buf2[:])
|
|
val.bigN2Low64 = new(big.Int).SetUint64(val.n2.Uint64())
|
|
}
|
|
return vals
|
|
}()
|
|
|
|
// maxUint256Bytes returns the raw bytes for a max value unsigned 256-bit
|
|
// big-endian integer used throughout the benchmarks.
|
|
func maxUint256Bytes() []byte {
|
|
return hexToBytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
|
}
|
|
|
|
// BenchmarkUint256SetBytes benchmarks initializing an unsigned 256-bit integer
|
|
// from bytes in big endian with the specialized type.
|
|
func BenchmarkUint256SetBytes(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
n.SetBytes(&vals[j].buf1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntSetBytes benchmarks initializing an unsigned 256-bit integer
|
|
// from bytes in big endian with stdlib big integers.
|
|
func BenchmarkBigIntSetBytes(b *testing.B) {
|
|
n := new(big.Int)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
n.SetBytes(vals[j].buf1[:])
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256SetBytesLE benchmarks initializing an unsigned 256-bit
|
|
// integer from bytes in little endian with the specialized type.
|
|
func BenchmarkUint256SetBytesLE(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
n.SetBytesLE(&vals[j].buf1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntSetBytesLE benchmarks initializing an unsigned 256-bit integer
|
|
// from bytes in little endian with stdlib big integers.
|
|
func BenchmarkBigIntSetBytesLE(b *testing.B) {
|
|
n := new(big.Int)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
// The big int API only takes the bytes in big endian, so they need
|
|
// to be reversed by the caller. Note that this implementation
|
|
// assumes the buffer is already 32 bytes and is not robust against
|
|
// other cases, but it's good enough for a reasonable benchmark.
|
|
buf := vals[j].buf1[:]
|
|
reversed := make([]byte, len(buf))
|
|
blen := len(buf)
|
|
for i := 0; i < blen/2; i++ {
|
|
reversed[i], reversed[blen-1-i] = buf[blen-1-i], buf[i]
|
|
}
|
|
n.SetBytes(reversed)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Bytes benchmarks unpacking an unsigned 256-bit integer to
|
|
// bytes in big endian with the specialized type.
|
|
func BenchmarkUint256Bytes(b *testing.B) {
|
|
vals := randBenchVals
|
|
var buf [32]byte
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
vals[j].n1.PutBytes(&buf)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntBytes benchmarks unpacking an unsigned 256-bit integer to
|
|
// bytes in big endian with the stdlib big integers.
|
|
func BenchmarkBigIntBytes(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
noElideBytes = vals[j].bigN1.Bytes()
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256BytesLE benchmarks unpacking an unsigned 256-bit integer to
|
|
// bytes in little endian with the specialized type.
|
|
func BenchmarkUint256BytesLE(b *testing.B) {
|
|
vals := randBenchVals
|
|
var buf [32]byte
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
vals[j].n1.PutBytesLE(&buf)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntBytesLE benchmarks unpacking an unsigned 256-bit integer to
|
|
// bytes in little endian with the stdlib big integers.
|
|
func BenchmarkBigIntBytesLE(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
// The big int API only provides the bytes in big endian, so they
|
|
// need to be reversed by the caller. Note that this implementation
|
|
// assumes the buffer is already 32 bytes and is not robust against
|
|
// other cases, but it's good enough for a reasonable benchmark.
|
|
buf := vals[j].bigN1.Bytes()
|
|
blen := len(buf)
|
|
for i := 0; i < blen/2; i++ {
|
|
buf[i], buf[blen-1-i] = buf[blen-1-i], buf[i]
|
|
}
|
|
noElideBytes = buf
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Zero benchmarks zeroing an unsigned 256-bit integer with the
|
|
// specialized type.
|
|
func BenchmarkUint256Zero(b *testing.B) {
|
|
n := new(Uint256).SetByteSlice(maxUint256Bytes())
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
n.Zero()
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntZero benchmarks zeroing an unsigned 256-bit integer with
|
|
// stdlib big integers.
|
|
func BenchmarkBigIntZero(b *testing.B) {
|
|
n := new(big.Int).SetBytes(maxUint256Bytes())
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
n.SetUint64(0)
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256IsZero benchmarks determining if an unsigned 256-bit integer
|
|
// is zero with the specialized type.
|
|
func BenchmarkUint256IsZero(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
noElideBool = vals[j].n1.IsZero()
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntIsZero benchmarks determining if an unsigned 256-bit integer
|
|
// is zero with stdlib big integers.
|
|
func BenchmarkBigIntIsZero(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
noElideBool = vals[j].bigN1.Sign() == 0
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256IsOdd benchmarks determining if an unsigned 256-bit integer
|
|
// is odd with the specialized type.
|
|
func BenchmarkUint256IsOdd(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
noElideBool = vals[j].n1.IsOdd()
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntIsOdd benchmarks determining if an unsigned 256-bit integer is
|
|
// odd with stdlib big integers.
|
|
func BenchmarkBigIntIsOdd(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
noElideBool = vals[j].bigN1.Bit(0) == 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Eq benchmarks determining equality between two unsigned
|
|
// 256-bit integers with the specialized type.
|
|
func BenchmarkUint256Eq(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideBool = val.n1.Eq(val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntEq benchmarks determining equality between two unsigned
|
|
// 256-bit integers with stdlib big integers.
|
|
func BenchmarkBigIntEq(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideBool = val.bigN1.Cmp(val.bigN2) == 0
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Lt benchmarks determining if one unsigned 256-bit integer is
|
|
// less than another with the specialized type.
|
|
func BenchmarkUint256Lt(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideBool = val.n1.Lt(val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntLt benchmarks determining if one unsigned 256-bit integer is
|
|
// less than another with stdlib big integers.
|
|
func BenchmarkBigIntLt(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideBool = val.bigN1.Cmp(val.bigN2) < 0
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Gt benchmarks determining if one unsigned 256-bit integer is
|
|
// greater than another with the specialized type.
|
|
func BenchmarkUint256Gt(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideBool = val.n1.Gt(val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntGt benchmarks determining if one unsigned 256-bit integer is
|
|
// greater than another with stdlib big integers.
|
|
func BenchmarkBigIntGt(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideBool = val.bigN1.Cmp(val.bigN2) > 0
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Cmp benchmarks comparing two unsigned 256-bit integers with
|
|
// the specialized type.
|
|
func BenchmarkUint256Cmp(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideInt = val.n1.Cmp(val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntCmp benchmarks comparing two unsigned 256-bit integers with
|
|
// stdlib big integers.
|
|
func BenchmarkBigIntCmp(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideInt = val.bigN1.Cmp(val.bigN2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256CmpUint64 benchmarks comparing an unsigned 256-bit integer
|
|
// with an unsigned 64-bit integer with the specialized type.
|
|
func BenchmarkUint256CmpUint64(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideInt = val.n1.CmpUint64(val.n2Low64.Uint64())
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntCmp benchmarks comparing an unsigned 256-bit integer with an
|
|
// unsigned 64-bit integer with stdlib big integers.
|
|
func BenchmarkBigIntCmpUint64(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideInt = val.bigN1.Cmp(val.bigN2Low64)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Add benchmarks computing the sum of unsigned 256-bit integers
|
|
// with the specialized type.
|
|
func BenchmarkUint256Add(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Add2(val.n1, val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntAdd benchmarks computing the sum of unsigned 256-bit integers
|
|
// with stdlib big integers.
|
|
func BenchmarkBigIntAdd(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Add(val.bigN1, val.bigN2)
|
|
n.Mod(n, two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256AddUint64 benchmarks computing the sum of an unsigned 256-bit
|
|
// integer and an unsigned 64-bit integer with the specialized type.
|
|
func BenchmarkUint256AddUint64(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.n1)
|
|
n.AddUint64(val.n2Low64.Uint64())
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntAddUint64 benchmarks computing the sum of an unsigned 256-bit
|
|
// integer and an unsigned 64-bit integer with stdlib big integers.
|
|
func BenchmarkBigIntAddUint64(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.bigN1) // For fair comparison.
|
|
n.Add(n, val.bigN2Low64)
|
|
n.Mod(n, two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Sub benchmarks computing the difference of unsigned 256-bit
|
|
// integers with the specialized type.
|
|
func BenchmarkUint256Sub(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Sub2(val.n1, val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntSub benchmarks computing the difference of unsigned 256-bit
|
|
// integers with stdlib big integers.
|
|
func BenchmarkBigIntSub(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Sub(val.bigN1, val.bigN2)
|
|
n.Mod(n, two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256SubUint64 benchmarks computing the difference of an unsigned
|
|
// 256-bit integer and unsigned 64-bit integer with the specialized type.
|
|
func BenchmarkUint256SubUint64(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.n1)
|
|
n.SubUint64(val.n2Low64.Uint64())
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntSubUint64 benchmarks computing the difference of an unsigned
|
|
// 256-bit integer and unsigned 64-bit integer with stdlib big integers.
|
|
func BenchmarkBigIntSubUint64(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.bigN1) // For fair comparison.
|
|
n.Sub(n, val.bigN2Low64)
|
|
n.Mod(n, two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Mul benchmarks computing the product of unsigned 256-bit
|
|
// integers with the specialized type.
|
|
func BenchmarkUint256Mul(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Mul2(val.n1, val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntMul benchmarks computing the product of unsigned 256-bit
|
|
// integers with stdlib big integers.
|
|
func BenchmarkBigIntMul(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Mul(val.bigN1, val.bigN2)
|
|
n.Mod(n, two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256MulUint64 benchmarks computing the product of an unsigned
|
|
// 256-bit integer and unsigned 64-bit integer with the specialized type.
|
|
func BenchmarkUint256MulUint64(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.n1)
|
|
n.MulUint64(val.n2Low64.Uint64())
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntMulUint64 benchmarks computing the product of an unsigned
|
|
// 256-bit integer and unsigned 64-bit integer with stdlib big integers.
|
|
func BenchmarkBigIntMulUint64(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.bigN1) // For fair comparison.
|
|
n.Mul(n, val.bigN2Low64)
|
|
n.Mod(n, two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Square benchmarks computing the quotient of unsigned 256-bit
|
|
// integers with the specialized type.
|
|
func BenchmarkUint256Square(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.SquareVal(val.n1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntSquare benchmarks computing the quotient of unsigned 256-bit
|
|
// integers with stdlib big integers.
|
|
func BenchmarkBigIntSquare(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Mul(val.bigN1, val.bigN1)
|
|
n.Mod(n, two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// divBenchTest describes tests that are used for the deterministic division
|
|
// benchmarks. It is defined separately so the same tests can easily be used in
|
|
// comparison benchmarks between the specialized type in this package and stdlib
|
|
// big integers.
|
|
type divBenchTest struct {
|
|
name string // benchmark description
|
|
n1 *Uint256 // dividend
|
|
n2 *Uint256 // divisor
|
|
}
|
|
|
|
// makeDivBenches returns a slice of tests that consist of deterministic
|
|
// unsigned 256-bit integers of various lengths for use in the division
|
|
// benchmarks.
|
|
func makeDivBenches() []divBenchTest {
|
|
return []divBenchTest{{
|
|
// (1<<256 - 2) / (1<<256 - 1)
|
|
name: "dividend lt divisor",
|
|
n1: hexToUint256("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"),
|
|
n2: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
}, {
|
|
// (1<<256 - 1) / (1<<256 - 1)
|
|
name: "dividend eq divisor",
|
|
n1: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
}, {
|
|
// (1<<64 - 1) / (1<<64 - 255)
|
|
name: "1 by 1 near",
|
|
n1: hexToUint256("000000000000000000000000000000000000000000000000ffffffffffffffff"),
|
|
n2: hexToUint256("000000000000000000000000000000000000000000000000ffffffffffffff01"),
|
|
}, {
|
|
// (1<<64 - 1) / (1<<2 - 1)
|
|
name: "1 by 1 far",
|
|
n1: hexToUint256("000000000000000000000000000000000000000000000000ffffffffffffffff"),
|
|
n2: hexToUint256("0000000000000000000000000000000000000000000000000000000000000003"),
|
|
}, {
|
|
// (1<<128 - 1) / (1<<64 - 1)
|
|
name: "2 by 1 near",
|
|
n1: hexToUint256("00000000000000000000000000000000ffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("000000000000000000000000000000000000000000000000ffffffffffffffff"),
|
|
}, {
|
|
// (1<<128 - 1) / (1<<2 - 1)
|
|
name: "2 by 1 far",
|
|
n1: hexToUint256("00000000000000000000000000000000ffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("0000000000000000000000000000000000000000000000000000000000000003"),
|
|
}, {
|
|
// (1<<192 - 1) / (1<<64 - 1)
|
|
name: "3 by 1 near",
|
|
n1: hexToUint256("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("000000000000000000000000000000000000000000000000ffffffffffffffff"),
|
|
}, {
|
|
// (1<<192 - 1) / (1<<2 - 1)
|
|
name: "3 by 1 far",
|
|
n1: hexToUint256("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("0000000000000000000000000000000000000000000000000000000000000003"),
|
|
}, {
|
|
// (1<<256 - 1) / (1<<64 - 1)
|
|
name: "4 by 1 near",
|
|
n1: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("000000000000000000000000000000000000000000000000ffffffffffffffff"),
|
|
}, {
|
|
// (1<<256 - 1) / (1<<2 - 1)
|
|
name: "4 by 1 far",
|
|
n1: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("0000000000000000000000000000000000000000000000000000000000000003"),
|
|
}, {
|
|
// (1<<128 - 1) / (1<<128 - 255)
|
|
name: "2 by 2 near",
|
|
n1: hexToUint256("00000000000000000000000000000000ffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("00000000000000000000000000000000ffffffffffffffffffffffffffffff01"),
|
|
}, {
|
|
// (1<<128 - 1) / (1<<65 - 1)
|
|
name: "2 by 2 far",
|
|
n1: hexToUint256("00000000000000000000000000000000ffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("000000000000000000000000000000000000000000000001ffffffffffffffff"),
|
|
}, {
|
|
// (1<<192 - 1) / (1<<128 - 1)
|
|
name: "3 by 2 near",
|
|
n1: hexToUint256("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("00000000000000000000000000000000ffffffffffffffffffffffffffffffff"),
|
|
}, {
|
|
// (1<<192 - 1) / (1<<65 - 1)
|
|
name: "3 by 2 far",
|
|
n1: hexToUint256("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("000000000000000000000000000000000000000000000001ffffffffffffffff"),
|
|
}, {
|
|
// (1<<256 - 1) / (1<<128 - 1)
|
|
name: "4 by 2 near",
|
|
n1: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("00000000000000000000000000000000ffffffffffffffffffffffffffffffff"),
|
|
}, {
|
|
// (1<<256 - 1) / (1<<65 - 1)
|
|
name: "4 by 2 far",
|
|
n1: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("000000000000000000000000000000000000000000000001ffffffffffffffff"),
|
|
}, {
|
|
// (1<<192 - 1) / (1<<192 - 255)
|
|
name: "3 by 3 near",
|
|
n1: hexToUint256("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffff01"),
|
|
}, {
|
|
// (1<<192 - 1) / (1<<129 - 1)
|
|
name: "3 by 3 far",
|
|
n1: hexToUint256("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("00000000000000000000000000000001ffffffffffffffffffffffffffffffff"),
|
|
}, {
|
|
// (1<<256 - 1) / (1<<192 - 1)
|
|
name: "4 by 3 near",
|
|
n1: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
}, {
|
|
// (1<<256 - 1) / (1<<129 - 1)
|
|
name: "4 by 3 far",
|
|
n1: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("00000000000000000000000000000001ffffffffffffffffffffffffffffffff"),
|
|
}, {
|
|
// (1<<256 - 1) / (1<<256 - 255)
|
|
name: "4 by 4 near",
|
|
n1: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01"),
|
|
}, {
|
|
// (1<<256 - 1) / (1<<193 - 1)
|
|
name: "4 by 4 far",
|
|
n1: hexToUint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
n2: hexToUint256("0000000000000001ffffffffffffffffffffffffffffffffffffffffffffffff"),
|
|
}}
|
|
}
|
|
|
|
// BenchmarkUint256Div benchmarks computing the quotient of deterministic
|
|
// unsigned 256-bit integers of various length with the specialized type.
|
|
func BenchmarkUint256Div(b *testing.B) {
|
|
benches := makeDivBenches()
|
|
for benchIdx := range benches {
|
|
bench := benches[benchIdx]
|
|
b.Run(bench.name, func(b *testing.B) {
|
|
n := new(Uint256)
|
|
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
n.Div2(bench.n1, bench.n2)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256DivRandom benchmarks computing the quotient of random large
|
|
// unsigned 256-bit integers with the specialized type.
|
|
func BenchmarkUint256DivRandom(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Div2(val.n1, val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntDiv benchmarks computing the quotient of deterministic
|
|
// unsigned 256-bit integers of various length with stdlib big integers.
|
|
func BenchmarkBigIntDiv(b *testing.B) {
|
|
benches := makeDivBenches()
|
|
for benchIdx := range benches {
|
|
bench := benches[benchIdx]
|
|
b.Run(bench.name, func(b *testing.B) {
|
|
n := new(big.Int)
|
|
n1Bytes, n2Bytes := bench.n1.Bytes(), bench.n2.Bytes()
|
|
n1 := new(big.Int).SetBytes(n1Bytes[:])
|
|
n2 := new(big.Int).SetBytes(n2Bytes[:])
|
|
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
n.Div(n1, n2)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntDivRandom benchmarks computing the quotient of random large
|
|
// unsigned 256-bit integers with stdlib big integers.
|
|
func BenchmarkBigIntDivRandom(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Div(val.bigN1, val.bigN2)
|
|
n.Mod(n, two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256DivUint64 benchmarks computing the quotient of an unsigned
|
|
// 256-bit integer and unsigned 64-bit integer with the specialized type.
|
|
func BenchmarkUint256DivUint64(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.n1)
|
|
n.DivUint64(val.n2Low64.Uint64())
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntDivUint64 benchmarks computing the quotient of an unsigned
|
|
// 256-bit integer and unsigned 64-bit integer with stdlib big integers.
|
|
func BenchmarkBigIntDivUint64(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Div(val.bigN1, val.bigN2Low64)
|
|
n.Mod(n, two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Negate benchmarks computing the negation modulo 2^256 of an
|
|
// unsigned 256-bit integer with the specialized type.
|
|
func BenchmarkUint256Negate(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
n.NegateVal(vals[j].n1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntNegate benchmarks computing the negation module 2^256 of an
|
|
// unsigned 256-bit integer with stdlib big integers.
|
|
func BenchmarkBigIntNegate(b *testing.B) {
|
|
n := new(big.Int)
|
|
two256 := new(big.Int).Lsh(big.NewInt(1), 256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
n.Mod(n.Neg(vals[j].bigN1), two256)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Lsh benchmarks left shifting an unsigned 256-bit integer with
|
|
// the specialized type.
|
|
func BenchmarkUint256Lsh(b *testing.B) {
|
|
for _, bits := range []uint32{0, 1, 64, 128, 192, 255, 256} {
|
|
benchName := fmt.Sprintf("bits %d", bits)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
result := new(Uint256)
|
|
max256 := new(Uint256).SetByteSlice(maxUint256Bytes())
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
result.LshVal(max256, bits)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntLsh benchmarks left shifting an unsigned 256-bit integer with
|
|
// stdlib big integers.
|
|
func BenchmarkBigIntLsh(b *testing.B) {
|
|
for _, bits := range []uint{0, 1, 64, 128, 192, 255, 256} {
|
|
benchName := fmt.Sprintf("bits %d", bits)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
result := new(big.Int)
|
|
max256 := new(big.Int).SetBytes(maxUint256Bytes())
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
result.Lsh(max256, bits)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Rsh benchmarks right shifting an unsigned 256-bit integer
|
|
// with the specialized type.
|
|
func BenchmarkUint256Rsh(b *testing.B) {
|
|
for _, bits := range []uint32{0, 1, 64, 128, 192, 255, 256} {
|
|
benchName := fmt.Sprintf("bits %d", bits)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
result := new(Uint256)
|
|
max256 := new(Uint256).SetByteSlice(maxUint256Bytes())
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
result.RshVal(max256, bits)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntRsh benchmarks right shifting an unsigned 256-bit integer with
|
|
// stdlib big integers.
|
|
func BenchmarkBigIntRsh(b *testing.B) {
|
|
for _, bits := range []uint{0, 1, 64, 128, 192, 255, 256} {
|
|
benchName := fmt.Sprintf("bits %d", bits)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
result := new(big.Int)
|
|
max256 := new(big.Int).SetBytes(maxUint256Bytes())
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
result.Rsh(max256, bits)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Not benchmarks computing the bitwise not of an unsigned
|
|
// 256-bit integer with the specialized type.
|
|
func BenchmarkUint256Not(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
n.Set(vals[j].n1)
|
|
n.Not()
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntNot benchmarks computing the bitwise not of an unsigned
|
|
// 256-bit integer with stdlib big integers.
|
|
func BenchmarkBigIntNot(b *testing.B) {
|
|
n := new(big.Int)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
n.Set(vals[j].bigN1) // For fair comparison.
|
|
n.Not(n)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Or benchmarks computing the bitwise or of unsigned 256-bit
|
|
// integers with the specialized type.
|
|
func BenchmarkUint256Or(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.n1)
|
|
n.Or(val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntOr benchmarks computing the bitwise or of unsigned 256-bit
|
|
// integers with stdlib big integers.
|
|
func BenchmarkBigIntOr(b *testing.B) {
|
|
n := new(big.Int)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.bigN1) // For fair comparison.
|
|
n.Or(n, val.bigN2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256And benchmarks computing the bitwise and of unsigned 256-bit
|
|
// integers with the specialized type.
|
|
func BenchmarkUint256And(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.n1)
|
|
n.And(val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntAnd benchmarks computing the bitwise and of unsigned 256-bit
|
|
// integers with stdlib big integers.
|
|
func BenchmarkBigIntAnd(b *testing.B) {
|
|
n := new(big.Int)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.bigN1) // For fair comparison.
|
|
n.And(n, val.bigN2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Xor benchmarks computing the bitwise exclusive or of unsigned
|
|
// 256-bit integers with the specialized type.
|
|
func BenchmarkUint256Xor(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.n1)
|
|
n.Xor(val.n2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntXor benchmarks computing the bitwise exclusive or of unsigned
|
|
// 256-bit integers with stdlib big integers.
|
|
func BenchmarkBigIntXor(b *testing.B) {
|
|
n := new(big.Int)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.Set(val.bigN1) // For fair comparison.
|
|
n.Xor(n, val.bigN2)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256BitLen benchmarks determining the bit length of an unsigned
|
|
// 256-bit integer with the specialized type.
|
|
func BenchmarkUint256BitLen(b *testing.B) {
|
|
for _, bits := range []uint32{64, 128, 192, 255} {
|
|
benchName := fmt.Sprintf("bits %d", bits)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
n := new(Uint256).SetUint64(1).Lsh(bits)
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
noElideUint16 = n.BitLen()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntBitLen benchmarks determining the bit length of an unsigned
|
|
// 256-bit integer with stdlib big integers.
|
|
func BenchmarkBigIntBitLen(b *testing.B) {
|
|
for _, bits := range []uint{64, 128, 192, 255} {
|
|
benchName := fmt.Sprintf("bits %d", bits)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
n := new(big.Int).SetUint64(1)
|
|
n.Lsh(n, bits)
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
noElideInt = n.BitLen()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Text benchmarks converting an unsigned 256-bit integer to
|
|
// various output bases with the specialized type.
|
|
func BenchmarkUint256Text(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
for _, base := range []OutputBase{2, 8, 10, 16} {
|
|
benchName := fmt.Sprintf("base %d", base)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideString = val.n1.Text(base)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntText benchmarks converting an unsigned 256-bit integer to
|
|
// various output bases with stdlib big integers.
|
|
func BenchmarkBigIntText(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
for _, base := range []int{2, 8, 10, 16} {
|
|
benchName := fmt.Sprintf("base %d", base)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideString = val.bigN1.Text(base)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256Format benchmarks formatting an unsigned 256-bit integer to
|
|
// various output bases via fmt.Sprintf with the specialized type.
|
|
func BenchmarkUint256Format(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
for _, base := range []int{2, 8, 10, 16} {
|
|
benchName := fmt.Sprintf("base %d", base)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
var fmtStr string
|
|
switch base {
|
|
case 2:
|
|
fmtStr = "%b"
|
|
case 8:
|
|
fmtStr = "%o"
|
|
case 10:
|
|
fmtStr = "%d"
|
|
case 16:
|
|
fmtStr = "%x"
|
|
}
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideString = fmt.Sprintf(fmtStr, val.n1)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkBigIntFormat benchmarks formatting an unsigned 256-bit integer to
|
|
// various output bases via fmt.Sprintf with stdlib big integers.
|
|
func BenchmarkBigIntFormat(b *testing.B) {
|
|
vals := randBenchVals
|
|
|
|
for _, base := range []int{2, 8, 10, 16} {
|
|
benchName := fmt.Sprintf("base %d", base)
|
|
b.Run(benchName, func(b *testing.B) {
|
|
var fmtStr string
|
|
switch base {
|
|
case 2:
|
|
fmtStr = "%b"
|
|
case 8:
|
|
fmtStr = "%o"
|
|
case 10:
|
|
fmtStr = "%d"
|
|
case 16:
|
|
fmtStr = "%x"
|
|
}
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
noElideString = fmt.Sprintf(fmtStr, val.bigN1)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256PutBig benchmarks converting an unsigned 256-bit integer to a
|
|
// stdlib big integer.
|
|
func BenchmarkUint256PutBig(b *testing.B) {
|
|
n := new(big.Int)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
val.n1.PutBig(n)
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkUint256PutBig benchmarks converting a stdlib big integer to an
|
|
// unsigned 256-bit integer.
|
|
func BenchmarkUint256SetBig(b *testing.B) {
|
|
n := new(Uint256)
|
|
vals := randBenchVals
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i += len(vals) {
|
|
for j := 0; j < len(vals); j++ {
|
|
val := &vals[j]
|
|
n.SetBig(val.bigN1)
|
|
}
|
|
}
|
|
}
|