Skip to content

Commit

Permalink
add function to fill u256 to bigint (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
it4rb authored Feb 27, 2024
1 parent f1435a2 commit 87c9145
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
44 changes: 44 additions & 0 deletions number/conversion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package number

import (
"encoding/hex"
"math/big"
"math/bits"

"github.com/holiman/uint256"
)

const MaxWords = 256 / bits.UintSize

var MaxU256Hex, _ = hex.DecodeString("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")

// similar to `z.ToBig()` but try to re-use space inside `b` instead of allocating
func FillBig(z *uint256.Int, b *big.Int) {
switch MaxWords { // Compile-time check.
case 4: // 64-bit architectures.
if cap(b.Bits()) < 4 {
// this will resize b, we can be sure that b will only hold at most MaxU256
b.SetBytes(MaxU256Hex)
}
words := b.Bits()[:4]
words[0] = big.Word(z[0])
words[1] = big.Word(z[1])
words[2] = big.Word(z[2])
words[3] = big.Word(z[3])
b.SetBits(words)
case 8: // 32-bit architectures.
if cap(b.Bits()) < 8 {
b.SetBytes(MaxU256Hex)
}
words := b.Bits()[:8]
words[0] = big.Word(z[0])
words[1] = big.Word(z[0] >> 32)
words[2] = big.Word(z[1])
words[3] = big.Word(z[1] >> 32)
words[4] = big.Word(z[2])
words[5] = big.Word(z[2] >> 32)
words[6] = big.Word(z[3])
words[7] = big.Word(z[3] >> 32)
b.SetBits(words)
}
}
50 changes: 50 additions & 0 deletions number/conversion_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package number_test

import (
"fmt"
"math/big"
"testing"

"github.com/KyberNetwork/blockchain-toolkit/integer"
"github.com/KyberNetwork/blockchain-toolkit/number"
"github.com/holiman/uint256"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestFillBig(t *testing.T) {
var err error
var xU256 uint256.Int

for i := 0; i < 200; i++ {
xStr := number.RandNumberHexString(64)

t.Run(fmt.Sprintf("test %s", xStr), func(t *testing.T) {
err = xU256.SetFromHex("0x" + xStr)
require.Nil(t, err)

// known correct value to compare against
xBI, ok := new(big.Int).SetString(xStr, 16)
require.True(t, ok)

// should resize and fill small int
smallBI := big.NewInt(12)
number.FillBig(&xU256, smallBI)
assert.Equal(t, xBI, smallBI)

// should resize and fill big int
largeBI := integer.TenPow(200)
number.FillBig(&xU256, largeBI)
assert.Equal(t, xBI, largeBI)

})
}
}

func BenchmarkFillBig(b *testing.B) {
xU256 := number.Number_1e18
xBI := big.NewInt(0)
for i := 0; i < b.N; i++ {
number.FillBig(xU256, xBI)
}
}

0 comments on commit 87c9145

Please sign in to comment.