├── go.mod ├── .gitignore ├── codecov.yml ├── .deepsource.toml ├── AUTHORS ├── div.go ├── conversion_fuzz_test.go ├── COPYING ├── unary_test.go ├── oss-fuzz.sh ├── circle.yml ├── ternary_test.go ├── decimal_test.go ├── decimal.go ├── README.md ├── binary_test.go ├── shared_test.go ├── mod.go ├── conversion.go ├── uint256_test.go ├── benchmarks_test.go └── uint256.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/holiman/uint256 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | 3 | 4 | # go output files 5 | *.test 6 | *.out 7 | *.pb.gz 8 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | require_ci_to_pass: no 3 | 4 | coverage: 5 | status: 6 | project: no 7 | patch: no 8 | 9 | comment: 10 | layout: "diff" 11 | -------------------------------------------------------------------------------- /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | test_patterns = [ 4 | "*/*_test.go", 5 | "*_test.go" 6 | ] 7 | 8 | [[analyzers]] 9 | name = "go" 10 | enabled = true 11 | 12 | [analyzers.meta] 13 | import_paths = ["github.com/holiman/uint256"] -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of uint256 authors for copyright purposes. 2 | 3 | Martin Holst Swende 4 | Guillaume Ballet 5 | Kurkó Mihály 6 | Paweł Bylica 7 | Yao Zengzeng 8 | Dag Arne Osvik 9 | Thanee Charattrakool 10 | 11 | -------------------------------------------------------------------------------- /div.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import "math/bits" 8 | 9 | // reciprocal2by1 computes <^d, ^0> / d. 10 | func reciprocal2by1(d uint64) uint64 { 11 | reciprocal, _ := bits.Div64(^d, ^uint64(0), d) 12 | return reciprocal 13 | } 14 | 15 | // udivrem2by1 divides / d and produces both quotient and remainder. 16 | // It uses the provided d's reciprocal. 17 | // Implementation ported from https://github.com/chfast/intx and is based on 18 | // "Improved division by invariant integers", Algorithm 4. 19 | func udivrem2by1(uh, ul, d, reciprocal uint64) (quot, rem uint64) { 20 | qh, ql := bits.Mul64(reciprocal, uh) 21 | ql, carry := bits.Add64(ql, ul, 0) 22 | qh, _ = bits.Add64(qh, uh, carry) 23 | qh++ 24 | 25 | r := ul - qh*d 26 | 27 | if r > ql { 28 | qh-- 29 | r += d 30 | } 31 | 32 | if r >= d { 33 | qh++ 34 | r -= d 35 | } 36 | 37 | return qh, r 38 | } 39 | -------------------------------------------------------------------------------- /conversion_fuzz_test.go: -------------------------------------------------------------------------------- 1 | package uint256 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | "testing" 7 | ) 8 | 9 | func testSetFromDecForFuzzing(tc string) error { 10 | a := new(Int).SetAllOne() 11 | err := a.SetFromDecimal(tc) 12 | // If input is negative, we should eror 13 | if len(tc) > 0 && tc[0] == '-' { 14 | if err == nil { 15 | return fmt.Errorf("want error on negative input") 16 | } 17 | return nil 18 | } 19 | // Need to compare with big.Int 20 | bigA, ok := big.NewInt(0).SetString(tc, 10) 21 | if !ok { 22 | if err == nil { 23 | return fmt.Errorf("want error") 24 | } 25 | return nil // both agree that input is bad 26 | } 27 | if bigA.BitLen() > 256 { 28 | if err == nil { 29 | return fmt.Errorf("want error (bitlen > 256)") 30 | } 31 | return nil 32 | } 33 | want := bigA.String() 34 | have := a.Dec() 35 | if want != have { 36 | return fmt.Errorf("want %v, have %v", want, have) 37 | } 38 | if _, err := a.Value(); err != nil { 39 | return fmt.Errorf("fail to Value() %s, got err %s", tc, err) 40 | } 41 | return nil 42 | } 43 | 44 | func FuzzSetString(f *testing.F) { 45 | f.Fuzz(func(t *testing.T, data []byte) { 46 | if len(data) > 512 { 47 | return 48 | } 49 | if err := testSetFromDecForFuzzing(string(data)); err != nil { 50 | t.Fatal(err) 51 | } 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright 2020 uint256 Authors 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /unary_test.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "fmt" 9 | "math/big" 10 | "testing" 11 | ) 12 | 13 | type opUnaryArgFunc func(*Int, *Int) *Int 14 | type bigUnaryArgFunc func(*big.Int, *big.Int) *big.Int 15 | 16 | var unaryOpFuncs = []struct { 17 | name string 18 | u256Fn opUnaryArgFunc 19 | bigFn bigUnaryArgFunc 20 | }{ 21 | {"Not", (*Int).Not, (*big.Int).Not}, 22 | {"Neg", (*Int).Neg, (*big.Int).Neg}, 23 | {"Sqrt", (*Int).Sqrt, (*big.Int).Sqrt}, 24 | {"square", func(x *Int, y *Int) *Int { 25 | res := y.Clone() 26 | res.squared() 27 | return x.Set(res) 28 | }, func(b1, b2 *big.Int) *big.Int { return b1.Mul(b2, b2) }}, 29 | {"Abs", (*Int).Abs, func(b1, b2 *big.Int) *big.Int { return b1.Abs(bigS256(b2)) }}, 30 | } 31 | 32 | func checkUnaryOperation(t *testing.T, opName string, op opUnaryArgFunc, bigOp bigUnaryArgFunc, x Int) { 33 | var ( 34 | b1 = x.ToBig() 35 | f1 = x.Clone() 36 | operation = fmt.Sprintf("op: %v ( %v ) ", opName, x.Hex()) 37 | want, _ = FromBig(bigOp(new(big.Int), b1)) 38 | have = op(new(Int), f1) 39 | ) 40 | // Compare result with big.Int. 41 | if !have.Eq(want) { 42 | t.Fatalf("%v\nwant : %#x\nhave : %#x\n", operation, want, have) 43 | } 44 | // Check if arguments are unmodified. 45 | if !f1.Eq(x.Clone()) { 46 | t.Fatalf("%v\nfirst argument had been modified: %x", operation, f1) 47 | } 48 | // Check if reusing args as result works correctly. 49 | have = op(f1, f1) 50 | if have != f1 { 51 | t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f1) 52 | } 53 | if !have.Eq(want) { 54 | t.Fatalf("%v\n on argument reuse x.op(x)\nwant : %#x\nhave : %#x\n", operation, want, have) 55 | } 56 | } 57 | 58 | func TestUnaryOperations(t *testing.T) { 59 | for _, tc := range unaryOpFuncs { 60 | for _, arg := range unTestCases { 61 | f1 := MustFromHex(arg) 62 | checkUnaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1) 63 | } 64 | } 65 | } 66 | 67 | func FuzzUnaryOperations(f *testing.F) { 68 | f.Fuzz(func(t *testing.T, x0, x1, x2, x3 uint64) { 69 | x := Int{x0, x1, x2, x3} 70 | for _, tc := range unaryOpFuncs { 71 | checkUnaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, x) 72 | } 73 | }) 74 | } 75 | -------------------------------------------------------------------------------- /oss-fuzz.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | # This sets the -coverpgk for the coverage report when the corpus is executed through go test 4 | coverpkg="github.com/holiman/uint256/..." 5 | 6 | (cd /src/ && git clone https://github.com/holiman/gofuzz-shim.git ) 7 | 8 | function coverbuild { 9 | path=$1 10 | function=$2 11 | fuzzer=$3 12 | tags="" 13 | 14 | if [[ $# -eq 4 ]]; then 15 | tags="-tags $4" 16 | fi 17 | cd $path 18 | fuzzed_package=`pwd | rev | cut -d'/' -f 1 | rev` 19 | cp /src/gofuzz-shim/coverage_runner_template.txt ./"${function,,}"_test.go 20 | sed -i -e 's/FuzzFunction/'$function'/' ./"${function,,}"_test.go 21 | sed -i -e 's/mypackagebeingfuzzed/'$fuzzed_package'/' ./"${function,,}"_test.go 22 | sed -i -e 's/TestFuzzCorpus/Test'$function'Corpus/' ./"${function,,}"_test.go 23 | 24 | cat << DOG > $OUT/$fuzzer 25 | #/bin/sh 26 | 27 | cd $OUT/$path 28 | go test -run Test${function}Corpus -v $tags -coverprofile \$1 -coverpkg $coverpkg 29 | 30 | DOG 31 | 32 | chmod +x $OUT/$fuzzer 33 | #echo "Built script $OUT/$fuzzer" 34 | #cat $OUT/$fuzzer 35 | cd - 36 | } 37 | 38 | repo=/src/uint256 39 | 40 | function compile_fuzzer() { 41 | package=$1 42 | function=$2 43 | fuzzer=$3 44 | file=$4 45 | 46 | path=$repo 47 | 48 | echo "Building $fuzzer" 49 | cd $path 50 | 51 | # Install build dependencies 52 | go mod tidy 53 | go get github.com/holiman/gofuzz-shim/testing 54 | 55 | if [[ $SANITIZER == *coverage* ]]; then 56 | coverbuild $path $function $fuzzer $coverpkg 57 | else 58 | gofuzz-shim --func $function --package $package -f $file -o $fuzzer.a 59 | $CXX $CXXFLAGS $LIB_FUZZING_ENGINE $fuzzer.a -o $OUT/$fuzzer 60 | fi 61 | 62 | ## Check if there exists a seed corpus file 63 | corpusfile="${path}/testdata/${fuzzer}_seed_corpus.zip" 64 | if [ -f $corpusfile ] 65 | then 66 | cp $corpusfile $OUT/ 67 | echo "Found seed corpus: $corpusfile" 68 | fi 69 | cd - 70 | } 71 | 72 | go install github.com/holiman/gofuzz-shim@latest 73 | 74 | 75 | compile_fuzzer github.com/holiman/uint256 FuzzUnaryOperations fuzzUnary $repo/unary_test.go,$repo/shared_test.go 76 | compile_fuzzer github.com/holiman/uint256 FuzzBinaryOperations fuzzBinary $repo/binary_test.go,$repo/shared_test.go 77 | compile_fuzzer github.com/holiman/uint256 FuzzCompareOperations fuzzCompare $repo/binary_test.go,$repo/shared_test.go 78 | compile_fuzzer github.com/holiman/uint256 FuzzTernaryOperations fuzzTernary $repo/ternary_test.go,$repo/shared_test.go 79 | compile_fuzzer github.com/holiman/uint256 FuzzSetString fuzzSetString $repo/conversion_fuzz_test.go,$repo/shared_test.go 80 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | commands: 4 | test: 5 | parameters: 6 | arch: 7 | default: "amd64" 8 | description: The target architecture. 9 | type: enum 10 | enum: ["amd64", "386"] 11 | steps: 12 | - run: 13 | name: "Test (<>)" 14 | command: | 15 | export GOARCH=<> 16 | go version 17 | go env 18 | go test -v -coverprofile=coverage-<>.txt -covermode=count 19 | 20 | jobs: 21 | 22 | go124: 23 | docker: 24 | - image: cimg/go:1.24 25 | steps: 26 | - run: 27 | name: "Install tools" 28 | command: | 29 | curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.5 30 | - checkout 31 | - run: 32 | name: "Lint" 33 | command: golangci-lint run 34 | - test: 35 | arch: "amd64" 36 | - test: 37 | arch: "386" 38 | - run: 39 | name: "Codecov upload" 40 | command: bash <(curl -s https://codecov.io/bash) 41 | - restore_cache: 42 | keys: 43 | - corpus-v3 44 | - run: 45 | name: "Fuzzing" 46 | command: | 47 | GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzBinaryOperations -fuzztime 20s 48 | GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzCompareOperations -fuzztime 20s 49 | GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzTernaryOperations -fuzztime 20s 50 | GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzBase10StringCompare -fuzztime 10s 51 | GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzDecimal -fuzztime 10s 52 | GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzFloat64 -fuzztime 10s 53 | GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzLog10 -fuzztime 10s 54 | GOCACHE=/home/circleci/project/corpus-v3 go test . -run - -fuzz FuzzSetString -fuzztime 10s 55 | - save_cache: 56 | key: corpus-v3-{{ epoch }} 57 | paths: 58 | - corpus-v3 59 | - run: 60 | name: "Benchmark" 61 | command: go test -run=- -bench=. -benchmem 62 | - run: 63 | name: "Build tests for PPC64" 64 | command: | 65 | GOARCH=ppc64 go test -c 66 | mv uint256.test uint256.test.ppc64 67 | - persist_to_workspace: 68 | root: . 69 | paths: 70 | - uint256.test.* 71 | 72 | bigendian: 73 | docker: 74 | - image: cimg/base:current 75 | steps: 76 | - run: 77 | name: "Install QEMU" 78 | command: sudo apt-get -q update && sudo apt-get -qy install qemu-user-static --no-install-recommends 79 | - attach_workspace: 80 | at: . 81 | - run: 82 | name: "Test (PPC64 emulation)" 83 | command: qemu-ppc64-static uint256.test.ppc64 -test.v 84 | 85 | go123: 86 | docker: 87 | - image: cimg/go:1.23 88 | steps: 89 | - checkout 90 | - test 91 | 92 | go122: 93 | docker: 94 | - image: cimg/go:1.22 95 | steps: 96 | - checkout 97 | - test 98 | 99 | go121: 100 | docker: 101 | - image: cimg/go:1.21 102 | steps: 103 | - checkout 104 | - test 105 | 106 | go120: 107 | docker: 108 | - image: cimg/go:1.20 109 | steps: 110 | - checkout 111 | - test 112 | 113 | go119: 114 | docker: 115 | - image: cimg/go:1.19 116 | steps: 117 | - checkout 118 | - test 119 | 120 | 121 | 122 | workflows: 123 | version: 2 124 | uint256: 125 | jobs: 126 | - go119 127 | - go120 128 | - go121 129 | - go122 130 | - go123 131 | - go124: 132 | requires: 133 | - go123 134 | - bigendian: 135 | requires: 136 | - go124 137 | -------------------------------------------------------------------------------- /ternary_test.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "fmt" 9 | "math/big" 10 | "testing" 11 | ) 12 | 13 | type opThreeArgFunc func(*Int, *Int, *Int, *Int) *Int 14 | type bigThreeArgFunc func(*big.Int, *big.Int, *big.Int, *big.Int) *big.Int 15 | 16 | var ternaryOpFuncs = []struct { 17 | name string 18 | u256Fn opThreeArgFunc 19 | bigFn bigThreeArgFunc 20 | }{ 21 | {"AddMod", (*Int).AddMod, bigAddMod}, 22 | {"MulMod", (*Int).MulMod, bigMulMod}, 23 | {"MulModWithReciprocal", (*Int).mulModWithReciprocalWrapper, bigMulMod}, 24 | {"DivModZ", divModZ, bigDivModZ}, 25 | {"DivModM", divModM, bigDivModM}, 26 | } 27 | 28 | func checkTernaryOperation(t *testing.T, opName string, op opThreeArgFunc, bigOp bigThreeArgFunc, x, y, z Int) { 29 | var ( 30 | f1orig = x.Clone() 31 | f2orig = y.Clone() 32 | f3orig = z.Clone() 33 | b1 = x.ToBig() 34 | b2 = y.ToBig() 35 | b3 = z.ToBig() 36 | f1 = new(Int).Set(f1orig) 37 | f2 = new(Int).Set(f2orig) 38 | f3 = new(Int).Set(f3orig) 39 | operation = fmt.Sprintf("op: %v ( %v, %v, %v ) ", opName, x.Hex(), y.Hex(), z.Hex()) 40 | want, _ = FromBig(bigOp(new(big.Int), b1, b2, b3)) 41 | have = op(new(Int), f1, f2, f3) 42 | ) 43 | if !have.Eq(want) { 44 | t.Fatalf("%v\nwant : %#x\nhave : %#x\n", operation, want, have) 45 | } 46 | // Check if arguments are unmodified. 47 | if !f1.Eq(f1orig) { 48 | t.Fatalf("%v\nfirst argument had been modified: %x", operation, f1) 49 | } 50 | if !f2.Eq(f2orig) { 51 | t.Fatalf("%v\nsecond argument had been modified: %x", operation, f2) 52 | } 53 | if !f3.Eq(f3orig) { 54 | if opName != "DivModZ" && opName != "DivModM" { 55 | // DivMod takes m as third argument, modifies it, and returns it. That is by design. 56 | t.Fatalf("%v\nthird argument had been modified: %x", operation, f3) 57 | } 58 | } 59 | // Check if reusing args as result works correctly. 60 | if have = op(f1, f1, f2orig, f3orig); have != f1 { 61 | t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f1) 62 | } else if !have.Eq(want) { 63 | t.Fatalf("%v\non argument reuse x.op(x,y,z)\nwant : %#x\nhave : %#x\n", operation, want, have) 64 | } 65 | 66 | if have = op(f2, f1orig, f2, f3orig); have != f2 { 67 | t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f2) 68 | } else if !have.Eq(want) { 69 | t.Fatalf("%v\non argument reuse y.op(x,y,z)\nwant : %#x\nhave : %#x\n", operation, want, have) 70 | } 71 | 72 | if have = op(f3, f1orig, f2orig, f3); have != f3 { 73 | t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f3) 74 | } else if !have.Eq(want) { 75 | t.Fatalf("%v\non argument reuse z.op(x,y,z)\nwant : %#x\nhave : %#x\n", operation, want, have) 76 | } 77 | } 78 | 79 | func TestTernaryOperations(t *testing.T) { 80 | for _, tc := range ternaryOpFuncs { 81 | for _, inputs := range ternTestCases { 82 | f1 := MustFromHex(inputs[0]) 83 | f2 := MustFromHex(inputs[1]) 84 | f3 := MustFromHex(inputs[2]) 85 | t.Run(tc.name, func(t *testing.T) { 86 | checkTernaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2, *f3) 87 | }) 88 | } 89 | } 90 | } 91 | 92 | func FuzzTernaryOperations(f *testing.F) { 93 | f.Fuzz(func(t *testing.T, 94 | x0, x1, x2, x3, 95 | y0, y1, y2, y3, 96 | z0, z1, z2, z3 uint64) { 97 | 98 | x := Int{x0, x1, x2, x3} 99 | y := Int{y0, y1, y2, y3} 100 | z := Int{z0, z1, z2, z3} 101 | for _, tc := range ternaryOpFuncs { 102 | checkTernaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, x, y, z) 103 | } 104 | }) 105 | } 106 | 107 | func bigAddMod(result, x, y, mod *big.Int) *big.Int { 108 | if mod.Sign() == 0 { 109 | return result.SetUint64(0) 110 | } 111 | return result.Mod(result.Add(x, y), mod) 112 | } 113 | 114 | func bigMulMod(result, x, y, mod *big.Int) *big.Int { 115 | if mod.Sign() == 0 { 116 | return result.SetUint64(0) 117 | } 118 | return result.Mod(result.Mul(x, y), mod) 119 | } 120 | 121 | func (z *Int) mulModWithReciprocalWrapper(x, y, mod *Int) *Int { 122 | mu := Reciprocal(mod) 123 | return z.MulModWithReciprocal(x, y, mod, &mu) 124 | } 125 | 126 | func (z *Int) iMulModWithReciprocalWrapper(x, mod *Int) *Int { 127 | mu := Reciprocal(mod) 128 | return z.IMulModWithReciprocal(x, mod, &mu) 129 | } 130 | 131 | func divModZ(z, x, y, m *Int) *Int { 132 | z2, _ := z.DivMod(x, y, m) 133 | return z2 134 | } 135 | 136 | func bigDivModZ(result, x, y, mod *big.Int) *big.Int { 137 | if y.Sign() == 0 { 138 | return result.SetUint64(0) 139 | } 140 | z2, _ := result.DivMod(x, y, mod) 141 | return z2 142 | } 143 | 144 | func divModM(z, x, y, m *Int) *Int { 145 | _, m2 := z.DivMod(x, y, m) 146 | return z.Set(m2) 147 | } 148 | 149 | func bigDivModM(result, x, y, mod *big.Int) *big.Int { 150 | if y.Sign() == 0 { 151 | return result.SetUint64(0) 152 | } 153 | _, m2 := result.DivMod(x, y, mod) 154 | return result.Set(m2) 155 | } 156 | -------------------------------------------------------------------------------- /decimal_test.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "errors" 9 | "fmt" 10 | "math/big" 11 | "testing" 12 | ) 13 | 14 | // Test SetFromDecimal 15 | func testSetFromDec(tc string) error { 16 | a := new(Int).SetAllOne() 17 | err := a.SetFromDecimal(tc) 18 | { // Check the FromDecimal too 19 | b, err2 := FromDecimal(tc) 20 | if (err == nil) != (err2 == nil) { 21 | return fmt.Errorf("err != err2: %v %v", err, err2) 22 | } 23 | // Test the MustFromDecimal too 24 | if err != nil { 25 | if !causesPanic(func() { MustFromDecimal(tc) }) { 26 | return errors.New("expected panic") 27 | } 28 | } else { 29 | MustFromDecimal(tc) // must not manic 30 | } 31 | if err == nil { 32 | if a.Cmp(b) != 0 { 33 | return fmt.Errorf("a != b: %v %v", a, b) 34 | } 35 | } 36 | } 37 | // If input is negative, we should eror 38 | if len(tc) > 0 && tc[0] == '-' { 39 | if err == nil { 40 | return fmt.Errorf("want error on negative input") 41 | } 42 | return nil 43 | } 44 | // Need to compare with big.Int 45 | bigA, ok := big.NewInt(0).SetString(tc, 10) 46 | if !ok { 47 | if err == nil { 48 | return fmt.Errorf("want error") 49 | } 50 | return nil // both agree that input is bad 51 | } 52 | if bigA.BitLen() > 256 { 53 | if err == nil { 54 | return fmt.Errorf("want error (bitlen > 256)") 55 | } 56 | return nil 57 | } 58 | want := bigA.String() 59 | have := a.Dec() 60 | if want != have { 61 | return fmt.Errorf("want %v, have %v", want, have) 62 | } 63 | return nil 64 | } 65 | 66 | var cases = []string{ 67 | "0000000000000000000000000000000000000000000000000000000000000000000000000000000", 68 | "0000000000000000000000000000000000000000000000000000000000000000000000000000097", 69 | "-000000000000000000000000000000000000000000000000000000000000000000000000000000", 70 | "1157920892373161954235709850086879078532699846656405640394575840079131296399351", 71 | "215792089237316195423570985008687907853269984665640564039457584007913129639935", 72 | "115792089237316195423570985008687907853269984665640564039457584007913129639935", 73 | "15792089237316195423570985008687907853269984665640564039457584007913129639935", 74 | "+115792089237316195423570985008687907853269984665640564039457584007913129639935", 75 | "115792089237316195423570985008687907853269984665640564039457584007913129639936", 76 | "115792089237316195423570985008687907853269984665640564039457584007913129639935", 77 | "+0b00000000000000000000000000000000000000000000000000000000000000010", 78 | "340282366920938463463374607431768211456", 79 | "3402823669209384634633746074317682114561", 80 | "+3402823669209384634633746074317682114561", 81 | "+-3402823669209384634633746074317682114561", 82 | "40282366920938463463374607431768211456", 83 | "00000000000000000000000097", 84 | "184467440737095516161", 85 | "8446744073709551616", 86 | "banana", 87 | "+0x10", 88 | "000", 89 | "+000", 90 | "010", 91 | "0xab", 92 | "-10", 93 | "01", 94 | "ab", 95 | "0", 96 | "-0", 97 | "+0", 98 | "", 99 | "熊熊熊熊熊熊熊熊", 100 | "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 101 | "-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 102 | "0x10101011010", 103 | "熊熊熊熊熊熊熊熊", 104 | "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 105 | "-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 106 | "-0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 107 | "0x10000000000000000000000000000000000000000000000000000000000000000", 108 | "+0x10000000000000000000000000000000000000000000000000000000000000000", 109 | "+0x00000000000000000000000000000000000000000000000000000000000000000", 110 | "-0x00000000000000000000000000000000000000000000000000000000000000000", 111 | } 112 | 113 | func TestStringScan(t *testing.T) { 114 | for i, tc := range cases { 115 | if err := testSetFromDec(tc); err != nil { 116 | t.Errorf("test %d, input '%s', SetFromDecimal err: %v", i, tc, err) 117 | } 118 | // TODO testSetFromHex(tc) 119 | } 120 | } 121 | 122 | func FuzzBase10StringCompare(f *testing.F) { 123 | for _, tc := range cases { 124 | f.Add(tc) 125 | } 126 | f.Fuzz(func(t *testing.T, tc string) { 127 | if err := testSetFromDec(tc); err != nil { 128 | t.Errorf("input '%s', SetFromDecimal err: %v", tc, err) 129 | } 130 | // TODO testSetFromHex(tc) 131 | }) 132 | } 133 | 134 | func BenchmarkFromDecimalString(b *testing.B) { 135 | input := twoPow256Sub1 136 | 137 | b.Run("big", func(b *testing.B) { 138 | val := new(big.Int) 139 | b.ReportAllocs() 140 | b.ResetTimer() 141 | for i := 0; i < b.N; i++ { 142 | for j := 1; j < len(input); j++ { 143 | if _, ok := val.SetString(input[:j], 10); !ok { 144 | b.Fatalf("Error on %v", string(input[:j])) 145 | } 146 | } 147 | } 148 | }) 149 | 150 | b.Run("uint256", func(b *testing.B) { 151 | val := new(Int) 152 | b.ReportAllocs() 153 | b.ResetTimer() 154 | for i := 0; i < b.N; i++ { 155 | for j := 1; j < len(input); j++ { 156 | if err := val.SetFromDecimal(input[:j]); err != nil { 157 | b.Fatalf("%v: %v", err, string(input[:j])) 158 | } 159 | } 160 | } 161 | }) 162 | } 163 | -------------------------------------------------------------------------------- /decimal.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "io" 9 | "strconv" 10 | ) 11 | 12 | const twoPow256Sub1 = "115792089237316195423570985008687907853269984665640564039457584007913129639935" 13 | 14 | // Dec returns the decimal representation of z. 15 | func (z *Int) Dec() string { 16 | if z.IsZero() { 17 | return "0" 18 | } 19 | if z.IsUint64() { 20 | return strconv.FormatUint(z.Uint64(), 10) 21 | } 22 | // The max uint64 value being 18446744073709551615, the largest 23 | // power-of-ten below that is 10000000000000000000. 24 | // When we do a DivMod using that number, the remainder that we 25 | // get back is the lower part of the output. 26 | // 27 | // The ascii-output of remainder will never exceed 19 bytes (since it will be 28 | // below 10000000000000000000). 29 | // 30 | // Algorithm example using 100 as divisor 31 | // 32 | // 12345 % 100 = 45 (rem) 33 | // 12345 / 100 = 123 (quo) 34 | // -> output '45', continue iterate on 123 35 | var ( 36 | // out is 98 bytes long: 78 (max size of a string without leading zeroes, 37 | // plus slack so we can copy 19 bytes every iteration). 38 | // We init it with zeroes, because when strconv appends the ascii representations, 39 | // it will omit leading zeroes. 40 | out = []byte("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") 41 | divisor = NewInt(10000000000000000000) // 20 digits 42 | y = new(Int).Set(z) // copy to avoid modifying z 43 | pos = len(out) // position to write to 44 | buf = make([]byte, 0, 19) // buffer to write uint64:s to 45 | ) 46 | for { 47 | // Obtain Q and R for divisor 48 | var quot, rem Int 49 | udivrem(quot[:], y[:], divisor, &rem) 50 | y.Set(") // Set Q for next loop 51 | // Convert the R to ascii representation 52 | buf = strconv.AppendUint(buf[:0], rem.Uint64(), 10) 53 | // Copy in the ascii digits 54 | copy(out[pos-len(buf):], buf) 55 | if y.IsZero() { 56 | break 57 | } 58 | // Move 19 digits left 59 | pos -= 19 60 | } 61 | // skip leading zeroes by only using the 'used size' of buf 62 | return string(out[pos-len(buf):]) 63 | } 64 | 65 | // PrettyDec returns the decimal representation of z, with thousands-separators. 66 | func (z *Int) PrettyDec(separator byte) string { 67 | if z.IsZero() { 68 | return "0" 69 | } 70 | // See algorithm-description in Dec() 71 | // This just also inserts comma while copying byte-for-byte instead 72 | // of using copy(). 73 | var ( 74 | out = []byte("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") 75 | divisor = NewInt(10000000000000000000) 76 | y = new(Int).Set(z) // copy to avoid modifying z 77 | pos = len(out) - 1 // position to write to 78 | buf = make([]byte, 0, 19) // buffer to write uint64:s to 79 | comma = 0 80 | ) 81 | for { 82 | var quot, rem Int 83 | udivrem(quot[:], y[:], divisor, &rem) 84 | y.Set(") // Set Q for next loop 85 | buf = strconv.AppendUint(buf[:0], rem.Uint64(), 10) 86 | for j := len(buf) - 1; j >= 0; j-- { 87 | if comma == 3 { 88 | out[pos] = separator 89 | pos-- 90 | comma = 0 91 | } 92 | out[pos] = buf[j] 93 | comma++ 94 | pos-- 95 | } 96 | if y.IsZero() { 97 | break 98 | } 99 | // Need to do zero-padding if we have more iterations coming 100 | for j := 0; j < 19-len(buf); j++ { 101 | if comma == 3 { 102 | out[pos] = separator 103 | pos-- 104 | comma = 0 105 | } 106 | comma++ 107 | pos-- 108 | } 109 | } 110 | return string(out[pos+1:]) 111 | } 112 | 113 | // FromDecimal is a convenience-constructor to create an Int from a 114 | // decimal (base 10) string. Numbers larger than 256 bits are not accepted. 115 | func FromDecimal(decimal string) (*Int, error) { 116 | var z Int 117 | if err := z.SetFromDecimal(decimal); err != nil { 118 | return nil, err 119 | } 120 | return &z, nil 121 | } 122 | 123 | // MustFromDecimal is a convenience-constructor to create an Int from a 124 | // decimal (base 10) string. 125 | // Returns a new Int and panics if any error occurred. 126 | func MustFromDecimal(decimal string) *Int { 127 | var z Int 128 | if err := z.SetFromDecimal(decimal); err != nil { 129 | panic(err) 130 | } 131 | return &z 132 | } 133 | 134 | // SetFromDecimal sets z from the given string, interpreted as a decimal number. 135 | // OBS! This method is _not_ strictly identical to the (*big.Int).SetString(..., 10) method. 136 | // Notable differences: 137 | // - This method does not accept underscore input, e.g. "100_000", 138 | // - This method does not accept negative zero as valid, e.g "-0", 139 | // - (this method does not accept any negative input as valid)) 140 | func (z *Int) SetFromDecimal(s string) (err error) { 141 | // Remove max one leading + 142 | if len(s) > 0 && s[0] == '+' { 143 | s = s[1:] 144 | } 145 | // Remove any number of leading zeroes 146 | if len(s) > 0 && s[0] == '0' { 147 | var i int 148 | var c rune 149 | for i, c = range s { 150 | if c != '0' { 151 | break 152 | } 153 | } 154 | s = s[i:] 155 | } 156 | if len(s) < len(twoPow256Sub1) { 157 | return z.fromDecimal(s) 158 | } 159 | if len(s) == len(twoPow256Sub1) { 160 | if s > twoPow256Sub1 { 161 | return ErrBig256Range 162 | } 163 | return z.fromDecimal(s) 164 | } 165 | return ErrBig256Range 166 | } 167 | 168 | // multipliers holds the values that are needed for fromDecimal 169 | var multipliers = [5]*Int{ 170 | nil, // represents first round, no multiplication needed 171 | {10000000000000000000, 0, 0, 0}, // 10 ^ 19 172 | {687399551400673280, 5421010862427522170, 0, 0}, // 10 ^ 38 173 | {5332261958806667264, 17004971331911604867, 2938735877055718769, 0}, // 10 ^ 57 174 | {0, 8607968719199866880, 532749306367912313, 1593091911132452277}, // 10 ^ 76 175 | } 176 | 177 | // fromDecimal is a helper function to only ever be called via SetFromDecimal 178 | // this function takes a string and chunks it up, calling ParseUint on it up to 5 times 179 | // these chunks are then multiplied by the proper power of 10, then added together. 180 | // Note: this method assumes that some basic validity-checks have already been performed 181 | // on the input 'bs'. See SetFromDecimal. 182 | func (z *Int) fromDecimal(bs string) error { 183 | // first clear the input 184 | z.Clear() 185 | // the maximum value of uint64 is 18446744073709551615, which is 20 characters 186 | // one less means that a string of 19 9's is always within the uint64 limit 187 | var ( 188 | num uint64 189 | err error 190 | remaining = len(bs) 191 | ) 192 | if remaining == 0 { 193 | return io.EOF 194 | } 195 | // We proceed in steps of 19 characters (nibbles), from least significant to most significant. 196 | // This means that the first (up to) 19 characters do not need to be multiplied. 197 | // In the second iteration, our slice of 19 characters needs to be multipleied 198 | // by a factor of 10^19. Et cetera. 199 | for i, mult := range multipliers { 200 | if remaining <= 0 { 201 | return nil // Done 202 | } else if remaining > 19 { 203 | num, err = strconv.ParseUint(bs[remaining-19:remaining], 10, 64) 204 | } else { 205 | // Final round 206 | num, err = strconv.ParseUint(bs, 10, 64) 207 | } 208 | if err != nil { 209 | return err 210 | } 211 | // add that number to our running total 212 | if i == 0 { 213 | z.SetUint64(num) 214 | } else { 215 | base := NewInt(num) 216 | z.Add(z, base.Mul(base, mult)) 217 | } 218 | // Chop off another 19 characters 219 | if remaining > 19 { 220 | bs = bs[0 : remaining-19] 221 | } 222 | remaining -= 19 223 | } 224 | return nil 225 | } 226 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Fixed size 256-bit math library 2 | 3 | This is a library specialized at replacing the big.Int library for math based on 256-bit types, used by both 4 | [go-ethereum](https://github.com/ethereum/go-ethereum) and [erigon](https://github.com/ledgerwatch/erigon). 5 | 6 | [![Go Reference](https://pkg.go.dev/badge/github.com/holiman/uint256.svg)](https://pkg.go.dev/github.com/holiman/uint256) 7 | [![codecov](https://codecov.io/gh/holiman/uint256/branch/master/graph/badge.svg?token=LHs7xL99wQ)](https://codecov.io/gh/holiman/uint256) 8 | [![DeepSource](https://deepsource.io/gh/holiman/uint256.svg/?label=active+issues&token=CNJRIm7wXZdOM9xKKH4hXUKd)](https://deepsource.io/gh/holiman/uint256/?ref=repository-badge) 9 | 10 | ## Benchmarks 11 | 12 | Current benchmarks, with tests ending with `big` being the standard `big.Int` library, and `uint256` being this library. 13 | 14 | ### Current status 15 | 16 | - As of 2020-03-18, `uint256` wins over `math/big` in every single case, often with orders of magnitude. 17 | - And as of release `0.1.0`, the `uint256` library is alloc-free. 18 | - With the `1.0.0` release, it also has `100%` test coverage. 19 | 20 | ### Bitwise 21 | 22 | | benchmark | `u256` time/op | `big` time/op | time diff | `u256` B/op| `big` B/op | B diff| `u256` allocs/op | `big` allocs/op | allocs diff | 23 | |--|--|--|--|--|--|--|--|--|--| 24 | | And/single | 2.03ns | 8.46ns | `-76.04%` | 0 | 0 | `~` | 0 | 0 | `~`| 25 | | Or/single | 2.03ns | 10.98ns | `-81.51%` | 0 | 0 | `~` | 0 | 0 | `~`| 26 | | Xor/single | 2.03ns | 12.19ns | `-83.34%` | 0 | 0 | `~` | 0 | 0 | `~`| 27 | | Rsh/n_eq_0 | 5.00ns | 48.11ns | `-89.61%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| 28 | | Rsh/n_gt_0 | 10.42ns | 48.41ns | `-78.48%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| 29 | | Rsh/n_gt_64 | 6.94ns | 52.39ns | `-86.76%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| 30 | | Rsh/n_gt_128 | 5.49ns | 44.21ns | `-87.59%` | 0 | 48 | `-100.00%` | 0 | 1 | `-100.00%`| 31 | | Rsh/n_gt_192 | 3.43ns | 28.71ns | `-88.04%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| 32 | | Lsh/n_eq_0 | 4.89ns | 40.49ns | `-87.92%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| 33 | | Lsh/n_gt_0 | 10.14ns | 53.25ns | `-80.96%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| 34 | | Lsh/n_gt_64 | 7.50ns | 53.92ns | `-86.08%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| 35 | | Lsh/n_gt_128 | 5.39ns | 56.86ns | `-90.52%` | 0 | 96 | `-100.00%` | 0 | 1 | `-100.00%`| 36 | | Lsh/n_gt_192 | 3.90ns | 57.61ns | `-93.23%` | 0 | 96 | `-100.00%` | 0 | 1 | `-100.00%`| 37 | 38 | ### Conversions 39 | 40 | | benchmark | `u256` time/op | `big` time/op | time diff | `u256` B/op| `big` B/op | B diff| `u256` allocs/op | `big` allocs/op | allocs diff | 41 | |--|--|--|--|--|--|--|--|--|--| 42 | | FromHexString | 116.70ns | 861.30ns | `-86.45%` | 32 | 88 | `-63.64%` | 1 | 3 | `-66.67%`| 43 | | FromDecimalString | 7973.00ns | 32850.00ns | `-75.73%` | 0 | 2464 | `-100.00%` | 0 | 77 | `-100.00%`| 44 | | Float64/Float64 | 2366.00ns | 28483.00ns | `-91.69%` | 0 | 23424 | `-100.00%` | 0 | 510 | `-100.00%`| 45 | | EncodeHex/large | 95.26ns | 184.30ns | `-48.31%` | 80 | 140 | `-42.86%` | 1 | 2 | `-50.00%`| 46 | | Decimal/ToDecimal | 67384.00ns | 83431.00ns | `-19.23%` | 11344 | 31920 | `-64.46%` | 248 | 594 | `-58.25%`| 47 | | Decimal/ToPrettyDecimal | 84208.00ns | 123953.00ns | `-32.06%` | 14720 | 61376 | `-76.02%` | 251 | 1100 | `-77.18%`| 48 | 49 | ### Math 50 | 51 | | benchmark | `u256` time/op | `big` time/op | time diff | `u256` B/op| `big` B/op | B diff| `u256` allocs/op | `big` allocs/op | allocs diff | 52 | |--|--|--|--|--|--|--|--|--|--| 53 | | Add/single | 1.99ns | 18.11ns | `-89.02%` | 0 | 0 | `~` | 0 | 0 | `~`| 54 | | Sub/single | 2.00ns | 17.19ns | `-88.35%` | 0 | 0 | `~` | 0 | 0 | `~`| 55 | | Mul/single | 12.10ns | 57.69ns | `-79.03%` | 0 | 0 | `~` | 0 | 0 | `~`| 56 | | SDiv/large | 94.64ns | 642.10ns | `-85.26%` | 0 | 312 | `-100.00%` | 0 | 6 | `-100.00%`| 57 | | Sqrt/single | 594.90ns | 1844.00ns | `-67.74%` | 0 | 528 | `-100.00%` | 0 | 7 | `-100.00%`| 58 | | Square/single | 12.49ns | 56.10ns | `-77.74%` | 0 | 0 | `~` | 0 | 0 | `~`| 59 | | Cmp/single | 4.78ns | 12.79ns | `-62.61%` | 0 | 0 | `~` | 0 | 0 | `~`| 60 | | Div/small | 12.91ns | 48.31ns | `-73.28%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| 61 | | Div/mod64 | 65.77ns | 111.20ns | `-40.85%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| 62 | | Div/mod128 | 93.67ns | 301.40ns | `-68.92%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| 63 | | Div/mod192 | 86.52ns | 263.80ns | `-67.20%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| 64 | | Div/mod256 | 77.17ns | 252.80ns | `-69.47%` | 0 | 80 | `-100.00%` | 0 | 1 | `-100.00%`| 65 | | AddMod/small | 13.84ns | 48.16ns | `-71.26%` | 0 | 4 | `-100.00%` | 0 | 0 | `~`| 66 | | AddMod/mod64 | 22.83ns | 57.58ns | `-60.35%` | 0 | 11 | `-100.00%` | 0 | 0 | `~`| 67 | | AddMod/mod128 | 48.31ns | 145.00ns | `-66.68%` | 0 | 12 | `-100.00%` | 0 | 0 | `~`| 68 | | AddMod/mod192 | 47.26ns | 160.00ns | `-70.46%` | 0 | 12 | `-100.00%` | 0 | 0 | `~`| 69 | | AddMod/mod256 | 14.44ns | 143.20ns | `-89.92%` | 0 | 12 | `-100.00%` | 0 | 0 | `~`| 70 | | MulMod/small | 40.81ns | 63.14ns | `-35.37%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| 71 | | MulMod/mod64 | 91.66ns | 112.60ns | `-18.60%` | 0 | 48 | `-100.00%` | 0 | 1 | `-100.00%`| 72 | | MulMod/mod128 | 136.00ns | 362.70ns | `-62.50%` | 0 | 128 | `-100.00%` | 0 | 2 | `-100.00%`| 73 | | MulMod/mod192 | 151.70ns | 421.20ns | `-63.98%` | 0 | 144 | `-100.00%` | 0 | 2 | `-100.00%`| 74 | | MulMod/mod256 | 188.80ns | 489.20ns | `-61.41%` | 0 | 176 | `-100.00%` | 0 | 2 | `-100.00%`| 75 | | Exp/small | 433.70ns | 7490.00ns | `-94.21%` | 0 | 7392 | `-100.00%` | 0 | 77 | `-100.00%`| 76 | | Exp/large | 5145.00ns | 23043.00ns | `-77.67%` | 0 | 18144 | `-100.00%` | 0 | 189 | `-100.00%`| 77 | | Mod/mod64 | 70.94ns | 118.90ns | `-40.34%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| 78 | | Mod/small | 14.82ns | 46.27ns | `-67.97%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| 79 | | Mod/mod128 | 99.58ns | 286.90ns | `-65.29%` | 0 | 64 | `-100.00%` | 0 | 1 | `-100.00%`| 80 | | Mod/mod192 | 95.31ns | 269.30ns | `-64.61%` | 0 | 48 | `-100.00%` | 0 | 1 | `-100.00%`| 81 | | Mod/mod256 | 84.13ns | 222.90ns | `-62.26%` | 0 | 8 | `-100.00%` | 0 | 1 | `-100.00%`| 82 | | MulOverflow/single | 27.68ns | 57.52ns | `-51.88%` | 0 | 0 | `~` | 0 | 0 | `~`| 83 | | MulDivOverflow/small | 2.83ns | 22.97ns | `-87.69%` | 0 | 0 | `~` | 0 | 0 | `~`| 84 | | MulDivOverflow/div64 | 2.85ns | 23.13ns | `-87.66%` | 0 | 0 | `~` | 0 | 0 | `~`| 85 | | MulDivOverflow/div128 | 3.14ns | 31.29ns | `-89.96%` | 0 | 2 | `-100.00%` | 0 | 0 | `~`| 86 | | MulDivOverflow/div192 | 3.17ns | 30.28ns | `-89.54%` | 0 | 2 | `-100.00%` | 0 | 0 | `~`| 87 | | MulDivOverflow/div256 | 3.54ns | 35.56ns | `-90.06%` | 0 | 5 | `-100.00%` | 0 | 0 | `~`| 88 | | Lt/small | 3.12ns | 10.43ns | `-70.06%` | 0 | 0 | `~` | 0 | 0 | `~`| 89 | | Lt/large | 3.49ns | 10.32ns | `-66.18%` | 0 | 0 | `~` | 0 | 0 | `~`| 90 | 91 | ### Other 92 | 93 | | benchmark | `u256` time/op | `u256` B/op| `u256` allocs/op | 94 | |--|--|--|--| 95 | | SetBytes/generic | 104.30ns | 0 | 0 || 96 | | Sub/single/uint256_of | 1.99ns | 0 | 0 || 97 | | SetFromBig/overflow | 3.57ns | 0 | 0 || 98 | | ToBig/2words | 73.84ns | 64 | 2 || 99 | | SetBytes/specific | 45.81ns | 0 | 0 || 100 | | ScanScientific | 674.10ns | 0 | 0 || 101 | | SetFromBig/4words | 3.82ns | 0 | 0 || 102 | | ToBig/4words | 68.82ns | 64 | 2 || 103 | | RLPEncoding | 11917.00ns | 11911 | 255 || 104 | | SetFromBig/1word | 2.99ns | 0 | 0 || 105 | | SetFromBig/3words | 4.12ns | 0 | 0 || 106 | | ToBig/3words | 70.12ns | 64 | 2 || 107 | | ToBig/1word | 75.38ns | 64 | 2 || 108 | | MulMod/mod256/uint256r | 77.11ns | 0 | 0 || 109 | | HashTreeRoot | 11.27ns | 0 | 0 || 110 | | SetFromBig/2words | 3.90ns | 0 | 0 || 111 | 112 | ## Helping out 113 | 114 | If you're interested in low-level algorithms and/or doing optimizations for shaving off nanoseconds, then this is certainly for you! 115 | 116 | ### Implementation work 117 | 118 | Choose an operation, and optimize the s**t out of it! 119 | 120 | A few rules, though, to help your PR get approved: 121 | 122 | - Do not optimize for 'best-case'/'most common case' at the expense of worst-case. 123 | - We'll hold off on go assembly for a while, until the algos and interfaces are finished in a 'good enough' first version. After that, it's assembly time. 124 | 125 | ### Doing benchmarks 126 | 127 | To do a simple benchmark for everything, do 128 | 129 | ``` 130 | go test -run - -bench . -benchmem 131 | 132 | ``` 133 | 134 | To see the difference between a branch and master, for a particular benchmark, do 135 | 136 | ``` 137 | git checkout master 138 | go test -run - -bench Benchmark_Lsh -benchmem -count=10 > old.txt 139 | 140 | git checkout opt_branch 141 | go test -run - -bench Benchmark_Lsh -benchmem -count=10 > new.txt 142 | 143 | benchstat old.txt new.txt 144 | 145 | ``` 146 | -------------------------------------------------------------------------------- /binary_test.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "fmt" 9 | "math/big" 10 | "testing" 11 | ) 12 | 13 | type opDualArgFunc func(*Int, *Int, *Int) *Int 14 | type bigDualArgFunc func(*big.Int, *big.Int, *big.Int) *big.Int 15 | 16 | type opCmpArgFunc func(*Int, *Int) bool 17 | type bigCmpArgFunc func(*big.Int, *big.Int) bool 18 | 19 | type binaryOpEntry struct { 20 | name string 21 | u256Fn opDualArgFunc 22 | bigFn bigDualArgFunc 23 | } 24 | 25 | func lookupBinary(name string) binaryOpEntry { 26 | for _, tc := range binaryOpFuncs { 27 | if tc.name == name { 28 | return tc 29 | } 30 | } 31 | panic(fmt.Sprintf("%v not found", name)) 32 | } 33 | 34 | var binaryOpFuncs = []binaryOpEntry{ 35 | {"Add", (*Int).Add, (*big.Int).Add}, 36 | {"Sub", (*Int).Sub, (*big.Int).Sub}, 37 | {"Mul", (*Int).Mul, (*big.Int).Mul}, 38 | {"Div", (*Int).Div, bigDiv}, 39 | {"Mod", (*Int).Mod, bigMod}, 40 | {"SDiv", (*Int).SDiv, bigSDiv}, 41 | {"SMod", (*Int).SMod, bigSMod}, 42 | {"And", (*Int).And, (*big.Int).And}, 43 | {"Or", (*Int).Or, (*big.Int).Or}, 44 | {"Xor", (*Int).Xor, (*big.Int).Xor}, 45 | {"Exp", (*Int).Exp, func(b1, b2, b3 *big.Int) *big.Int { return b1.Exp(b2, b3, bigtt256) }}, 46 | {"Lsh", u256Lsh, bigLsh}, 47 | {"Rsh", u256Rsh, bigRsh}, 48 | {"SRsh", u256SRsh, bigSRsh}, 49 | {"DivModDiv", divModDiv, bigDiv}, 50 | {"DivModMod", divModMod, bigMod}, 51 | {"udivremDiv", udivremDiv, bigDiv}, 52 | {"udivremMod", udivremMod, bigMod}, 53 | {"ExtendSign", (*Int).ExtendSign, bigExtendSign}, 54 | } 55 | 56 | var cmpOpFuncs = []struct { 57 | name string 58 | u256Fn opCmpArgFunc 59 | bigFn bigCmpArgFunc 60 | }{ 61 | {"Eq", (*Int).Eq, func(a, b *big.Int) bool { return a.Cmp(b) == 0 }}, 62 | {"Lt", (*Int).Lt, func(a, b *big.Int) bool { return a.Cmp(b) < 0 }}, 63 | {"Gt", (*Int).Gt, func(a, b *big.Int) bool { return a.Cmp(b) > 0 }}, 64 | {"Slt", (*Int).Slt, func(a, b *big.Int) bool { return bigS256(a).Cmp(bigS256(b)) < 0 }}, 65 | {"Sgt", (*Int).Sgt, func(a, b *big.Int) bool { return bigS256(a).Cmp(bigS256(b)) > 0 }}, 66 | {"CmpEq", func(a, b *Int) bool { return a.Cmp(b) == 0 }, func(a, b *big.Int) bool { return a.Cmp(b) == 0 }}, 67 | {"CmpLt", func(a, b *Int) bool { return a.Cmp(b) < 0 }, func(a, b *big.Int) bool { return a.Cmp(b) < 0 }}, 68 | {"CmpGt", func(a, b *Int) bool { return a.Cmp(b) > 0 }, func(a, b *big.Int) bool { return a.Cmp(b) > 0 }}, 69 | {"LtUint64", func(a, b *Int) bool { return a.LtUint64(b.Uint64()) }, func(a, b *big.Int) bool { return a.Cmp(new(big.Int).SetUint64(b.Uint64())) < 0 }}, 70 | {"GtUint64", func(a, b *Int) bool { return a.GtUint64(b.Uint64()) }, func(a, b *big.Int) bool { return a.Cmp(new(big.Int).SetUint64(b.Uint64())) > 0 }}, 71 | } 72 | 73 | func checkBinaryOperation(t *testing.T, opName string, op opDualArgFunc, bigOp bigDualArgFunc, x, y Int) { 74 | var ( 75 | b1 = x.ToBig() 76 | b2 = y.ToBig() 77 | f1 = x.Clone() 78 | f2 = y.Clone() 79 | operation = fmt.Sprintf("op: %v ( %v, %v ) ", opName, x.Hex(), y.Hex()) 80 | want, _ = FromBig(bigOp(new(big.Int), b1, b2)) 81 | have = op(new(Int), f1, f2) 82 | ) 83 | // Compare result with big.Int. 84 | if !have.Eq(want) { 85 | t.Fatalf("%v\nwant : %#x\nhave : %#x\n", operation, want, have) 86 | } 87 | 88 | // Check if arguments are unmodified. 89 | if !f1.Eq(x.Clone()) { 90 | t.Fatalf("%v\nfirst argument had been modified: %x", operation, f1) 91 | } 92 | if !f2.Eq(y.Clone()) { 93 | t.Fatalf("%v\nsecond argument had been modified: %x", operation, f2) 94 | } 95 | 96 | // Check if reusing args as result works correctly. 97 | have = op(f1, f1, y.Clone()) 98 | if have != f1 { 99 | t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f1) 100 | } 101 | if !have.Eq(want) { 102 | t.Fatalf("%v\non argument reuse x.op(x,y)\nwant : %#x\nhave : %#x\n", operation, want, have) 103 | } 104 | have = op(f2, x.Clone(), f2) 105 | if have != f2 { 106 | t.Fatalf("%v\nunexpected pointer returned: %p, expected: %p\n", operation, have, f2) 107 | } 108 | if !have.Eq(want) { 109 | t.Fatalf("%v\n on argument reuse x.op(y,x)\nwant : %#x\nhave : %#x\n", operation, want, have) 110 | } 111 | } 112 | 113 | func TestBinaryOperations(t *testing.T) { 114 | for _, tc := range binaryOpFuncs { 115 | for _, inputs := range binTestCases { 116 | f1 := MustFromHex(inputs[0]) 117 | f2 := MustFromHex(inputs[1]) 118 | checkBinaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2) 119 | } 120 | } 121 | } 122 | 123 | func Test10KRandomBinaryOperations(t *testing.T) { 124 | for _, tc := range binaryOpFuncs { 125 | for i := 0; i < 10000; i++ { 126 | f1 := randNum() 127 | f2 := randNum() 128 | checkBinaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2) 129 | } 130 | } 131 | } 132 | 133 | func FuzzBinaryOperations(f *testing.F) { 134 | f.Fuzz(func(t *testing.T, x0, x1, x2, x3, y0, y1, y2, y3 uint64) { 135 | x := Int{x0, x1, x2, x3} 136 | y := Int{y0, y1, y2, y3} 137 | for _, tc := range binaryOpFuncs { 138 | checkBinaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, x, y) 139 | } 140 | }) 141 | } 142 | 143 | func u256Rsh(z, x, y *Int) *Int { 144 | return z.Rsh(x, uint(y.Uint64()&0x1FF)) 145 | } 146 | func bigRsh(z, x, y *big.Int) *big.Int { 147 | return z.Rsh(x, uint(y.Uint64()&0x1FF)) 148 | } 149 | 150 | func u256Lsh(z, x, y *Int) *Int { 151 | return z.Lsh(x, uint(y.Uint64()&0x1FF)) 152 | } 153 | func u256SRsh(z, x, y *Int) *Int { 154 | return z.SRsh(x, uint(y.Uint64()&0x1FF)) 155 | } 156 | 157 | func bigLsh(z, x, y *big.Int) *big.Int { 158 | return z.Lsh(x, uint(y.Uint64()&0x1FF)) 159 | } 160 | 161 | func bigSRsh(z, x, y *big.Int) *big.Int { 162 | return z.Rsh(bigS256(x), uint(y.Uint64()&0x1FF)) 163 | } 164 | 165 | func bigExtendSign(result, num, byteNum *big.Int) *big.Int { 166 | if byteNum.Cmp(big.NewInt(31)) >= 0 { 167 | return result.Set(num) 168 | } 169 | bit := uint(byteNum.Uint64()*8 + 7) 170 | mask := byteNum.Lsh(big.NewInt(1), bit) 171 | mask.Sub(mask, big.NewInt(1)) 172 | if num.Bit(int(bit)) > 0 { 173 | result.Or(num, mask.Not(mask)) 174 | } else { 175 | result.And(num, mask) 176 | } 177 | return result 178 | } 179 | 180 | // bigDiv implements uint256/EVM compatible division for big.Int: returns 0 when dividing by 0 181 | func bigDiv(z, x, y *big.Int) *big.Int { 182 | if y.Sign() == 0 { 183 | return z.SetUint64(0) 184 | } 185 | return z.Div(x, y) 186 | } 187 | 188 | // bigMod implements uint256/EVM compatible mod for big.Int: returns 0 when dividing by 0 189 | func bigMod(z, x, y *big.Int) *big.Int { 190 | if y.Sign() == 0 { 191 | return z.SetUint64(0) 192 | } 193 | return z.Mod(x, y) 194 | } 195 | 196 | // bigSDiv implements EVM-compatible SDIV operation on big.Int 197 | func bigSDiv(result, x, y *big.Int) *big.Int { 198 | if y.Sign() == 0 { 199 | return result.SetUint64(0) 200 | } 201 | sx := bigS256(x) 202 | sy := bigS256(y) 203 | 204 | n := new(big.Int) 205 | if sx.Sign() == sy.Sign() { 206 | n.SetInt64(1) 207 | } else { 208 | n.SetInt64(-1) 209 | } 210 | result.Div(sx.Abs(sx), sy.Abs(sy)) 211 | result.Mul(result, n) 212 | return result 213 | } 214 | 215 | // bigSMod implements EVM-compatible SMOD operation on big.Int 216 | func bigSMod(result, x, y *big.Int) *big.Int { 217 | if y.Sign() == 0 { 218 | return result.SetUint64(0) 219 | } 220 | 221 | sx := bigS256(x) 222 | sy := bigS256(y) 223 | neg := sx.Sign() < 0 224 | 225 | result.Mod(sx.Abs(sx), sy.Abs(sy)) 226 | if neg { 227 | result.Neg(result) 228 | } 229 | return bigU256(result) 230 | } 231 | 232 | // divModDiv wraps DivMod and returns quotient only 233 | func divModDiv(z, x, y *Int) *Int { 234 | var m Int 235 | z.DivMod(x, y, &m) 236 | return z 237 | } 238 | 239 | // divModMod wraps DivMod and returns modulus only 240 | func divModMod(z, x, y *Int) *Int { 241 | new(Int).DivMod(x, y, z) 242 | return z 243 | } 244 | 245 | // udivremDiv wraps udivrem and returns quotient 246 | func udivremDiv(z, x, y *Int) *Int { 247 | var quot Int 248 | if !y.IsZero() { 249 | udivrem(quot[:], x[:], y, nil) 250 | } 251 | return z.Set(") 252 | } 253 | 254 | // udivremMod wraps udivrem and returns remainder 255 | func udivremMod(z, x, y *Int) *Int { 256 | if y.IsZero() { 257 | return z.Clear() 258 | } 259 | var quot, rem Int 260 | udivrem(quot[:], x[:], y, &rem) 261 | return z.Set(&rem) 262 | } 263 | 264 | func checkCompareOperation(t *testing.T, opName string, op opCmpArgFunc, bigOp bigCmpArgFunc, x, y Int) { 265 | var ( 266 | f1orig = x.Clone() 267 | f2orig = y.Clone() 268 | b1 = x.ToBig() 269 | b2 = y.ToBig() 270 | f1 = new(Int).Set(f1orig) 271 | f2 = new(Int).Set(f2orig) 272 | operation = fmt.Sprintf("op: %v ( %v, %v ) ", opName, x.Hex(), y.Hex()) 273 | want = bigOp(b1, b2) 274 | have = op(f1, f2) 275 | ) 276 | // Compare result with big.Int. 277 | if have != want { 278 | t.Fatalf("%v\nwant : %v\nhave : %v\n", operation, want, have) 279 | } 280 | // Check if arguments are unmodified. 281 | if !f1.Eq(f1orig) { 282 | t.Fatalf("%v\nfirst argument had been modified: %x", operation, f1) 283 | } 284 | if !f2.Eq(f2orig) { 285 | t.Fatalf("%v\nsecond argument had been modified: %x", operation, f2) 286 | } 287 | } 288 | 289 | func TestCompareOperations(t *testing.T) { 290 | for _, tc := range cmpOpFuncs { 291 | for _, inputs := range binTestCases { 292 | f1 := MustFromHex(inputs[0]) 293 | f2 := MustFromHex(inputs[1]) 294 | checkCompareOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2) 295 | } 296 | } 297 | } 298 | 299 | func FuzzCompareOperations(f *testing.F) { 300 | f.Fuzz(func(t *testing.T, x0, x1, x2, x3, y0, y1, y2, y3 uint64) { 301 | x := Int{x0, x1, x2, x3} 302 | y := Int{y0, y1, y2, y3} 303 | for _, tc := range cmpOpFuncs { 304 | checkCompareOperation(t, tc.name, tc.u256Fn, tc.bigFn, x, y) 305 | } 306 | }) 307 | } 308 | -------------------------------------------------------------------------------- /shared_test.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2018-2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "crypto/rand" 9 | "math/big" 10 | ) 11 | 12 | // This file contains some utilities which the oss-fuzz fuzzer shares with the 13 | // regular go-native tests. It is placed in a separate file, becaue the oss-fuzz 14 | // clang-based fuzzing infrastructure requires some instrumentation. 15 | // During this instrumentation, the file under test (e.g. unary_test.go) is modified, 16 | // and the same modification needs to be performed with any other files that 17 | // it requires (this file). 18 | 19 | var ( 20 | bigtt256 = new(big.Int).Lsh(big.NewInt(1), 256) 21 | bigtt255 = new(big.Int).Lsh(big.NewInt(1), 255) 22 | bigtt256m1 = new(big.Int).Sub(bigtt256, big.NewInt(1)) 23 | 24 | unTestCases = []string{ 25 | "0x0", 26 | "0x1", 27 | "0x8000000000000000", 28 | "0x12cbafcee8f60f9f", 29 | "0x80000000000000000000000000000000", 30 | "0x80000000000000010000000000000000", 31 | "0x80000000000000000000000000000001", 32 | "0x12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5", 33 | "0x8000000000000000000000000000000000000000000000000000000000000000", 34 | "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", 35 | "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 36 | } 37 | 38 | // A collection of interesting input values for binary operators (especially for division). 39 | // No expected results as big.Int can be used as the source of truth. 40 | binTestCases = [][2]string{ 41 | {"0x0", "0x0"}, 42 | {"0x1", "0x0"}, 43 | {"0x1", "0x767676767676767676000000767676767676"}, 44 | {"0x2", "0x0"}, 45 | {"0x2", "0x1"}, 46 | {"0x12cbafcee8f60f9f3fa308c90fde8d298772ffea667aa6bc109d5c661e7929a5", "0xc76f4afb041407a8ea478d65024f5c3dfe1db1a1bb10c5ea8bec314ccf9"}, 47 | {"0x10000000000000000", "0x2"}, 48 | {"0x7000000000000000", "0x8000000000000000"}, 49 | {"0x8000000000000000", "0x8000000000000000"}, 50 | {"0x8000000000000001", "0x8000000000000000"}, 51 | {"0x80000000000000010000000000000000", "0x80000000000000000000000000000000"}, 52 | {"0x80000000000000000000000000000000", "0x80000000000000000000000000000001"}, 53 | {"0x478392145435897052", "0x111"}, 54 | {"0x767676767676767676000000767676767676", "0x2900760076761e00020076760000000076767676000000"}, 55 | {"0x12121212121212121212121212121212", "0x232323232323232323"}, 56 | {"0xfffff716b61616160b0b0b2b0b0b0becf4bef50a0df4f48b090b2b0bc60a0a00", "0xfffff716b61616160b0b0b2b0b230b000008010d0a2b00"}, 57 | {"0x50beb1c60141a0000dc2b0b0b0b0b0b410a0a0df4f40b090b2b0bc60a0a00", "0x2000110000000d0a300e750a000000090a0a"}, 58 | {"0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b090b2b0bc60a0a1000", "0x4b00000b41000b0b0b2b0b0b0b0b0b410a0aeff4f40b0a0a"}, 59 | {"0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", "0x7"}, 60 | {"0xf6376770abd3a36b20394c5664afef1194c801c3f05e42566f085ed24d002bb0", "0xb368d219438b7f3f"}, 61 | {"0x0", "0x10900000000000000000000000000000000000000000000000000"}, 62 | {"0x77676767676760000000000000001002e000000000000040000000e000000000", "0xfffc000000000000767676240000000000002b0576047"}, 63 | {"0x767676767676000000000076000000000000005600000000000000000000", "0x767676767676000000000076000000760000"}, 64 | {"0x8200000000000000000000000000000000000000000000000000000000000000", "0x8200000000000000fe000004000000ffff000000fffff700"}, 65 | {"0xdac7fff9ffd9e1322626262626262600", "0xd021262626262626"}, 66 | {"0x8000000000000001800000000000000080000000000000008000000000000000", "0x800000000000000080000000000000008000000000000000"}, 67 | {"0xe8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000", "0xe8e8e8e2000100000009ea02000000000000ff3ffffff800000010002280ff"}, 68 | {"0xc9700000000000000000023f00c00014ff000000000000000022300805", "0xc9700000000000000000023f00c00014ff002c000000000000223108"}, 69 | {"0x40000000fd000000db0000000000000000000000000000000000000000000001", "0x40000000fd000000db0000000000000000000040000000fd000000db000001"}, 70 | {"0x40000000fd000000db0000000000000000000000000000000000000000000001", "0x40000000fd000000db0000000000000000000040000000fd000000db0000d3"}, 71 | {"0x1f000000000000000000000000000000200000000100000000000000000000", "0x100000000ffffffffffffffff0000000000002e000000"}, 72 | {"0x7effffff80000000000000000000000000020000440000000000000000000001", "0x7effffff800000007effffff800000008000ff0000010000"}, 73 | {"0x5fd8fffffffffffffffffffffffffffffc090000ce700004d0c9ffffff000001", "0x2ffffffffffffffffffffffffffffffffff000000030000"}, 74 | {"0x62d8fffffffffffffffffffffffffffffc18000000000000000000ca00000001", "0x2ffffffffffffffffffffffffffffffffff200000000000"}, 75 | {"0x7effffff8000000000000000000000000000000000000000d900000000000001", "0x7effffff8000000000000000000000000000000000008001"}, 76 | {"0x6400aff20ff00200004e7fd1eff08ffca0afd1eff08ffca0a", "0x210000000000000022"}, 77 | {"0x6d5adef08547abf7eb", "0x13590cab83b779e708b533b0eef3561483ddeefc841f5"}, 78 | {"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, 79 | {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, 80 | {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, 81 | {"0xe8e8e8e2000100000009ea02000000000000ff3ffffff80000001000220000", "0xffffffffffffffff7effffff800000007effffff800000008000ff0000010000"}, 82 | {"0x1ce97e1ab91a", "0x66aa0a5319bcf5cb4"}, // regression test for udivrem() where len(x) < len(y) 83 | } 84 | 85 | // A collection of interesting input values for ternary operators (addmod, mulmod). 86 | ternTestCases = [][3]string{ 87 | {"0x0", "0x0", "0x0"}, 88 | {"0x1", "0x0", "0x0"}, 89 | {"0x1", "0x1", "0x0"}, 90 | {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0x0"}, 91 | {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, 92 | {"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd", "0x3", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, 93 | {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"}, 94 | {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"}, 95 | {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x2"}, 96 | {"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "0x1"}, 97 | {"0xffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffe00000000000000000000000000000002"}, 98 | {"0xffffffffffffffffffffffffffffffff", "0xffffffffffffffffffffffffffffffff", "0xfffffffffffffffffffffffffffffffe00000000000000000000000000000001"}, 99 | {"0xffffffffffffffffffffffffffff000004020041fffffffffc00000060000020", "0xffffffffffffffffffffffffffffffe6000000ffffffe60000febebeffffffff", "0xffffffffffffffffffe6000000ffffffe60000febebeffffffffffffffffffff"}, 100 | {"0xffffffffffffffffffffffffffffffff00ffffe6ff0000000000000060000020", "0xffffffffffffffffffffffffffffffffffe6000000ffff00e60000febebeffff", "0xffffffffffffffffffe6000000ffff00e60000fe0000ffff00e60000febebeff"}, 101 | {"0xfffffffffffffffffffffffff600000000005af50100bebe000000004a00be0a", "0xffffffffffffffffffffffffffffeaffdfd9fffffffffffff5f60000000000ff", "0xffffffffffffffffffffffeaffdfd9fffffffffffffff60000000000ffffffff"}, 102 | {"0x8000000000000001000000000000000000000000000000000000000000000000", "0x800000000000000100000000000000000000000000000000000000000000000b", "0x8000000000000000000000000000000000000000000000000000000000000000"}, 103 | {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000", "0x8000000000000000000000000000000000000000000000000000000000000000"}, 104 | {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000", "0x8000000000000001000000000000000000000000000000000000000000000000"}, 105 | {"0x8000000000000000000000000000000000000000000000000000000000000000", "0x8000000000000000000000000000000100000000000000000000000000000000", "0x8000000000000000000000000000000000000000000000000000000000000001"}, 106 | {"0x1", "0x1", "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff"}, 107 | {"0x1", "0x1", "0x1000000003030303030303030303030303030303030303030303030303030"}, 108 | {"0x1", "0x1", "0x4000000000000000130303030303030303030303030303030303030303030"}, 109 | {"0x1", "0x1", "0x8000000000000000000000000000000043030303000000000"}, 110 | {"0x1", "0x1", "0x8000000000000000000000000000000003030303030303030"}, 111 | } 112 | ) 113 | 114 | // bigU256 encodes as a 256 bit two's complement number. This operation is destructive. 115 | func bigU256(x *big.Int) *big.Int { 116 | return x.And(x, bigtt256m1) 117 | } 118 | 119 | func bigS256(x *big.Int) *big.Int { 120 | if x.Cmp(bigtt255) < 0 { 121 | return x 122 | } 123 | return new(big.Int).Sub(x, bigtt256) 124 | } 125 | 126 | func randNum() *Int { 127 | //How many bits? 0-256 128 | nbits, _ := rand.Int(rand.Reader, big.NewInt(257)) 129 | //Max random value, a 130-bits integer, i.e 2^130 130 | max := new(big.Int) 131 | max.Exp(big.NewInt(2), big.NewInt(nbits.Int64()), nil) 132 | b, _ := rand.Int(rand.Reader, max) 133 | f, _ := FromBig(b) 134 | return f 135 | } 136 | -------------------------------------------------------------------------------- /mod.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2021 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "math/bits" 9 | ) 10 | 11 | // Reciprocal computes a 320-bit value representing 1/m 12 | // 13 | // Notes: 14 | // - specialized for m[3] != 0, hence limited to 2^192 <= m < 2^256 15 | // - returns zero if m[3] == 0 16 | // - starts with a 32-bit division, refines with newton-raphson iterations 17 | func Reciprocal(m *Int) (mu [5]uint64) { 18 | 19 | if m[3] == 0 { 20 | return mu 21 | } 22 | 23 | s := bits.LeadingZeros64(m[3]) // Replace with leadingZeros(m) for general case 24 | p := 255 - s // floor(log_2(m)), m>0 25 | 26 | // 0 or a power of 2? 27 | 28 | // Check if at least one bit is set in m[2], m[1] or m[0], 29 | // or at least two bits in m[3] 30 | 31 | if m[0] | m[1] | m[2] | (m[3] & (m[3]-1)) == 0 { 32 | 33 | mu[4] = ^uint64(0) >> uint(p & 63) 34 | mu[3] = ^uint64(0) 35 | mu[2] = ^uint64(0) 36 | mu[1] = ^uint64(0) 37 | mu[0] = ^uint64(0) 38 | 39 | return mu 40 | } 41 | 42 | // Maximise division precision by left-aligning divisor 43 | 44 | var ( 45 | y Int // left-aligned copy of m 46 | r0 uint32 // estimate of 2^31/y 47 | ) 48 | 49 | y.Lsh(m, uint(s)) // 1/2 < y < 1 50 | 51 | // Extract most significant 32 bits 52 | 53 | yh := uint32(y[3] >> 32) 54 | 55 | 56 | if yh == 0x80000000 { // Avoid overflow in division 57 | r0 = 0xffffffff 58 | } else { 59 | r0, _ = bits.Div32(0x80000000, 0, yh) 60 | } 61 | 62 | // First iteration: 32 -> 64 63 | 64 | t1 := uint64(r0) // 2^31/y 65 | t1 *= t1 // 2^62/y^2 66 | t1, _ = bits.Mul64(t1, y[3]) // 2^62/y^2 * 2^64/y / 2^64 = 2^62/y 67 | 68 | r1 := uint64(r0) << 32 // 2^63/y 69 | r1 -= t1 // 2^63/y - 2^62/y = 2^62/y 70 | r1 *= 2 // 2^63/y 71 | 72 | if (r1 | (y[3]<<1)) == 0 { 73 | r1 = ^uint64(0) 74 | } 75 | 76 | // Second iteration: 64 -> 128 77 | 78 | // square: 2^126/y^2 79 | a2h, a2l := bits.Mul64(r1, r1) 80 | 81 | // multiply by y: e2h:e2l:b2h = 2^126/y^2 * 2^128/y / 2^128 = 2^126/y 82 | b2h, _ := bits.Mul64(a2l, y[2]) 83 | c2h, c2l := bits.Mul64(a2l, y[3]) 84 | d2h, d2l := bits.Mul64(a2h, y[2]) 85 | e2h, e2l := bits.Mul64(a2h, y[3]) 86 | 87 | b2h, c := bits.Add64(b2h, c2l, 0) 88 | e2l, c = bits.Add64(e2l, c2h, c) 89 | e2h, _ = bits.Add64(e2h, 0, c) 90 | 91 | _, c = bits.Add64(b2h, d2l, 0) 92 | e2l, c = bits.Add64(e2l, d2h, c) 93 | e2h, _ = bits.Add64(e2h, 0, c) 94 | 95 | // subtract: t2h:t2l = 2^127/y - 2^126/y = 2^126/y 96 | t2l, b := bits.Sub64( 0, e2l, 0) 97 | t2h, _ := bits.Sub64(r1, e2h, b) 98 | 99 | // double: r2h:r2l = 2^127/y 100 | r2l, c := bits.Add64(t2l, t2l, 0) 101 | r2h, _ := bits.Add64(t2h, t2h, c) 102 | 103 | if (r2h | r2l | (y[3]<<1)) == 0 { 104 | r2h = ^uint64(0) 105 | r2l = ^uint64(0) 106 | } 107 | 108 | // Third iteration: 128 -> 192 109 | 110 | // square r2 (keep 256 bits): 2^190/y^2 111 | a3h, a3l := bits.Mul64(r2l, r2l) 112 | b3h, b3l := bits.Mul64(r2l, r2h) 113 | c3h, c3l := bits.Mul64(r2h, r2h) 114 | 115 | a3h, c = bits.Add64(a3h, b3l, 0) 116 | c3l, c = bits.Add64(c3l, b3h, c) 117 | c3h, _ = bits.Add64(c3h, 0, c) 118 | 119 | a3h, c = bits.Add64(a3h, b3l, 0) 120 | c3l, c = bits.Add64(c3l, b3h, c) 121 | c3h, _ = bits.Add64(c3h, 0, c) 122 | 123 | // multiply by y: q = 2^190/y^2 * 2^192/y / 2^192 = 2^190/y 124 | 125 | x0 := a3l 126 | x1 := a3h 127 | x2 := c3l 128 | x3 := c3h 129 | 130 | var q0, q1, q2, q3, q4, t0 uint64 131 | 132 | q0, _ = bits.Mul64(x2, y[0]) 133 | q1, t0 = bits.Mul64(x3, y[0]); q0, c = bits.Add64(q0, t0, 0); q1, _ = bits.Add64(q1, 0, c) 134 | 135 | 136 | t1, _ = bits.Mul64(x1, y[1]); q0, c = bits.Add64(q0, t1, 0) 137 | q2, t0 = bits.Mul64(x3, y[1]); q1, c = bits.Add64(q1, t0, c); q2, _ = bits.Add64(q2, 0, c) 138 | 139 | t1, t0 = bits.Mul64(x2, y[1]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c); q2, _ = bits.Add64(q2, 0, c) 140 | 141 | 142 | t1, t0 = bits.Mul64(x1, y[2]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) 143 | q3, t0 = bits.Mul64(x3, y[2]); q2, c = bits.Add64(q2, t0, c); q3, _ = bits.Add64(q3, 0, c) 144 | 145 | t1, _ = bits.Mul64(x0, y[2]); q0, c = bits.Add64(q0, t1, 0) 146 | t1, t0 = bits.Mul64(x2, y[2]); q1, c = bits.Add64(q1, t0, c); q2, c = bits.Add64(q2, t1, c); q3, _ = bits.Add64(q3, 0, c) 147 | 148 | 149 | t1, t0 = bits.Mul64(x1, y[3]); q1, c = bits.Add64(q1, t0, 0); q2, c = bits.Add64(q2, t1, c) 150 | q4, t0 = bits.Mul64(x3, y[3]); q3, c = bits.Add64(q3, t0, c); q4, _ = bits.Add64(q4, 0, c) 151 | 152 | t1, t0 = bits.Mul64(x0, y[3]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) 153 | t1, t0 = bits.Mul64(x2, y[3]); q2, c = bits.Add64(q2, t0, c); q3, c = bits.Add64(q3, t1, c); q4, _ = bits.Add64(q4, 0, c) 154 | 155 | // subtract: t3 = 2^191/y - 2^190/y = 2^190/y 156 | _, b = bits.Sub64( 0, q0, 0) 157 | _, b = bits.Sub64( 0, q1, b) 158 | t3l, b := bits.Sub64( 0, q2, b) 159 | t3m, b := bits.Sub64(r2l, q3, b) 160 | t3h, _ := bits.Sub64(r2h, q4, b) 161 | 162 | // double: r3 = 2^191/y 163 | r3l, c := bits.Add64(t3l, t3l, 0) 164 | r3m, c := bits.Add64(t3m, t3m, c) 165 | r3h, _ := bits.Add64(t3h, t3h, c) 166 | 167 | // Fourth iteration: 192 -> 320 168 | 169 | // square r3 170 | 171 | a4h, a4l := bits.Mul64(r3l, r3l) 172 | b4h, b4l := bits.Mul64(r3l, r3m) 173 | c4h, c4l := bits.Mul64(r3l, r3h) 174 | d4h, d4l := bits.Mul64(r3m, r3m) 175 | e4h, e4l := bits.Mul64(r3m, r3h) 176 | f4h, f4l := bits.Mul64(r3h, r3h) 177 | 178 | b4h, c = bits.Add64(b4h, c4l, 0) 179 | e4l, c = bits.Add64(e4l, c4h, c) 180 | e4h, _ = bits.Add64(e4h, 0, c) 181 | 182 | a4h, c = bits.Add64(a4h, b4l, 0) 183 | d4l, c = bits.Add64(d4l, b4h, c) 184 | d4h, c = bits.Add64(d4h, e4l, c) 185 | f4l, c = bits.Add64(f4l, e4h, c) 186 | f4h, _ = bits.Add64(f4h, 0, c) 187 | 188 | a4h, c = bits.Add64(a4h, b4l, 0) 189 | d4l, c = bits.Add64(d4l, b4h, c) 190 | d4h, c = bits.Add64(d4h, e4l, c) 191 | f4l, c = bits.Add64(f4l, e4h, c) 192 | f4h, _ = bits.Add64(f4h, 0, c) 193 | 194 | // multiply by y 195 | 196 | x1, x0 = bits.Mul64(d4h, y[0]) 197 | x3, x2 = bits.Mul64(f4h, y[0]) 198 | t1, t0 = bits.Mul64(f4l, y[0]); x1, c = bits.Add64(x1, t0, 0); x2, c = bits.Add64(x2, t1, c) 199 | x3, _ = bits.Add64(x3, 0, c) 200 | 201 | t1, t0 = bits.Mul64(d4h, y[1]); x1, c = bits.Add64(x1, t0, 0); x2, c = bits.Add64(x2, t1, c) 202 | x4, t0 := bits.Mul64(f4h, y[1]); x3, c = bits.Add64(x3, t0, c); x4, _ = bits.Add64(x4, 0, c) 203 | t1, t0 = bits.Mul64(d4l, y[1]); x0, c = bits.Add64(x0, t0, 0); x1, c = bits.Add64(x1, t1, c) 204 | t1, t0 = bits.Mul64(f4l, y[1]); x2, c = bits.Add64(x2, t0, c); x3, c = bits.Add64(x3, t1, c) 205 | x4, _ = bits.Add64(x4, 0, c) 206 | 207 | t1, t0 = bits.Mul64(a4h, y[2]); x0, c = bits.Add64(x0, t0, 0); x1, c = bits.Add64(x1, t1, c) 208 | t1, t0 = bits.Mul64(d4h, y[2]); x2, c = bits.Add64(x2, t0, c); x3, c = bits.Add64(x3, t1, c) 209 | x5, t0 := bits.Mul64(f4h, y[2]); x4, c = bits.Add64(x4, t0, c); x5, _ = bits.Add64(x5, 0, c) 210 | t1, t0 = bits.Mul64(d4l, y[2]); x1, c = bits.Add64(x1, t0, 0); x2, c = bits.Add64(x2, t1, c) 211 | t1, t0 = bits.Mul64(f4l, y[2]); x3, c = bits.Add64(x3, t0, c); x4, c = bits.Add64(x4, t1, c) 212 | x5, _ = bits.Add64(x5, 0, c) 213 | 214 | t1, t0 = bits.Mul64(a4h, y[3]); x1, c = bits.Add64(x1, t0, 0); x2, c = bits.Add64(x2, t1, c) 215 | t1, t0 = bits.Mul64(d4h, y[3]); x3, c = bits.Add64(x3, t0, c); x4, c = bits.Add64(x4, t1, c) 216 | x6, t0 := bits.Mul64(f4h, y[3]); x5, c = bits.Add64(x5, t0, c); x6, _ = bits.Add64(x6, 0, c) 217 | t1, t0 = bits.Mul64(a4l, y[3]); x0, c = bits.Add64(x0, t0, 0); x1, c = bits.Add64(x1, t1, c) 218 | t1, t0 = bits.Mul64(d4l, y[3]); x2, c = bits.Add64(x2, t0, c); x3, c = bits.Add64(x3, t1, c) 219 | t1, t0 = bits.Mul64(f4l, y[3]); x4, c = bits.Add64(x4, t0, c); x5, c = bits.Add64(x5, t1, c) 220 | x6, _ = bits.Add64(x6, 0, c) 221 | 222 | // subtract 223 | _, b = bits.Sub64( 0, x0, 0) 224 | _, b = bits.Sub64( 0, x1, b) 225 | r4l, b := bits.Sub64( 0, x2, b) 226 | r4k, b := bits.Sub64( 0, x3, b) 227 | r4j, b := bits.Sub64(r3l, x4, b) 228 | r4i, b := bits.Sub64(r3m, x5, b) 229 | r4h, _ := bits.Sub64(r3h, x6, b) 230 | 231 | // Multiply candidate for 1/4y by y, with full precision 232 | 233 | x0 = r4l 234 | x1 = r4k 235 | x2 = r4j 236 | x3 = r4i 237 | x4 = r4h 238 | 239 | q1, q0 = bits.Mul64(x0, y[0]) 240 | q3, q2 = bits.Mul64(x2, y[0]) 241 | q5, q4 := bits.Mul64(x4, y[0]) 242 | 243 | t1, t0 = bits.Mul64(x1, y[0]); q1, c = bits.Add64(q1, t0, 0); q2, c = bits.Add64(q2, t1, c) 244 | t1, t0 = bits.Mul64(x3, y[0]); q3, c = bits.Add64(q3, t0, c); q4, c = bits.Add64(q4, t1, c); q5, _ = bits.Add64(q5, 0, c) 245 | 246 | t1, t0 = bits.Mul64(x0, y[1]); q1, c = bits.Add64(q1, t0, 0); q2, c = bits.Add64(q2, t1, c) 247 | t1, t0 = bits.Mul64(x2, y[1]); q3, c = bits.Add64(q3, t0, c); q4, c = bits.Add64(q4, t1, c) 248 | q6, t0 := bits.Mul64(x4, y[1]); q5, c = bits.Add64(q5, t0, c); q6, _ = bits.Add64(q6, 0, c) 249 | 250 | t1, t0 = bits.Mul64(x1, y[1]); q2, c = bits.Add64(q2, t0, 0); q3, c = bits.Add64(q3, t1, c) 251 | t1, t0 = bits.Mul64(x3, y[1]); q4, c = bits.Add64(q4, t0, c); q5, c = bits.Add64(q5, t1, c); q6, _ = bits.Add64(q6, 0, c) 252 | 253 | t1, t0 = bits.Mul64(x0, y[2]); q2, c = bits.Add64(q2, t0, 0); q3, c = bits.Add64(q3, t1, c) 254 | t1, t0 = bits.Mul64(x2, y[2]); q4, c = bits.Add64(q4, t0, c); q5, c = bits.Add64(q5, t1, c) 255 | q7, t0 := bits.Mul64(x4, y[2]); q6, c = bits.Add64(q6, t0, c); q7, _ = bits.Add64(q7, 0, c) 256 | 257 | t1, t0 = bits.Mul64(x1, y[2]); q3, c = bits.Add64(q3, t0, 0); q4, c = bits.Add64(q4, t1, c) 258 | t1, t0 = bits.Mul64(x3, y[2]); q5, c = bits.Add64(q5, t0, c); q6, c = bits.Add64(q6, t1, c); q7, _ = bits.Add64(q7, 0, c) 259 | 260 | t1, t0 = bits.Mul64(x0, y[3]); q3, c = bits.Add64(q3, t0, 0); q4, c = bits.Add64(q4, t1, c) 261 | t1, t0 = bits.Mul64(x2, y[3]); q5, c = bits.Add64(q5, t0, c); q6, c = bits.Add64(q6, t1, c) 262 | q8, t0 := bits.Mul64(x4, y[3]); q7, c = bits.Add64(q7, t0, c); q8, _ = bits.Add64(q8, 0, c) 263 | 264 | t1, t0 = bits.Mul64(x1, y[3]); q4, c = bits.Add64(q4, t0, 0); q5, c = bits.Add64(q5, t1, c) 265 | t1, t0 = bits.Mul64(x3, y[3]); q6, c = bits.Add64(q6, t0, c); q7, c = bits.Add64(q7, t1, c); q8, _ = bits.Add64(q8, 0, c) 266 | 267 | // Final adjustment 268 | 269 | // subtract q from 1/4 270 | _, b = bits.Sub64(0, q0, 0) 271 | _, b = bits.Sub64(0, q1, b) 272 | _, b = bits.Sub64(0, q2, b) 273 | _, b = bits.Sub64(0, q3, b) 274 | _, b = bits.Sub64(0, q4, b) 275 | _, b = bits.Sub64(0, q5, b) 276 | _, b = bits.Sub64(0, q6, b) 277 | _, b = bits.Sub64(0, q7, b) 278 | _, b = bits.Sub64(uint64(1) << 62, q8, b) 279 | 280 | // decrement the result 281 | x0, t := bits.Sub64(r4l, 1, 0) 282 | x1, t = bits.Sub64(r4k, 0, t) 283 | x2, t = bits.Sub64(r4j, 0, t) 284 | x3, t = bits.Sub64(r4i, 0, t) 285 | x4, _ = bits.Sub64(r4h, 0, t) 286 | 287 | // commit the decrement if the subtraction underflowed (reciprocal was too large) 288 | if b != 0 { 289 | r4h, r4i, r4j, r4k, r4l = x4, x3, x2, x1, x0 290 | } 291 | 292 | // Shift to correct bit alignment, truncating excess bits 293 | 294 | p = (p & 63) - 1 295 | 296 | x0, c = bits.Add64(r4l, r4l, 0) 297 | x1, c = bits.Add64(r4k, r4k, c) 298 | x2, c = bits.Add64(r4j, r4j, c) 299 | x3, c = bits.Add64(r4i, r4i, c) 300 | x4, _ = bits.Add64(r4h, r4h, c) 301 | 302 | if p < 0 { 303 | r4h, r4i, r4j, r4k, r4l = x4, x3, x2, x1, x0 304 | p = 0 // avoid negative shift below 305 | } 306 | 307 | { 308 | r := uint(p) // right shift 309 | l := uint(64 - r) // left shift 310 | 311 | x0 = (r4l >> r) | (r4k << l) 312 | x1 = (r4k >> r) | (r4j << l) 313 | x2 = (r4j >> r) | (r4i << l) 314 | x3 = (r4i >> r) | (r4h << l) 315 | x4 = (r4h >> r) 316 | } 317 | 318 | if p > 0 { 319 | r4h, r4i, r4j, r4k, r4l = x4, x3, x2, x1, x0 320 | } 321 | 322 | mu[0] = r4l 323 | mu[1] = r4k 324 | mu[2] = r4j 325 | mu[3] = r4i 326 | mu[4] = r4h 327 | 328 | return mu 329 | } 330 | 331 | // reduce4 computes the least non-negative residue of x modulo m 332 | // 333 | // requires a four-word modulus (m[3] != 0) and its inverse (mu) 334 | func (z *Int) reduce4(x *[8]uint64, m *Int, mu *[5]uint64) *Int { 335 | 336 | // NB: Most variable names in the comments match the pseudocode for 337 | // Barrett reduction in the Handbook of Applied Cryptography. 338 | 339 | // q1 = x/2^192 340 | 341 | x0 := x[3] 342 | x1 := x[4] 343 | x2 := x[5] 344 | x3 := x[6] 345 | x4 := x[7] 346 | 347 | // q2 = q1 * mu; q3 = q2 / 2^320 348 | 349 | var q0, q1, q2, q3, q4, q5, t0, t1, c uint64 350 | 351 | q0, _ = bits.Mul64(x3, mu[0]) 352 | q1, t0 = bits.Mul64(x4, mu[0]); q0, c = bits.Add64(q0, t0, 0); q1, _ = bits.Add64(q1, 0, c) 353 | 354 | 355 | t1, _ = bits.Mul64(x2, mu[1]); q0, c = bits.Add64(q0, t1, 0) 356 | q2, t0 = bits.Mul64(x4, mu[1]); q1, c = bits.Add64(q1, t0, c); q2, _ = bits.Add64(q2, 0, c) 357 | 358 | t1, t0 = bits.Mul64(x3, mu[1]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c); q2, _ = bits.Add64(q2, 0, c) 359 | 360 | 361 | t1, t0 = bits.Mul64(x2, mu[2]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) 362 | q3, t0 = bits.Mul64(x4, mu[2]); q2, c = bits.Add64(q2, t0, c); q3, _ = bits.Add64(q3, 0, c) 363 | 364 | t1, _ = bits.Mul64(x1, mu[2]); q0, c = bits.Add64(q0, t1, 0) 365 | t1, t0 = bits.Mul64(x3, mu[2]); q1, c = bits.Add64(q1, t0, c); q2, c = bits.Add64(q2, t1, c); q3, _ = bits.Add64(q3, 0, c) 366 | 367 | 368 | t1, _ = bits.Mul64(x0, mu[3]); q0, c = bits.Add64(q0, t1, 0) 369 | t1, t0 = bits.Mul64(x2, mu[3]); q1, c = bits.Add64(q1, t0, c); q2, c = bits.Add64(q2, t1, c) 370 | q4, t0 = bits.Mul64(x4, mu[3]); q3, c = bits.Add64(q3, t0, c); q4, _ = bits.Add64(q4, 0, c) 371 | 372 | t1, t0 = bits.Mul64(x1, mu[3]); q0, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) 373 | t1, t0 = bits.Mul64(x3, mu[3]); q2, c = bits.Add64(q2, t0, c); q3, c = bits.Add64(q3, t1, c); q4, _ = bits.Add64(q4, 0, c) 374 | 375 | 376 | t1, t0 = bits.Mul64(x0, mu[4]); _, c = bits.Add64(q0, t0, 0); q1, c = bits.Add64(q1, t1, c) 377 | t1, t0 = bits.Mul64(x2, mu[4]); q2, c = bits.Add64(q2, t0, c); q3, c = bits.Add64(q3, t1, c) 378 | q5, t0 = bits.Mul64(x4, mu[4]); q4, c = bits.Add64(q4, t0, c); q5, _ = bits.Add64(q5, 0, c) 379 | 380 | t1, t0 = bits.Mul64(x1, mu[4]); q1, c = bits.Add64(q1, t0, 0); q2, c = bits.Add64(q2, t1, c) 381 | t1, t0 = bits.Mul64(x3, mu[4]); q3, c = bits.Add64(q3, t0, c); q4, c = bits.Add64(q4, t1, c); q5, _ = bits.Add64(q5, 0, c) 382 | 383 | // Drop the fractional part of q3 384 | 385 | q0 = q1 386 | q1 = q2 387 | q2 = q3 388 | q3 = q4 389 | q4 = q5 390 | 391 | // r1 = x mod 2^320 392 | 393 | x0 = x[0] 394 | x1 = x[1] 395 | x2 = x[2] 396 | x3 = x[3] 397 | x4 = x[4] 398 | 399 | // r2 = q3 * m mod 2^320 400 | 401 | var r0, r1, r2, r3, r4 uint64 402 | 403 | r4, r3 = bits.Mul64(q0, m[3]) 404 | _, t0 = bits.Mul64(q1, m[3]); r4, _ = bits.Add64(r4, t0, 0) 405 | 406 | 407 | t1, r2 = bits.Mul64(q0, m[2]); r3, c = bits.Add64(r3, t1, 0) 408 | _, t0 = bits.Mul64(q2, m[2]); r4, _ = bits.Add64(r4, t0, c) 409 | 410 | t1, t0 = bits.Mul64(q1, m[2]); r3, c = bits.Add64(r3, t0, 0); r4, _ = bits.Add64(r4, t1, c) 411 | 412 | 413 | t1, r1 = bits.Mul64(q0, m[1]); r2, c = bits.Add64(r2, t1, 0) 414 | t1, t0 = bits.Mul64(q2, m[1]); r3, c = bits.Add64(r3, t0, c); r4, _ = bits.Add64(r4, t1, c) 415 | 416 | t1, t0 = bits.Mul64(q1, m[1]); r2, c = bits.Add64(r2, t0, 0); r3, c = bits.Add64(r3, t1, c) 417 | _, t0 = bits.Mul64(q3, m[1]); r4, _ = bits.Add64(r4, t0, c) 418 | 419 | 420 | t1, r0 = bits.Mul64(q0, m[0]); r1, c = bits.Add64(r1, t1, 0) 421 | t1, t0 = bits.Mul64(q2, m[0]); r2, c = bits.Add64(r2, t0, c); r3, c = bits.Add64(r3, t1, c) 422 | _, t0 = bits.Mul64(q4, m[0]); r4, _ = bits.Add64(r4, t0, c) 423 | 424 | t1, t0 = bits.Mul64(q1, m[0]); r1, c = bits.Add64(r1, t0, 0); r2, c = bits.Add64(r2, t1, c) 425 | t1, t0 = bits.Mul64(q3, m[0]); r3, c = bits.Add64(r3, t0, c); r4, _ = bits.Add64(r4, t1, c) 426 | 427 | 428 | // r = r1 - r2 429 | 430 | var b uint64 431 | 432 | r0, b = bits.Sub64(x0, r0, 0) 433 | r1, b = bits.Sub64(x1, r1, b) 434 | r2, b = bits.Sub64(x2, r2, b) 435 | r3, b = bits.Sub64(x3, r3, b) 436 | r4, b = bits.Sub64(x4, r4, b) 437 | 438 | // if r<0 then r+=m 439 | 440 | if b != 0 { 441 | r0, c = bits.Add64(r0, m[0], 0) 442 | r1, c = bits.Add64(r1, m[1], c) 443 | r2, c = bits.Add64(r2, m[2], c) 444 | r3, c = bits.Add64(r3, m[3], c) 445 | r4, _ = bits.Add64(r4, 0, c) 446 | } 447 | 448 | // while (r>=m) r-=m 449 | 450 | for { 451 | // q = r - m 452 | q0, b = bits.Sub64(r0, m[0], 0) 453 | q1, b = bits.Sub64(r1, m[1], b) 454 | q2, b = bits.Sub64(r2, m[2], b) 455 | q3, b = bits.Sub64(r3, m[3], b) 456 | q4, b = bits.Sub64(r4, 0, b) 457 | 458 | // if borrow break 459 | if b != 0 { 460 | break 461 | } 462 | 463 | // r = q 464 | r4, r3, r2, r1, r0 = q4, q3, q2, q1, q0 465 | } 466 | 467 | z[3], z[2], z[1], z[0] = r3, r2, r1, r0 468 | 469 | return z 470 | } 471 | -------------------------------------------------------------------------------- /conversion.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "database/sql" 9 | "database/sql/driver" 10 | "encoding" 11 | "encoding/binary" 12 | "encoding/json" 13 | "errors" 14 | "fmt" 15 | "io" 16 | "math" 17 | "math/big" 18 | "math/bits" 19 | "strings" 20 | ) 21 | 22 | const ( 23 | maxWords = 256 / bits.UintSize // number of big.Words in 256-bit 24 | 25 | // The constants below work as compile-time checks: in case evaluated to 26 | // negative value it cannot be assigned to uint type and compilation fails. 27 | // These particular expressions check if maxWords either 4 or 8 matching 28 | // 32-bit and 64-bit architectures. 29 | _ uint = -(maxWords & (maxWords - 1)) // maxWords is power of two. 30 | _ uint = -(maxWords & ^(4 | 8)) // maxWords is 4 or 8. 31 | ) 32 | 33 | // Compile time interface checks 34 | var ( 35 | _ driver.Valuer = (*Int)(nil) 36 | _ sql.Scanner = (*Int)(nil) 37 | _ encoding.TextMarshaler = (*Int)(nil) 38 | _ encoding.TextUnmarshaler = (*Int)(nil) 39 | _ json.Marshaler = (*Int)(nil) 40 | _ json.Unmarshaler = (*Int)(nil) 41 | ) 42 | 43 | // ToBig returns a big.Int version of z. 44 | // Return `nil` if z is nil 45 | func (z *Int) ToBig() *big.Int { 46 | if z == nil { 47 | return nil 48 | } 49 | var b *big.Int 50 | z.IntoBig(&b) 51 | return b 52 | } 53 | 54 | // IntoBig sets a provided big.Int to the value of z. 55 | // Sets `nil` if z is nil (thus the double pointer). 56 | func (z *Int) IntoBig(b **big.Int) { 57 | if z == nil { 58 | *b = nil 59 | return 60 | } 61 | if *b == nil { 62 | *b = new(big.Int) 63 | } 64 | switch maxWords { // Compile-time check. 65 | case 4: // 64-bit architectures. 66 | if words := (*b).Bits(); cap(words) >= 4 { 67 | // Enough underlying space to set all the uint256 data 68 | words = words[:4] 69 | 70 | words[0] = big.Word(z[0]) 71 | words[1] = big.Word(z[1]) 72 | words[2] = big.Word(z[2]) 73 | words[3] = big.Word(z[3]) 74 | 75 | // Feed it back to normalize (up or down within the big.Int) 76 | (*b).SetBits(words) 77 | } else { 78 | // Not enough space to set all the words, have to allocate 79 | words := [4]big.Word{big.Word(z[0]), big.Word(z[1]), big.Word(z[2]), big.Word(z[3])} 80 | (*b).SetBits(words[:]) 81 | } 82 | case 8: // 32-bit architectures. 83 | if words := (*b).Bits(); cap(words) >= 8 { 84 | // Enough underlying space to set all the uint256 data 85 | words = words[:8] 86 | 87 | words[0], words[1] = big.Word(z[0]), big.Word(z[0]>>32) 88 | words[2], words[3] = big.Word(z[1]), big.Word(z[1]>>32) 89 | words[4], words[5] = big.Word(z[2]), big.Word(z[2]>>32) 90 | words[6], words[7] = big.Word(z[3]), big.Word(z[3]>>32) 91 | 92 | // Feed it back to normalize (up or down within the big.Int) 93 | (*b).SetBits(words) 94 | } else { 95 | // Not enough space to set all the words, have to allocate 96 | words := [8]big.Word{ 97 | big.Word(z[0]), big.Word(z[0] >> 32), 98 | big.Word(z[1]), big.Word(z[1] >> 32), 99 | big.Word(z[2]), big.Word(z[2] >> 32), 100 | big.Word(z[3]), big.Word(z[3] >> 32), 101 | } 102 | (*b).SetBits(words[:]) 103 | } 104 | } 105 | } 106 | 107 | // FromBig is a convenience-constructor from big.Int. 108 | // Returns a new Int and whether overflow occurred. 109 | // OBS: If b is `nil`, this method returns `nil, false` 110 | func FromBig(b *big.Int) (*Int, bool) { 111 | if b == nil { 112 | return nil, false 113 | } 114 | z := &Int{} 115 | overflow := z.SetFromBig(b) 116 | return z, overflow 117 | } 118 | 119 | // MustFromBig is a convenience-constructor from big.Int. 120 | // Returns a new Int and panics if overflow occurred. 121 | // OBS: If b is `nil`, this method does _not_ panic, but 122 | // instead returns `nil` 123 | func MustFromBig(b *big.Int) *Int { 124 | if b == nil { 125 | return nil 126 | } 127 | z := &Int{} 128 | if z.SetFromBig(b) { 129 | panic("overflow") 130 | } 131 | return z 132 | } 133 | 134 | // Float64 returns the float64 value nearest to x. 135 | // 136 | // Note: The `big.Float` version of `Float64` also returns an 'Accuracy', indicating 137 | // whether the value was too small or too large to be represented by a 138 | // `float64`. However, the `uint256` type is unable to represent values 139 | // out of scope (|x| < math.SmallestNonzeroFloat64 or |x| > math.MaxFloat64), 140 | // therefore this method does not return any accuracy. 141 | func (z *Int) Float64() float64 { 142 | if z.IsUint64() { 143 | return float64(z.Uint64()) 144 | } 145 | // See [1] for a detailed walkthrough of IEEE 754 conversion 146 | // 147 | // 1: https://www.wikihow.com/Convert-a-Number-from-Decimal-to-IEEE-754-Floating-Point-Representation 148 | 149 | bitlen := uint64(z.BitLen()) 150 | 151 | // Normalize the number, by shifting it so that the MSB is shifted out. 152 | y := new(Int).Lsh(z, uint(1+256-bitlen)) 153 | // The number with the leading 1 shifted out is the fraction. 154 | fraction := y[3] 155 | 156 | // The exp is calculated from the number of shifts, adjusted with the bias. 157 | // double-precision uses 1023 as bias 158 | biased_exp := 1023 + bitlen - 1 159 | 160 | // The IEEE 754 double-precision layout is as follows: 161 | // 1 sign bit (we don't bother with this, since it's always zero for uints) 162 | // 11 exponent bits 163 | // 52 fraction bits 164 | // -------- 165 | // 64 bits 166 | 167 | return math.Float64frombits(biased_exp<<52 | fraction>>12) 168 | } 169 | 170 | // SetFromHex sets z from the given string, interpreted as a hexadecimal number. 171 | // OBS! This method is _not_ strictly identical to the (*big.Int).SetString(..., 16) method. 172 | // Notable differences: 173 | // - This method _require_ "0x" or "0X" prefix. 174 | // - This method does not accept zero-prefixed hex, e.g. "0x0001" 175 | // - This method does not accept underscore input, e.g. "100_000", 176 | // - This method does not accept negative zero as valid, e.g "-0x0", 177 | // - (this method does not accept any negative input as valid) 178 | func (z *Int) SetFromHex(hex string) error { 179 | return z.fromHex(hex) 180 | } 181 | 182 | // fromHex is the internal implementation of parsing a hex-string. 183 | func (z *Int) fromHex(hex string) error { 184 | if err := checkNumberS(hex); err != nil { 185 | return err 186 | } 187 | if len(hex) > 66 { 188 | return ErrBig256Range 189 | } 190 | z.Clear() 191 | end := len(hex) 192 | for i := 0; i < 4; i++ { 193 | start := end - 16 194 | if start < 2 { 195 | start = 2 196 | } 197 | for ri := start; ri < end; ri++ { 198 | nib := bintable[hex[ri]] 199 | if nib == badNibble { 200 | return ErrSyntax 201 | } 202 | z[i] = z[i] << 4 203 | z[i] += uint64(nib) 204 | } 205 | end = start 206 | } 207 | return nil 208 | } 209 | 210 | // FromHex is a convenience-constructor to create an Int from 211 | // a hexadecimal string. The string is required to be '0x'-prefixed 212 | // Numbers larger than 256 bits are not accepted. 213 | func FromHex(hex string) (*Int, error) { 214 | var z Int 215 | if err := z.fromHex(hex); err != nil { 216 | return nil, err 217 | } 218 | return &z, nil 219 | } 220 | 221 | // MustFromHex is a convenience-constructor to create an Int from 222 | // a hexadecimal string. 223 | // Returns a new Int and panics if any error occurred. 224 | func MustFromHex(hex string) *Int { 225 | var z Int 226 | if err := z.fromHex(hex); err != nil { 227 | panic(err) 228 | } 229 | return &z 230 | } 231 | 232 | // UnmarshalText implements encoding.TextUnmarshaler. This method 233 | // can unmarshal either hexadecimal or decimal. 234 | // - For hexadecimal, the input _must_ be prefixed with 0x or 0X 235 | func (z *Int) UnmarshalText(input []byte) error { 236 | if len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') { 237 | return z.fromHex(string(input)) 238 | } 239 | return z.SetFromDecimal(string(input)) 240 | } 241 | 242 | // SetFromBig converts a big.Int to Int and sets the value to z. 243 | // TODO: Ensure we have sufficient testing, esp for negative bigints. 244 | func (z *Int) SetFromBig(b *big.Int) bool { 245 | z.Clear() 246 | words := b.Bits() 247 | overflow := len(words) > maxWords 248 | 249 | switch maxWords { // Compile-time check. 250 | case 4: // 64-bit architectures. 251 | if len(words) > 0 { 252 | z[0] = uint64(words[0]) 253 | if len(words) > 1 { 254 | z[1] = uint64(words[1]) 255 | if len(words) > 2 { 256 | z[2] = uint64(words[2]) 257 | if len(words) > 3 { 258 | z[3] = uint64(words[3]) 259 | } 260 | } 261 | } 262 | } 263 | case 8: // 32-bit architectures. 264 | numWords := len(words) 265 | if overflow { 266 | numWords = maxWords 267 | } 268 | for i := 0; i < numWords; i++ { 269 | if i%2 == 0 { 270 | z[i/2] = uint64(words[i]) 271 | } else { 272 | z[i/2] |= uint64(words[i]) << 32 273 | } 274 | } 275 | } 276 | 277 | if b.Sign() == -1 { 278 | z.Neg(z) 279 | } 280 | return overflow 281 | } 282 | 283 | // Format implements fmt.Formatter. It accepts the formats 284 | // 'b' (binary), 'o' (octal with 0 prefix), 'O' (octal with 0o prefix), 285 | // 'd' (decimal), 'x' (lowercase hexadecimal), and 286 | // 'X' (uppercase hexadecimal). 287 | // Also supported are the full suite of package fmt's format 288 | // flags for integral types, including '+' and ' ' for sign 289 | // control, '#' for leading zero in octal and for hexadecimal, 290 | // a leading "0x" or "0X" for "%#x" and "%#X" respectively, 291 | // specification of minimum digits precision, output field 292 | // width, space or zero padding, and '-' for left or right 293 | // justification. 294 | func (z *Int) Format(s fmt.State, ch rune) { 295 | z.ToBig().Format(s, ch) 296 | } 297 | 298 | // SetBytes8 is identical to SetBytes(in[:8]), but panics is input is too short 299 | func (z *Int) SetBytes8(in []byte) *Int { 300 | _ = in[7] // bounds check hint to compiler; see golang.org/issue/14808 301 | z[3], z[2], z[1] = 0, 0, 0 302 | z[0] = binary.BigEndian.Uint64(in[0:8]) 303 | return z 304 | } 305 | 306 | // SetBytes16 is identical to SetBytes(in[:16]), but panics is input is too short 307 | func (z *Int) SetBytes16(in []byte) *Int { 308 | _ = in[15] // bounds check hint to compiler; see golang.org/issue/14808 309 | z[3], z[2] = 0, 0 310 | z[1] = binary.BigEndian.Uint64(in[0:8]) 311 | z[0] = binary.BigEndian.Uint64(in[8:16]) 312 | return z 313 | } 314 | 315 | // SetBytes24 is identical to SetBytes(in[:24]), but panics is input is too short 316 | func (z *Int) SetBytes24(in []byte) *Int { 317 | _ = in[23] // bounds check hint to compiler; see golang.org/issue/14808 318 | z[3] = 0 319 | z[2] = binary.BigEndian.Uint64(in[0:8]) 320 | z[1] = binary.BigEndian.Uint64(in[8:16]) 321 | z[0] = binary.BigEndian.Uint64(in[16:24]) 322 | return z 323 | } 324 | 325 | func (z *Int) SetBytes32(in []byte) *Int { 326 | _ = in[31] // bounds check hint to compiler; see golang.org/issue/14808 327 | z[3] = binary.BigEndian.Uint64(in[0:8]) 328 | z[2] = binary.BigEndian.Uint64(in[8:16]) 329 | z[1] = binary.BigEndian.Uint64(in[16:24]) 330 | z[0] = binary.BigEndian.Uint64(in[24:32]) 331 | return z 332 | } 333 | 334 | func (z *Int) SetBytes1(in []byte) *Int { 335 | z[3], z[2], z[1] = 0, 0, 0 336 | z[0] = uint64(in[0]) 337 | return z 338 | } 339 | 340 | func (z *Int) SetBytes9(in []byte) *Int { 341 | _ = in[8] // bounds check hint to compiler; see golang.org/issue/14808 342 | z[3], z[2] = 0, 0 343 | z[1] = uint64(in[0]) 344 | z[0] = binary.BigEndian.Uint64(in[1:9]) 345 | return z 346 | } 347 | 348 | func (z *Int) SetBytes17(in []byte) *Int { 349 | _ = in[16] // bounds check hint to compiler; see golang.org/issue/14808 350 | z[3] = 0 351 | z[2] = uint64(in[0]) 352 | z[1] = binary.BigEndian.Uint64(in[1:9]) 353 | z[0] = binary.BigEndian.Uint64(in[9:17]) 354 | return z 355 | } 356 | 357 | func (z *Int) SetBytes25(in []byte) *Int { 358 | _ = in[24] // bounds check hint to compiler; see golang.org/issue/14808 359 | z[3] = uint64(in[0]) 360 | z[2] = binary.BigEndian.Uint64(in[1:9]) 361 | z[1] = binary.BigEndian.Uint64(in[9:17]) 362 | z[0] = binary.BigEndian.Uint64(in[17:25]) 363 | return z 364 | } 365 | 366 | func (z *Int) SetBytes2(in []byte) *Int { 367 | _ = in[1] // bounds check hint to compiler; see golang.org/issue/14808 368 | z[3], z[2], z[1] = 0, 0, 0 369 | z[0] = uint64(binary.BigEndian.Uint16(in[0:2])) 370 | return z 371 | } 372 | 373 | func (z *Int) SetBytes10(in []byte) *Int { 374 | _ = in[9] // bounds check hint to compiler; see golang.org/issue/14808 375 | z[3], z[2] = 0, 0 376 | z[1] = uint64(binary.BigEndian.Uint16(in[0:2])) 377 | z[0] = binary.BigEndian.Uint64(in[2:10]) 378 | return z 379 | } 380 | 381 | func (z *Int) SetBytes18(in []byte) *Int { 382 | _ = in[17] // bounds check hint to compiler; see golang.org/issue/14808 383 | z[3] = 0 384 | z[2] = uint64(binary.BigEndian.Uint16(in[0:2])) 385 | z[1] = binary.BigEndian.Uint64(in[2:10]) 386 | z[0] = binary.BigEndian.Uint64(in[10:18]) 387 | return z 388 | } 389 | 390 | func (z *Int) SetBytes26(in []byte) *Int { 391 | _ = in[25] // bounds check hint to compiler; see golang.org/issue/14808 392 | z[3] = uint64(binary.BigEndian.Uint16(in[0:2])) 393 | z[2] = binary.BigEndian.Uint64(in[2:10]) 394 | z[1] = binary.BigEndian.Uint64(in[10:18]) 395 | z[0] = binary.BigEndian.Uint64(in[18:26]) 396 | return z 397 | } 398 | 399 | func (z *Int) SetBytes3(in []byte) *Int { 400 | _ = in[2] // bounds check hint to compiler; see golang.org/issue/14808 401 | z[3], z[2], z[1] = 0, 0, 0 402 | z[0] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16 403 | return z 404 | } 405 | 406 | func (z *Int) SetBytes11(in []byte) *Int { 407 | _ = in[10] // bounds check hint to compiler; see golang.org/issue/14808 408 | z[3], z[2] = 0, 0 409 | z[1] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16 410 | z[0] = binary.BigEndian.Uint64(in[3:11]) 411 | return z 412 | } 413 | 414 | func (z *Int) SetBytes19(in []byte) *Int { 415 | _ = in[18] // bounds check hint to compiler; see golang.org/issue/14808 416 | z[3] = 0 417 | z[2] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16 418 | z[1] = binary.BigEndian.Uint64(in[3:11]) 419 | z[0] = binary.BigEndian.Uint64(in[11:19]) 420 | return z 421 | } 422 | 423 | func (z *Int) SetBytes27(in []byte) *Int { 424 | _ = in[26] // bounds check hint to compiler; see golang.org/issue/14808 425 | z[3] = uint64(binary.BigEndian.Uint16(in[1:3])) | uint64(in[0])<<16 426 | z[2] = binary.BigEndian.Uint64(in[3:11]) 427 | z[1] = binary.BigEndian.Uint64(in[11:19]) 428 | z[0] = binary.BigEndian.Uint64(in[19:27]) 429 | return z 430 | } 431 | 432 | func (z *Int) SetBytes4(in []byte) *Int { 433 | _ = in[3] // bounds check hint to compiler; see golang.org/issue/14808 434 | z[3], z[2], z[1] = 0, 0, 0 435 | z[0] = uint64(binary.BigEndian.Uint32(in[0:4])) 436 | return z 437 | } 438 | 439 | func (z *Int) SetBytes12(in []byte) *Int { 440 | _ = in[11] // bounds check hint to compiler; see golang.org/issue/14808 441 | z[3], z[2] = 0, 0 442 | z[1] = uint64(binary.BigEndian.Uint32(in[0:4])) 443 | z[0] = binary.BigEndian.Uint64(in[4:12]) 444 | return z 445 | } 446 | 447 | func (z *Int) SetBytes20(in []byte) *Int { 448 | _ = in[19] // bounds check hint to compiler; see golang.org/issue/14808 449 | z[3] = 0 450 | z[2] = uint64(binary.BigEndian.Uint32(in[0:4])) 451 | z[1] = binary.BigEndian.Uint64(in[4:12]) 452 | z[0] = binary.BigEndian.Uint64(in[12:20]) 453 | return z 454 | } 455 | 456 | func (z *Int) SetBytes28(in []byte) *Int { 457 | _ = in[27] // bounds check hint to compiler; see golang.org/issue/14808 458 | z[3] = uint64(binary.BigEndian.Uint32(in[0:4])) 459 | z[2] = binary.BigEndian.Uint64(in[4:12]) 460 | z[1] = binary.BigEndian.Uint64(in[12:20]) 461 | z[0] = binary.BigEndian.Uint64(in[20:28]) 462 | return z 463 | } 464 | 465 | func (z *Int) SetBytes5(in []byte) *Int { 466 | _ = in[4] // bounds check hint to compiler; see golang.org/issue/14808 467 | z[3], z[2], z[1] = 0, 0, 0 468 | z[0] = bigEndianUint40(in[0:5]) 469 | return z 470 | } 471 | 472 | func (z *Int) SetBytes13(in []byte) *Int { 473 | _ = in[12] // bounds check hint to compiler; see golang.org/issue/14808 474 | z[3], z[2] = 0, 0 475 | z[1] = bigEndianUint40(in[0:5]) 476 | z[0] = binary.BigEndian.Uint64(in[5:13]) 477 | return z 478 | } 479 | 480 | func (z *Int) SetBytes21(in []byte) *Int { 481 | _ = in[20] // bounds check hint to compiler; see golang.org/issue/14808 482 | z[3] = 0 483 | z[2] = bigEndianUint40(in[0:5]) 484 | z[1] = binary.BigEndian.Uint64(in[5:13]) 485 | z[0] = binary.BigEndian.Uint64(in[13:21]) 486 | return z 487 | } 488 | 489 | func (z *Int) SetBytes29(in []byte) *Int { 490 | _ = in[28] // bounds check hint to compiler; see golang.org/issue/14808 491 | z[3] = bigEndianUint40(in[0:5]) 492 | z[2] = binary.BigEndian.Uint64(in[5:13]) 493 | z[1] = binary.BigEndian.Uint64(in[13:21]) 494 | z[0] = binary.BigEndian.Uint64(in[21:29]) 495 | return z 496 | } 497 | 498 | func (z *Int) SetBytes6(in []byte) *Int { 499 | _ = in[5] // bounds check hint to compiler; see golang.org/issue/14808 500 | z[3], z[2], z[1] = 0, 0, 0 501 | z[0] = bigEndianUint48(in[0:6]) 502 | return z 503 | } 504 | 505 | func (z *Int) SetBytes14(in []byte) *Int { 506 | _ = in[13] // bounds check hint to compiler; see golang.org/issue/14808 507 | z[3], z[2] = 0, 0 508 | z[1] = bigEndianUint48(in[0:6]) 509 | z[0] = binary.BigEndian.Uint64(in[6:14]) 510 | return z 511 | } 512 | 513 | func (z *Int) SetBytes22(in []byte) *Int { 514 | _ = in[21] // bounds check hint to compiler; see golang.org/issue/14808 515 | z[3] = 0 516 | z[2] = bigEndianUint48(in[0:6]) 517 | z[1] = binary.BigEndian.Uint64(in[6:14]) 518 | z[0] = binary.BigEndian.Uint64(in[14:22]) 519 | return z 520 | } 521 | 522 | func (z *Int) SetBytes30(in []byte) *Int { 523 | _ = in[29] // bounds check hint to compiler; see golang.org/issue/14808 524 | z[3] = bigEndianUint48(in[0:6]) 525 | z[2] = binary.BigEndian.Uint64(in[6:14]) 526 | z[1] = binary.BigEndian.Uint64(in[14:22]) 527 | z[0] = binary.BigEndian.Uint64(in[22:30]) 528 | return z 529 | } 530 | 531 | func (z *Int) SetBytes7(in []byte) *Int { 532 | _ = in[6] // bounds check hint to compiler; see golang.org/issue/14808 533 | z[3], z[2], z[1] = 0, 0, 0 534 | z[0] = bigEndianUint56(in[0:7]) 535 | return z 536 | } 537 | 538 | func (z *Int) SetBytes15(in []byte) *Int { 539 | _ = in[14] // bounds check hint to compiler; see golang.org/issue/14808 540 | z[3], z[2] = 0, 0 541 | z[1] = bigEndianUint56(in[0:7]) 542 | z[0] = binary.BigEndian.Uint64(in[7:15]) 543 | return z 544 | } 545 | 546 | func (z *Int) SetBytes23(in []byte) *Int { 547 | _ = in[22] // bounds check hint to compiler; see golang.org/issue/14808 548 | z[3] = 0 549 | z[2] = bigEndianUint56(in[0:7]) 550 | z[1] = binary.BigEndian.Uint64(in[7:15]) 551 | z[0] = binary.BigEndian.Uint64(in[15:23]) 552 | return z 553 | } 554 | 555 | func (z *Int) SetBytes31(in []byte) *Int { 556 | _ = in[30] // bounds check hint to compiler; see golang.org/issue/14808 557 | z[3] = bigEndianUint56(in[0:7]) 558 | z[2] = binary.BigEndian.Uint64(in[7:15]) 559 | z[1] = binary.BigEndian.Uint64(in[15:23]) 560 | z[0] = binary.BigEndian.Uint64(in[23:31]) 561 | return z 562 | } 563 | 564 | // Utility methods that are "missing" among the bigEndian.UintXX methods. 565 | 566 | func bigEndianUint40(b []byte) uint64 { 567 | _ = b[4] // bounds check hint to compiler; see golang.org/issue/14808 568 | return uint64(b[4]) | uint64(b[3])<<8 | uint64(b[2])<<16 | uint64(b[1])<<24 | 569 | uint64(b[0])<<32 570 | } 571 | 572 | func bigEndianUint48(b []byte) uint64 { 573 | _ = b[5] // bounds check hint to compiler; see golang.org/issue/14808 574 | return uint64(b[5]) | uint64(b[4])<<8 | uint64(b[3])<<16 | uint64(b[2])<<24 | 575 | uint64(b[1])<<32 | uint64(b[0])<<40 576 | } 577 | 578 | func bigEndianUint56(b []byte) uint64 { 579 | _ = b[6] // bounds check hint to compiler; see golang.org/issue/14808 580 | return uint64(b[6]) | uint64(b[5])<<8 | uint64(b[4])<<16 | uint64(b[3])<<24 | 581 | uint64(b[2])<<32 | uint64(b[1])<<40 | uint64(b[0])<<48 582 | } 583 | 584 | // MarshalSSZAppend _almost_ implements the fastssz.Marshaler (see below) interface. 585 | // Originally, this method was named `MarshalSSZTo`, and ostensibly implemented the interface. 586 | // However, it was noted (https://github.com/holiman/uint256/issues/170) that the 587 | // actual implementation did not match the intended semantics of the interface: it 588 | // inserted the data instead of appending. 589 | // 590 | // Therefore, the `MarshalSSZTo` has been removed: to force users into making a choice: 591 | // - Use `MarshalSSZAppend`: this is the method that appends to the destination buffer, 592 | // and returns a potentially newly allocated buffer. This method will become `MarshalSSZTo` 593 | // in some future release. 594 | // - Or use `MarshalSSZInto`: this is the original method which places the data into 595 | // the destination buffer, without ever reallocating. 596 | // 597 | // fastssz.Marshaler interface: 598 | // 599 | // https://github.com/ferranbt/fastssz/blob/main/interface.go#L4 600 | // type Marshaler interface { 601 | // MarshalSSZTo(dst []byte) ([]byte, error) 602 | // MarshalSSZ() ([]byte, error) 603 | // SizeSSZ() int 604 | // } 605 | func (z *Int) MarshalSSZAppend(dst []byte) ([]byte, error) { 606 | dst = binary.LittleEndian.AppendUint64(dst, z[0]) 607 | dst = binary.LittleEndian.AppendUint64(dst, z[1]) 608 | dst = binary.LittleEndian.AppendUint64(dst, z[2]) 609 | dst = binary.LittleEndian.AppendUint64(dst, z[3]) 610 | return dst, nil 611 | } 612 | 613 | // MarshalSSZInto is the first attempt to implement the fastssz.Marshaler interface, 614 | // but which does not obey the intended semantics. See MarshalSSZAppend and 615 | // - https://github.com/holiman/uint256/pull/171 616 | // - https://github.com/holiman/uint256/issues/170 617 | // @deprecated 618 | func (z *Int) MarshalSSZInto(dst []byte) ([]byte, error) { 619 | if len(dst) < 32 { 620 | return nil, fmt.Errorf("%w: have %d, want %d bytes", ErrBadBufferLength, len(dst), 32) 621 | } 622 | binary.LittleEndian.PutUint64(dst[0:8], z[0]) 623 | binary.LittleEndian.PutUint64(dst[8:16], z[1]) 624 | binary.LittleEndian.PutUint64(dst[16:24], z[2]) 625 | binary.LittleEndian.PutUint64(dst[24:32], z[3]) 626 | 627 | return dst[32:], nil 628 | } 629 | 630 | // MarshalSSZ implements the fastssz.Marshaler interface and returns the integer 631 | // marshalled into a newly allocated byte slice. 632 | func (z *Int) MarshalSSZ() ([]byte, error) { 633 | blob, _ := z.MarshalSSZAppend(make([]byte, 0, 32)) // ignore error, cannot fail, surely have 32 byte space in blob 634 | return blob, nil 635 | } 636 | 637 | // SizeSSZ implements the fastssz.Marshaler interface and returns the byte size 638 | // of the 256 bit int. 639 | func (*Int) SizeSSZ() int { 640 | return 32 641 | } 642 | 643 | // UnmarshalSSZ implements the fastssz.Unmarshaler interface and parses an encoded 644 | // integer into the local struct. 645 | func (z *Int) UnmarshalSSZ(buf []byte) error { 646 | if len(buf) != 32 { 647 | return fmt.Errorf("%w: have %d, want %d bytes", ErrBadEncodedLength, len(buf), 32) 648 | } 649 | z[0] = binary.LittleEndian.Uint64(buf[0:8]) 650 | z[1] = binary.LittleEndian.Uint64(buf[8:16]) 651 | z[2] = binary.LittleEndian.Uint64(buf[16:24]) 652 | z[3] = binary.LittleEndian.Uint64(buf[24:32]) 653 | 654 | return nil 655 | } 656 | 657 | // HashTreeRoot implements the fastssz.HashRoot interface's non-dependent part. 658 | func (z *Int) HashTreeRoot() ([32]byte, error) { 659 | b, _ := z.MarshalSSZAppend(make([]byte, 0, 32)) // ignore error, cannot fail 660 | var hash [32]byte 661 | copy(hash[:], b) 662 | return hash, nil 663 | } 664 | 665 | // EncodeRLP implements the rlp.Encoder interface from go-ethereum 666 | // and writes the RLP encoding of z to w. 667 | func (z *Int) EncodeRLP(w io.Writer) error { 668 | if z == nil { 669 | _, err := w.Write([]byte{0x80}) 670 | return err 671 | } 672 | nBits := z.BitLen() 673 | if nBits == 0 { 674 | _, err := w.Write([]byte{0x80}) 675 | return err 676 | } 677 | if nBits <= 7 { 678 | _, err := w.Write([]byte{byte(z[0])}) 679 | return err 680 | } 681 | nBytes := byte((nBits + 7) / 8) 682 | var b [33]byte 683 | binary.BigEndian.PutUint64(b[1:9], z[3]) 684 | binary.BigEndian.PutUint64(b[9:17], z[2]) 685 | binary.BigEndian.PutUint64(b[17:25], z[1]) 686 | binary.BigEndian.PutUint64(b[25:33], z[0]) 687 | b[32-nBytes] = 0x80 + nBytes 688 | _, err := w.Write(b[32-nBytes:]) 689 | return err 690 | } 691 | 692 | // MarshalText implements encoding.TextMarshaler 693 | // MarshalText marshals using the decimal representation (compatible with big.Int) 694 | func (z *Int) MarshalText() ([]byte, error) { 695 | return []byte(z.Dec()), nil 696 | } 697 | 698 | // MarshalJSON implements json.Marshaler. 699 | // MarshalJSON marshals using the 'decimal string' representation. This is _not_ compatible 700 | // with big.Int: big.Int marshals into JSON 'native' numeric format. 701 | // 702 | // The JSON native format is, on some platforms, (e.g. javascript), limited to 53-bit large 703 | // integer space. Thus, U256 uses string-format, which is not compatible with 704 | // big.int (big.Int refuses to unmarshal a string representation). 705 | func (z *Int) MarshalJSON() ([]byte, error) { 706 | return []byte(`"` + z.Dec() + `"`), nil 707 | } 708 | 709 | // UnmarshalJSON implements json.Unmarshaler. UnmarshalJSON accepts either 710 | // - Quoted string: either hexadecimal OR decimal 711 | // - Not quoted string: only decimal 712 | func (z *Int) UnmarshalJSON(input []byte) error { 713 | if len(input) < 2 || input[0] != '"' || input[len(input)-1] != '"' { 714 | // if not quoted, it must be decimal 715 | return z.SetFromDecimal(string(input)) 716 | } 717 | return z.UnmarshalText(input[1 : len(input)-1]) 718 | } 719 | 720 | // String returns the decimal encoding of b. 721 | func (z *Int) String() string { 722 | return z.Dec() 723 | } 724 | 725 | const ( 726 | hextable = "0123456789abcdef" 727 | bintable = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x01\x02\x03\x04\x05\x06\a\b\t\xff\xff\xff\xff\xff\xff\xff\n\v\f\r\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\n\v\f\r\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" 728 | badNibble = 0xff 729 | ) 730 | 731 | // Hex encodes z in 0x-prefixed hexadecimal form. 732 | func (z *Int) Hex() string { 733 | // This implementation is not optimal, it allocates a full 734 | // 66-byte output buffer which it fills. It could instead allocate a smaller 735 | // buffer, and omit the final crop-stage. 736 | output := make([]byte, 66) 737 | nibbles := (z.BitLen() + 3) / 4 // nibbles [0,64] 738 | if nibbles == 0 { 739 | nibbles = 1 740 | } 741 | // Start with the most significant 742 | zWord := (nibbles - 1) / 16 743 | for i := zWord; i >= 0; i-- { 744 | off := (3 - i) * 16 745 | output[off+2] = hextable[byte(z[i]>>60)&0xf] 746 | output[off+3] = hextable[byte(z[i]>>56)&0xf] 747 | output[off+4] = hextable[byte(z[i]>>52)&0xf] 748 | output[off+5] = hextable[byte(z[i]>>48)&0xf] 749 | output[off+6] = hextable[byte(z[i]>>44)&0xf] 750 | output[off+7] = hextable[byte(z[i]>>40)&0xf] 751 | output[off+8] = hextable[byte(z[i]>>36)&0xf] 752 | output[off+9] = hextable[byte(z[i]>>32)&0xf] 753 | output[off+10] = hextable[byte(z[i]>>28)&0xf] 754 | output[off+11] = hextable[byte(z[i]>>24)&0xf] 755 | output[off+12] = hextable[byte(z[i]>>20)&0xf] 756 | output[off+13] = hextable[byte(z[i]>>16)&0xf] 757 | output[off+14] = hextable[byte(z[i]>>12)&0xf] 758 | output[off+15] = hextable[byte(z[i]>>8)&0xf] 759 | output[off+16] = hextable[byte(z[i]>>4)&0xf] 760 | output[off+17] = hextable[byte(z[i]&0xF)&0xf] 761 | } 762 | output[64-nibbles] = '0' 763 | output[65-nibbles] = 'x' 764 | return string(output[64-nibbles:]) 765 | } 766 | 767 | // Scan implements the database/sql Scanner interface. 768 | // It decodes a string, because that is what postgres uses for its numeric type 769 | func (dst *Int) Scan(src interface{}) error { 770 | if src == nil { 771 | dst.Clear() 772 | return nil 773 | } 774 | switch src := src.(type) { 775 | case string: 776 | return dst.scanScientificFromString(src) 777 | case []byte: 778 | return dst.scanScientificFromString(string(src)) 779 | } 780 | return errors.New("unsupported type") 781 | } 782 | 783 | func (dst *Int) scanScientificFromString(src string) error { 784 | if len(src) == 0 { 785 | dst.Clear() 786 | return nil 787 | } 788 | idx := strings.IndexByte(src, 'e') 789 | if idx == -1 { 790 | return dst.SetFromDecimal(src) 791 | } 792 | if err := dst.SetFromDecimal(src[:idx]); err != nil { 793 | return err 794 | } 795 | if src[(idx+1):] == "0" { 796 | return nil 797 | } 798 | exp := new(Int) 799 | if err := exp.SetFromDecimal(src[(idx + 1):]); err != nil { 800 | return err 801 | } 802 | if exp.GtUint64(77) { // 10**78 is larger than 2**256 803 | return ErrBig256Range 804 | } 805 | exp.Exp(NewInt(10), exp) 806 | if _, overflow := dst.MulOverflow(dst, exp); overflow { 807 | return ErrBig256Range 808 | } 809 | return nil 810 | } 811 | 812 | // Value implements the database/sql/driver Valuer interface. 813 | // It encodes a base 10 string. 814 | // In Postgres, this will work with both integer and the Numeric/Decimal types 815 | // In MariaDB/MySQL, this will work with the Numeric/Decimal types up to 65 digits, however any more and you should use either VarChar or Char(79) 816 | // In SqLite, use TEXT 817 | func (src *Int) Value() (driver.Value, error) { 818 | return src.Dec(), nil 819 | } 820 | 821 | var ( 822 | ErrEmptyString = errors.New("empty hex string") 823 | ErrSyntax = errors.New("invalid hex string") 824 | ErrMissingPrefix = errors.New("hex string without 0x prefix") 825 | ErrEmptyNumber = errors.New("hex string \"0x\"") 826 | ErrLeadingZero = errors.New("hex number with leading zero digits") 827 | ErrBig256Range = errors.New("hex number > 256 bits") 828 | ErrBadBufferLength = errors.New("bad ssz buffer length") 829 | ErrBadEncodedLength = errors.New("bad ssz encoded length") 830 | ) 831 | 832 | func checkNumberS(input string) error { 833 | l := len(input) 834 | if l == 0 { 835 | return ErrEmptyString 836 | } 837 | if l < 2 || input[0] != '0' || 838 | (input[1] != 'x' && input[1] != 'X') { 839 | return ErrMissingPrefix 840 | } 841 | if l == 2 { 842 | return ErrEmptyNumber 843 | } 844 | if len(input) > 3 && input[2] == '0' { 845 | return ErrLeadingZero 846 | } 847 | return nil 848 | } 849 | -------------------------------------------------------------------------------- /uint256_test.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2018-2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "encoding/hex" 11 | "fmt" 12 | "math" 13 | "math/big" 14 | "testing" 15 | ) 16 | 17 | func hex2Bytes(str string) []byte { 18 | h, _ := hex.DecodeString(str) 19 | return h 20 | } 21 | 22 | func checkOverflow(b *big.Int, f *Int, overflow bool) error { 23 | max := big.NewInt(0).SetBytes(hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")) 24 | shouldOverflow := b.Cmp(max) > 0 25 | if overflow != shouldOverflow { 26 | return fmt.Errorf("Overflow should be %v, was %v\nf= %x\nb= %x\b", shouldOverflow, overflow, f, b) 27 | } 28 | return nil 29 | } 30 | 31 | func randNums() (*big.Int, *Int) { 32 | //How many bits? 0-256 33 | nbits, _ := rand.Int(rand.Reader, big.NewInt(257)) 34 | //Max random value, a 130-bits integer, i.e 2^130 35 | max := new(big.Int) 36 | max.Exp(big.NewInt(2), big.NewInt(nbits.Int64()), nil) 37 | b, _ := rand.Int(rand.Reader, max) 38 | f, overflow := FromBig(b) 39 | if err := checkOverflow(b, f, overflow); err != nil { 40 | panic(err) 41 | } 42 | return b, f 43 | } 44 | 45 | func randHighNums() (*big.Int, *Int) { 46 | //How many bits? 0-256 47 | nbits := int64(256) 48 | //Max random value, a 130-bits integer, i.e 2^130 49 | max := new(big.Int) 50 | max.Exp(big.NewInt(2), big.NewInt(nbits), nil) 51 | //Generate cryptographically strong pseudo-random between 0 - max 52 | b, _ := rand.Int(rand.Reader, max) 53 | f, overflow := FromBig(b) 54 | if err := checkOverflow(b, f, overflow); err != nil { 55 | panic(err) 56 | } 57 | return b, f 58 | } 59 | 60 | func checkEq(b *big.Int, f *Int) bool { 61 | f2, _ := FromBig(b) 62 | return f.Eq(f2) 63 | } 64 | 65 | func requireEq(t *testing.T, exp *big.Int, got *Int, txt string) bool { 66 | expF, _ := FromBig(exp) 67 | if !expF.Eq(got) { 68 | t.Errorf("got %x expected %x: %v\n", got, expF, txt) 69 | return false 70 | } 71 | return true 72 | } 73 | 74 | func TestRandomSubOverflow(t *testing.T) { 75 | for i := 0; i < 10000; i++ { 76 | b, f1 := randNums() 77 | b2, f2 := randNums() 78 | f1a, f2a := f1.Clone(), f2.Clone() 79 | _, overflow := f1.SubOverflow(f1, f2) 80 | b.Sub(b, b2) 81 | 82 | // check overflow 83 | if have, want := overflow, b.Cmp(big.NewInt(0)) < 0; have != want { 84 | t.Fatalf("underflow should be %v, was %v\nf= %x\nb= %x\b", have, want, f1, b) 85 | } 86 | if eq := checkEq(b, f1); !eq { 87 | t.Fatalf("Expected equality:\nf1= %x\nf2= %x\n[ - ]==\nf= %x\nb= %x\n", f1a, f2a, f1, b) 88 | } 89 | } 90 | } 91 | 92 | func TestRandomMulOverflow(t *testing.T) { 93 | for i := 0; i < 10000; i++ { 94 | b, f1 := randNums() 95 | b2, f2 := randNums() 96 | 97 | f1a, f2a := f1.Clone(), f2.Clone() 98 | _, overflow := f1.MulOverflow(f1, f2) 99 | b.Mul(b, b2) 100 | if err := checkOverflow(b, f1, overflow); err != nil { 101 | t.Fatal(err) 102 | } 103 | if eq := checkEq(b, f1); !eq { 104 | t.Fatalf("Expected equality:\nf1= %x\nf2= %x\n[ - ]==\nf= %x\nb= %x\n", f1a, f2a, f1, b) 105 | } 106 | } 107 | } 108 | 109 | func set3Int(s1, s2, s3, d1, d2, d3 *Int) { 110 | d1.Set(s1) 111 | d2.Set(s2) 112 | d3.Set(s3) 113 | } 114 | 115 | func set3Big(s1, s2, s3, d1, d2, d3 *big.Int) { 116 | d1.Set(s1) 117 | d2.Set(s2) 118 | d3.Set(s3) 119 | } 120 | 121 | func runMulModCase( 122 | t *testing.T, 123 | tA, tB, tMod, b *big.Int, 124 | uA, uB, uMod, f *Int, 125 | labelA, labelB, labelMod string, 126 | 127 | ) { 128 | 129 | // Test MulMod 130 | b.Mod(b.Mul(tA, tB), tMod) 131 | f.MulMod(uA, uB, uMod) 132 | if !checkEq(b, f) { 133 | t.Fatalf("MulMod Expected equality:\n%s= 0x%x\n%s= 0x%x\n%s= 0x%x\n[ op ]==\nf = %x\nb = %x\n", labelA, uA, labelB, uB, labelMod, uMod, f, b) 134 | } 135 | 136 | // Test IMulMod 137 | f.Set(uA) 138 | f.IMulMod(uB, uMod) 139 | if !checkEq(b, f) { 140 | t.Fatalf("IMulMod Expected equality:\n%s= 0x%x\n%s= 0x%x\n%s= 0x%x\n[ op ]==\nf = %x\nb = %x\n", labelA, uA, labelB, uB, labelMod, uMod, f, b) 141 | } 142 | } 143 | 144 | func TestRandomMulMod(t *testing.T) { 145 | // Random tests (10,000 iterations) for both MulMod and IMulMod 146 | for i := 0; i < 10000; i++ { 147 | b1, f1 := randNums() 148 | b2, f2 := randNums() 149 | b3, f3 := randNums() 150 | b4, f4 := randNums() 151 | for b4.Cmp(big.NewInt(0)) == 0 { 152 | b4, f4 = randNums() 153 | } 154 | 155 | // Test MulMod 156 | f1.MulMod(f2, f3, f4) 157 | b1.Mod(big.NewInt(0).Mul(b2, b3), b4) 158 | if !checkEq(b1, f1) { 159 | t.Fatalf("Expected equality:\nf2= %x\nf3= %x\nf4= %x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f4, f1, b1) 160 | } 161 | 162 | // Test MulModWithReciprocal 163 | f1.mulModWithReciprocalWrapper(f2, f3, f4) 164 | if !checkEq(b1, f1) { 165 | t.Fatalf("Expected equality:\nf2= %x\nf3= %x\nf4= %x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f4, f1, b1) 166 | } 167 | 168 | // Test IMulMod 169 | f1.Set(f2) 170 | f1.IMulMod(f3, f4) 171 | if !checkEq(b1, f1) { 172 | t.Fatalf("IMulMod Expected equality:\nf2= %x\nf3= %x\nf4= %x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f4, f1, b1) 173 | } 174 | 175 | // Test IMulModWithReciprocal 176 | f1.Set(f2) 177 | f1.iMulModWithReciprocalWrapper(f3, f4) 178 | if !checkEq(b1, f1) { 179 | t.Fatalf("IMulModWithReciprocal Expected equality:\nf2= %x\nf3= %x\nf4= %x\n[ op ]==\nf = %x\nb = %x\n", f2, f3, f4, f1, b1) 180 | } 181 | 182 | } 183 | 184 | // Tests related to powers of 2 185 | // Power of 2 tests with all 6 permutations of operands for both functions 186 | 187 | f_minusone := &Int{^uint64(0), ^uint64(0), ^uint64(0), ^uint64(0)} 188 | 189 | b_one := big.NewInt(1) 190 | b_minusone := big.NewInt(0) 191 | b_minusone = b_minusone.Sub(b_minusone, b_one) 192 | 193 | for i := uint(0); i < 256; i++ { 194 | b := big.NewInt(0) 195 | f := NewInt(0) 196 | 197 | t1, t2, t3 := b, b, b 198 | u1, u2, u3 := f, f, f 199 | 200 | b1 := b.Lsh(b, i) 201 | f1 := f.Lsh(f, i) 202 | 203 | b2, f2 := randNums() 204 | for b2.Cmp(big.NewInt(0)) == 0 { 205 | b2, f2 = randNums() 206 | } 207 | 208 | b3, f3 := randNums() 209 | for b3.Cmp(big.NewInt(0)) == 0 { 210 | b3, f3 = randNums() 211 | } 212 | 213 | // Tests with one operand a power of 2 214 | 215 | // --- 1 --- 216 | set3Big(b1, b2, b3, t1, t2, t3) 217 | set3Int(f1, f2, f3, u1, u2, u3) 218 | runMulModCase(t, t1, t2, t3, b, u1, u2, u3, f, "f1", "f2", "f3") 219 | 220 | // --- 2 --- 221 | set3Big(b1, b2, b3, t1, t2, t3) 222 | set3Int(f1, f2, f3, u1, u2, u3) 223 | runMulModCase(t, t1, t3, t2, b, u1, u3, u2, f, "f1", "f3", "f2") 224 | 225 | // --- 3 --- 226 | set3Big(b1, b2, b3, t1, t2, t3) 227 | set3Int(f1, f2, f3, u1, u2, u3) 228 | runMulModCase(t, t2, t1, t3, b, u2, u1, u3, f, "f2", "f1", "f3") 229 | 230 | // --- 4 --- 231 | set3Big(b1, b2, b3, t1, t2, t3) 232 | set3Int(f1, f2, f3, u1, u2, u3) 233 | runMulModCase(t, t2, t3, t1, b, u2, u3, u1, f, "f2", "f3", "f1") 234 | 235 | // --- 5 --- 236 | set3Big(b1, b2, b3, t1, t2, t3) 237 | set3Int(f1, f2, f3, u1, u2, u3) 238 | runMulModCase(t, t3, t1, t2, b, u3, u1, u2, f, "f3", "f1", "f2") 239 | 240 | // --- 6 --- 241 | set3Big(b1, b2, b3, t1, t2, t3) 242 | set3Int(f1, f2, f3, u1, u2, u3) 243 | runMulModCase(t, t3, t2, t1, b, u3, u2, u1, f, "f3", "f2", "f1") 244 | 245 | // Tests with one operand 2^256 minus a power of 2 246 | 247 | f1.Xor(f1, f_minusone) 248 | b1.Xor(b1, b_minusone) 249 | 250 | // Tests with one operand a power of 2 plus 1 251 | 252 | b1.Add(b1, b_one) 253 | f1.AddUint64(f1, 1) 254 | 255 | // --- 1 --- 256 | set3Big(b1, b2, b3, t1, t2, t3) 257 | set3Int(f1, f2, f3, u1, u2, u3) 258 | runMulModCase(t, t1, t2, t3, b, u1, u2, u3, f, "f1", "f2", "f3") 259 | 260 | // --- 2 --- 261 | set3Big(b1, b2, b3, t1, t2, t3) 262 | set3Int(f1, f2, f3, u1, u2, u3) 263 | runMulModCase(t, t1, t3, t2, b, u1, u3, u2, f, "f1", "f3", "f2") 264 | 265 | // --- 3 --- 266 | set3Big(b1, b2, b3, t1, t2, t3) 267 | set3Int(f1, f2, f3, u1, u2, u3) 268 | runMulModCase(t, t2, t1, t3, b, u2, u1, u3, f, "f2", "f1", "f3") 269 | 270 | // --- 4 --- 271 | set3Big(b1, b2, b3, t1, t2, t3) 272 | set3Int(f1, f2, f3, u1, u2, u3) 273 | runMulModCase(t, t2, t3, t1, b, u2, u3, u1, f, "f2", "f3", "f1") 274 | 275 | // --- 5 --- 276 | set3Big(b1, b2, b3, t1, t2, t3) 277 | set3Int(f1, f2, f3, u1, u2, u3) 278 | runMulModCase(t, t3, t1, t2, b, u3, u1, u2, f, "f3", "f1", "f2") 279 | 280 | // --- 6 --- 281 | set3Big(b1, b2, b3, t1, t2, t3) 282 | set3Int(f1, f2, f3, u1, u2, u3) 283 | runMulModCase(t, t3, t2, t1, b, u3, u2, u1, f, "f3", "f2", "f1") 284 | 285 | f1.Xor(f1, f_minusone) 286 | b1.Xor(b1, b_minusone) 287 | 288 | // Tests with one operand a power of 2 plus 1 289 | 290 | b1.Add(b1, b_one) 291 | f1.AddUint64(f1, 1) 292 | 293 | // --- 1 --- 294 | set3Big(b1, b2, b3, t1, t2, t3) 295 | set3Int(f1, f2, f3, u1, u2, u3) 296 | runMulModCase(t, t1, t2, t3, b, u1, u2, u3, f, "f1", "f2", "f3") 297 | 298 | // --- 2 --- 299 | set3Big(b1, b2, b3, t1, t2, t3) 300 | set3Int(f1, f2, f3, u1, u2, u3) 301 | runMulModCase(t, t1, t3, t2, b, u1, u3, u2, f, "f1", "f3", "f2") 302 | 303 | // --- 3 --- 304 | set3Big(b1, b2, b3, t1, t2, t3) 305 | set3Int(f1, f2, f3, u1, u2, u3) 306 | runMulModCase(t, t2, t1, t3, b, u2, u1, u3, f, "f2", "f1", "f3") 307 | 308 | // --- 4 --- 309 | set3Big(b1, b2, b3, t1, t2, t3) 310 | set3Int(f1, f2, f3, u1, u2, u3) 311 | runMulModCase(t, t2, t3, t1, b, u2, u3, u1, f, "f2", "f3", "f1") 312 | 313 | // --- 5 --- 314 | set3Big(b1, b2, b3, t1, t2, t3) 315 | set3Int(f1, f2, f3, u1, u2, u3) 316 | runMulModCase(t, t3, t1, t2, b, u3, u1, u2, f, "f3", "f1", "f2") 317 | 318 | // --- 6 --- 319 | set3Big(b1, b2, b3, t1, t2, t3) 320 | set3Int(f1, f2, f3, u1, u2, u3) 321 | runMulModCase(t, t3, t2, t1, b, u3, u2, u1, f, "f3", "f2", "f1") 322 | 323 | // Tests with one operand a power of 2 minus 1 324 | 325 | if i == 0 { 326 | continue // skip zero operand 327 | } 328 | 329 | b1.Sub(b1, b_one) 330 | b1.Sub(b1, b_one) 331 | f1.SubUint64(f1, 2) 332 | 333 | // --- 1 --- 334 | set3Big(b1, b2, b3, t1, t2, t3) 335 | set3Int(f1, f2, f3, u1, u2, u3) 336 | runMulModCase(t, t1, t2, t3, b, u1, u2, u3, f, "f1", "f2", "f3") 337 | 338 | // --- 2 --- 339 | set3Big(b1, b2, b3, t1, t2, t3) 340 | set3Int(f1, f2, f3, u1, u2, u3) 341 | runMulModCase(t, t1, t3, t2, b, u1, u3, u2, f, "f1", "f3", "f2") 342 | 343 | // --- 3 --- 344 | set3Big(b1, b2, b3, t1, t2, t3) 345 | set3Int(f1, f2, f3, u1, u2, u3) 346 | runMulModCase(t, t2, t1, t3, b, u2, u1, u3, f, "f2", "f1", "f3") 347 | 348 | // --- 4 --- 349 | set3Big(b1, b2, b3, t1, t2, t3) 350 | set3Int(f1, f2, f3, u1, u2, u3) 351 | runMulModCase(t, t2, t3, t1, b, u2, u3, u1, f, "f2", "f3", "f1") 352 | 353 | // --- 5 --- 354 | set3Big(b1, b2, b3, t1, t2, t3) 355 | set3Int(f1, f2, f3, u1, u2, u3) 356 | runMulModCase(t, t3, t1, t2, b, u3, u1, u2, f, "f3", "f1", "f2") 357 | 358 | // --- 6 --- 359 | set3Big(b1, b2, b3, t1, t2, t3) 360 | set3Int(f1, f2, f3, u1, u2, u3) 361 | runMulModCase(t, t3, t2, t1, b, u3, u2, u1, f, "f3", "f2", "f1") 362 | } 363 | } 364 | 365 | func TestRandomMulDivOverflow(t *testing.T) { 366 | for i := 0; i < 10000; i++ { 367 | b1, f1 := randNums() 368 | b2, f2 := randNums() 369 | b3, f3 := randNums() 370 | 371 | f1a, f2a, f3a := f1.Clone(), f2.Clone(), f3.Clone() 372 | 373 | _, overflow := f1.MulDivOverflow(f1, f2, f3) 374 | if b3.BitLen() == 0 { 375 | b1.SetInt64(0) 376 | } else { 377 | b1.Div(b1.Mul(b1, b2), b3) 378 | } 379 | 380 | if err := checkOverflow(b1, f1, overflow); err != nil { 381 | t.Fatal(err) 382 | } 383 | if eq := checkEq(b1, f1); !eq { 384 | t.Fatalf("Expected equality:\nf1= %x\nf2= %x\nf3= %x\n[ - ]==\nf= %x\nb= %x\n", f1a, f2a, f3a, f1, b1) 385 | } 386 | } 387 | } 388 | 389 | func TestRandomMulDivOverflowRem(t *testing.T) { 390 | for i := 0; i < 10000; i++ { 391 | b1, f1 := randNums() 392 | b2, f2 := randNums() 393 | b3, f3 := randNums() 394 | 395 | f1a, f2a, f3a := f1.Clone(), f2.Clone(), f3.Clone() 396 | 397 | rem := new(Int) 398 | _, _, overflow := f1.MulDivOverflowRem(f1, f2, f3, rem) 399 | if b3.BitLen() == 0 { 400 | b1.SetInt64(0) 401 | } else { 402 | b1.Div(b1.Mul(b1, b2), b3) 403 | } 404 | 405 | if err := checkOverflow(b1, f1, overflow); err != nil { 406 | t.Fatal(err) 407 | } 408 | if eq := checkEq(b1, f1); !eq { 409 | t.Fatalf("Expected equality:\nf1= %x\nf2= %x\nf3= %x\n[ - ]==\nf= %x\nb= %x\n", f1a, f2a, f3a, f1, b1) 410 | } 411 | expRem := new(Int).MulMod(f1a, f2a, f3a) 412 | if !rem.Eq(expRem) { 413 | t.Fatalf("Expected remainder: %x, got %x", expRem, rem) 414 | } 415 | } 416 | } 417 | 418 | func TestRandomAbs(t *testing.T) { 419 | for i := 0; i < 10000; i++ { 420 | b, f1 := randHighNums() 421 | b2 := bigS256(big.NewInt(0).Set(b)) 422 | b2.Abs(b2) 423 | f1a := new(Int).Abs(f1) 424 | 425 | if eq := checkEq(b2, f1a); !eq { 426 | bf, _ := FromBig(b2) 427 | t.Fatalf("Expected equality:\nf1= %x\n[ abs ]==\nf = %x\nbf= %x\nb = %x\n", f1, f1a, bf, b2) 428 | } 429 | } 430 | } 431 | 432 | func TestUdivremQuick(t *testing.T) { 433 | var ( 434 | u = []uint64{1, 0, 0, 0, 0} 435 | expected = new(Int) 436 | rem Int 437 | ) 438 | udivrem([]uint64{}, u, &Int{0, 1, 0, 0}, &rem) 439 | copy(expected[:], u) 440 | if !rem.Eq(expected) { 441 | t.Errorf("Wrong remainder: %x, expected %x", rem, expected) 442 | } 443 | } 444 | 445 | func Test10KRandomSDiv(t *testing.T) { test10KRandom(t, "SDiv") } 446 | func Test10KRandomLsh(t *testing.T) { test10KRandom(t, "Lsh") } 447 | func Test10KRandomRsh(t *testing.T) { test10KRandom(t, "Rsh") } 448 | func Test10KRandomSRsh(t *testing.T) { test10KRandom(t, "SRsh") } 449 | func Test10KRandomExp(t *testing.T) { test10KRandom(t, "Exp") } 450 | 451 | func test10KRandom(t *testing.T, name string) { 452 | tc := lookupBinary(name) 453 | for i := 0; i < 10000; i++ { 454 | f1 := randNum() 455 | f2 := randNum() 456 | checkBinaryOperation(t, tc.name, tc.u256Fn, tc.bigFn, *f1, *f2) 457 | } 458 | } 459 | 460 | func TestSRsh(t *testing.T) { 461 | type testCase struct { 462 | arg string 463 | n uint64 464 | } 465 | testCases := []testCase{ 466 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 0}, 467 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 16}, 468 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 64}, 469 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 96}, 470 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 127}, 471 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 128}, 472 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 129}, 473 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 192}, 474 | {"0x8000000000000000000000000000000000000000000000000000000000000000", 254}, 475 | {"0x8000000000000000000000000000000000000000000000000000000000000000", 255}, 476 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 256}, 477 | {"0xFFFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 300}, 478 | {"0x7FFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 16}, 479 | {"0x7FFFEEEEDDDDCCCCBBBBAAAA9999888877776666555544443333222211110000", 256}, 480 | } 481 | op := lookupBinary("SRsh") 482 | for _, tc := range testCases { 483 | arg := MustFromHex(tc.arg) 484 | n := NewInt(tc.n) 485 | checkBinaryOperation(t, op.name, op.u256Fn, op.bigFn, *arg, *n) 486 | } 487 | } 488 | 489 | func TestByte(t *testing.T) { 490 | input, err := FromHex("0x102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f") 491 | if err != nil { 492 | t.Fatal(err) 493 | } 494 | for i := uint64(0); i < 35; i++ { 495 | var ( 496 | z = input.Clone() 497 | index = NewInt(i) 498 | have = z.Byte(index) 499 | want = NewInt(i) 500 | ) 501 | if i >= 32 { 502 | want.Clear() 503 | } 504 | if !have.Eq(want) { 505 | t.Fatalf("index %d: have %#x want %#x", i, have, want) 506 | } 507 | // Also check that we indeed modified the z 508 | if z != have { 509 | t.Fatalf("index %d: should return self %v %v", i, z, have) 510 | } 511 | } 512 | } 513 | 514 | func TestSignExtend(t *testing.T) { 515 | type testCase struct { 516 | arg string 517 | n uint64 518 | } 519 | testCases := []testCase{ 520 | {"10000000000000000", 2}, 521 | {"8080808080808080808080808080808080808080808080808080808080808080", 0}, 522 | {"8080808080808080808080808080808080808080808080808080808080808080", 1}, 523 | {"8080808080808080808080808080808080808080808080808080808080808080", 2}, 524 | {"8080808080808080808080808080808080808080808080808080808080808080", 3}, 525 | {"8080808080808080808080808080808080808080808080808080808080808080", 8}, 526 | {"8080808080808080808080808080808080808080808080808080808080808080", 18}, 527 | {"8080808080808080808080808080808080808080808080808080808080808080", 30}, 528 | {"8080808080808080808080808080808080808080808080808080808080808080", 31}, 529 | {"8080808080808080808080808080808080808080808080808080808080808080", 32}, 530 | {"4040404040404040404040404040404040404040404040404040404040404040", 0}, 531 | {"4040404040404040404040404040404040404040404040404040404040404040", 1}, 532 | {"4040404040404040404040404040404040404040404040404040404040404040", 15}, 533 | {"4040404040404040404040404040404040404040404040404040404040404040", 19}, 534 | {"4040404040404040404040404040404040404040404040404040404040404040", 30}, 535 | {"4040404040404040404040404040404040404040404040404040404040404040", 31}, 536 | {"4040404040404040404040404040404040404040404040404040404040404040", 32}, 537 | } 538 | op := lookupBinary("ExtendSign") 539 | for _, tc := range testCases { 540 | arg := new(Int).SetBytes(hex2Bytes(tc.arg)) 541 | n := new(Int).SetUint64(tc.n) 542 | checkBinaryOperation(t, op.name, op.u256Fn, op.bigFn, *arg, *n) 543 | } 544 | } 545 | 546 | func TestAddSubUint64(t *testing.T) { 547 | type testCase struct { 548 | arg string 549 | n uint64 550 | } 551 | testCases := []testCase{ 552 | {"0", 1}, 553 | {"1", 0}, 554 | {"1", 1}, 555 | {"1", 3}, 556 | {"0x10000000000000000", 1}, 557 | {"0x100000000000000000000000000000000", 1}, 558 | {"0", 0xffffffffffffffff}, 559 | {"1", 0xffffffff}, 560 | {"0xffffffffffffffff", 1}, 561 | {"0xffffffffffffffff", 0xffffffffffffffff}, 562 | {"0x10000000000000000", 1}, 563 | {"0xfffffffffffffffffffffffffffffffff", 1}, 564 | {"0xfffffffffffffffffffffffffffffffff", 2}, 565 | } 566 | 567 | for i := 0; i < len(testCases); i++ { 568 | tc := &testCases[i] 569 | bigArg, _ := new(big.Int).SetString(tc.arg, 0) 570 | arg, _ := FromBig(bigArg) 571 | { // SubUint64 572 | want, _ := FromBig(bigU256(new(big.Int).Sub(bigArg, new(big.Int).SetUint64(tc.n)))) 573 | have := new(Int).SetAllOne().SubUint64(arg, tc.n) 574 | if !have.Eq(want) { 575 | t.Logf("args: %s, %d\n", tc.arg, tc.n) 576 | t.Logf("want : %x\n", want) 577 | t.Logf("have : %x\n\n", have) 578 | t.Fail() 579 | } 580 | } 581 | { // ISubUint64 (in-place version) 582 | want, _ := FromBig(bigU256(new(big.Int).Sub(bigArg, new(big.Int).SetUint64(tc.n)))) 583 | have := new(Int).Set(arg) 584 | have.ISubUint64(tc.n) 585 | if !have.Eq(want) { 586 | t.Logf("ISubUint64 args: %s, %d\n", tc.arg, tc.n) 587 | t.Logf("want : %x\n", want) 588 | t.Logf("have : %x\n\n", have) 589 | t.Fail() 590 | } 591 | } 592 | { // AddUint64 593 | want, _ := FromBig(bigU256(new(big.Int).Add(bigArg, new(big.Int).SetUint64(tc.n)))) 594 | have := new(Int).AddUint64(arg, tc.n) 595 | if !have.Eq(want) { 596 | t.Logf("args: %s, %d\n", tc.arg, tc.n) 597 | t.Logf("want : %x\n", want) 598 | t.Logf("have : %x\n\n", have) 599 | t.Fail() 600 | } 601 | } 602 | { // IAddUint64 (in-place version) 603 | want, _ := FromBig(bigU256(new(big.Int).Add(bigArg, new(big.Int).SetUint64(tc.n)))) 604 | have := new(Int).Set(arg) 605 | have.IAddUint64(tc.n) 606 | if !have.Eq(want) { 607 | t.Logf("IAddUint64 args: %s, %d\n", tc.arg, tc.n) 608 | t.Logf("want : %x\n", want) 609 | t.Logf("have : %x\n\n", have) 610 | t.Fail() 611 | } 612 | } 613 | } 614 | } 615 | 616 | func TestSGT(t *testing.T) { 617 | 618 | x := new(Int).SetBytes(hex2Bytes("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")) 619 | y := new(Int).SetBytes(hex2Bytes("00")) 620 | actual := x.Sgt(y) 621 | if actual { 622 | t.Fatalf("Expected %v false", actual) 623 | } 624 | 625 | x = new(Int).SetBytes(hex2Bytes("00")) 626 | y = new(Int).SetBytes(hex2Bytes("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe")) 627 | actual = x.Sgt(y) 628 | if !actual { 629 | t.Fatalf("Expected %v true", actual) 630 | } 631 | } 632 | 633 | const ( 634 | // number of bits in a big.Word 635 | wordBits = 32 << (uint64(^big.Word(0)) >> 63) 636 | ) 637 | 638 | // TestFixedExpReusedArgs tests the cases in Exp() where the arguments (including result) alias the same objects. 639 | func TestFixedExpReusedArgs(t *testing.T) { 640 | f2 := Int{2, 0, 0, 0} 641 | f2.Exp(&f2, &f2) 642 | requireEq(t, big.NewInt(2*2), &f2, "") 643 | 644 | // TODO: This is tested in TestBinOp(). 645 | f3 := Int{3, 0, 0, 0} 646 | f4 := Int{4, 0, 0, 0} 647 | f3.Exp(&f4, &f3) 648 | requireEq(t, big.NewInt(4*4*4), &f3, "") 649 | 650 | // TODO: This is tested in TestBinOp(). 651 | f5 := Int{5, 0, 0, 0} 652 | f6 := Int{6, 0, 0, 0} 653 | f6.Exp(&f6, &f5) 654 | requireEq(t, big.NewInt(6*6*6*6*6), &f6, "") 655 | 656 | f3 = Int{3, 0, 0, 0} 657 | fr := new(Int).Exp(&f3, &f3) 658 | requireEq(t, big.NewInt(3*3*3), fr, "") 659 | } 660 | 661 | func TestPaddingRepresentation(t *testing.T) { 662 | a := big.NewInt(0xFF0AFcafe) 663 | aa := new(Int).SetUint64(0xFF0afcafe) 664 | bb := new(Int).SetBytes(a.Bytes()) 665 | if !aa.Eq(bb) { 666 | t.Fatal("aa != bb") 667 | } 668 | 669 | check := func(padded []byte, expectedHex string) { 670 | if expected := hex2Bytes(expectedHex); !bytes.Equal(padded, expected) { 671 | t.Errorf("incorrect padded bytes: %x, expected: %x", padded, expected) 672 | } 673 | } 674 | 675 | check(aa.PaddedBytes(32), "0000000000000000000000000000000000000000000000000000000ff0afcafe") 676 | check(aa.PaddedBytes(20), "0000000000000000000000000000000ff0afcafe") 677 | check(aa.PaddedBytes(40), "00000000000000000000000000000000000000000000000000000000000000000000000ff0afcafe") 678 | 679 | bytearr := hex2Bytes("0e320219838e859b2f9f18b72e3d4073ca50b37d") 680 | a = new(big.Int).SetBytes(bytearr) 681 | aa = new(Int).SetBytes(bytearr) 682 | bb = new(Int).SetBytes(a.Bytes()) 683 | if !aa.Eq(bb) { 684 | t.Fatal("aa != bb") 685 | } 686 | 687 | check(aa.PaddedBytes(32), "0000000000000000000000000e320219838e859b2f9f18b72e3d4073ca50b37d") 688 | check(aa.PaddedBytes(20), "0e320219838e859b2f9f18b72e3d4073ca50b37d") 689 | check(aa.PaddedBytes(40), "00000000000000000000000000000000000000000e320219838e859b2f9f18b72e3d4073ca50b37d") 690 | } 691 | 692 | func TestWriteToSlice(t *testing.T) { 693 | x1 := hex2Bytes("fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611") 694 | 695 | a := big.NewInt(0).SetBytes(x1) 696 | fa, _ := FromBig(a) 697 | 698 | dest := make([]byte, 32) 699 | fa.WriteToSlice(dest) 700 | if !bytes.Equal(dest, x1) { 701 | t.Errorf("got %x, expected %x", dest, x1) 702 | } 703 | 704 | fb := new(Int) 705 | exp := make([]byte, 32) 706 | fb.WriteToSlice(dest) 707 | if !bytes.Equal(dest, exp) { 708 | t.Errorf("got %x, expected %x", dest, exp) 709 | } 710 | // a too small buffer 711 | // Should fill the lower parts, masking upper bytes 712 | exp = hex2Bytes("683fd1e870eec79504c60144cc7f5fc2bad1e611") 713 | dest = make([]byte, 20) 714 | fa.WriteToSlice(dest) 715 | if !bytes.Equal(dest, exp) { 716 | t.Errorf("got %x, expected %x", dest, exp) 717 | } 718 | 719 | // a too large buffer, already filled with stuff 720 | // Should fill the leftmost 32 bytes, not touch the other things 721 | dest = hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") 722 | exp = hex2Bytes("fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611ffffffffffffffff") 723 | 724 | fa.WriteToSlice(dest) 725 | if !bytes.Equal(dest, exp) { 726 | t.Errorf("got %x, expected %x", dest, x1) 727 | } 728 | 729 | // an empty slice, no panics please 730 | dest = []byte{} 731 | exp = []byte{} 732 | 733 | fa.WriteToSlice(dest) 734 | if !bytes.Equal(dest, exp) { 735 | t.Errorf("got %x, expected %x", dest, x1) 736 | } 737 | 738 | } 739 | 740 | func TestInt_WriteToArray(t *testing.T) { 741 | x1 := hex2Bytes("0102030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611") 742 | a := big.NewInt(0).SetBytes(x1) 743 | fa, _ := FromBig(a) 744 | 745 | { 746 | dest := [20]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 747 | fa.WriteToArray20(&dest) 748 | exp := hex2Bytes("0d0ed1e870eec79504c60144cc7f5fc2bad1e611") 749 | if !bytes.Equal(dest[:], exp) { 750 | t.Errorf("got %x, expected %x", dest, exp) 751 | } 752 | } 753 | { 754 | dest := [32]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 755 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 756 | fa.WriteToArray32(&dest) 757 | exp := hex2Bytes("0102030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611") 758 | if !bytes.Equal(dest[:], exp) { 759 | t.Errorf("got %x, expected %x", dest, exp) 760 | } 761 | } 762 | { // A 36-byte slice: the first 32 bytes are overwritten 763 | dest := []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 764 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 765 | fa.PutUint256(dest) 766 | exp := hex2Bytes("0102030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611ffffffff") 767 | if !bytes.Equal(dest[:], exp) { 768 | t.Errorf("got %x, expected %x", dest, exp) 769 | } 770 | } 771 | } 772 | 773 | type gethAddress [20]byte 774 | 775 | // SetBytes sets the address to the value of b. 776 | // If b is larger than len(a) it will panic. 777 | func (a *gethAddress) setBytes(b []byte) { 778 | if len(b) > len(a) { 779 | b = b[len(b)-20:] 780 | } 781 | copy(a[20-len(b):], b) 782 | } 783 | 784 | // BytesToAddress returns Address with value b. 785 | // If b is larger than len(h), b will be cropped from the left. 786 | func bytesToAddress(b []byte) gethAddress { 787 | var a gethAddress 788 | a.setBytes(b) 789 | return a 790 | } 791 | 792 | type gethHash [32]byte 793 | 794 | // SetBytes sets the address to the value of b. 795 | // If b is larger than len(a) it will panic. 796 | func (a *gethHash) setBytes(b []byte) { 797 | if len(b) > len(a) { 798 | b = b[len(b)-32:] 799 | } 800 | copy(a[32-len(b):], b) 801 | } 802 | 803 | // BytesToHash returns gethHash with value b. 804 | // If b is larger than len(h), b will be cropped from the left. 805 | func bytesToHash(b []byte) gethHash { 806 | var a gethHash 807 | a.setBytes(b) 808 | return a 809 | } 810 | 811 | func TestByteRepresentation(t *testing.T) { 812 | for i, tt := range []string{ 813 | "1337fafafa0e320219838e859b2f9f18b72e3d4073ca50b37d", 814 | "fafafa0e320219838e859b2f9f18b72e3d4073ca50b37d", 815 | "0e320219838e859b2f9f18b72e3d4073ca50b37d", 816 | "320219838e859b2f9f18b72e3d4073ca50b37d", 817 | "838e859b2f9f18b72e3d4073ca50b37d", 818 | "38e859b2f9f18b72e3d4073ca50b37d", 819 | "f18b72e3d4073ca50b37d", 820 | "b37d", 821 | "01", 822 | "", 823 | "00", 824 | } { 825 | bytearr := hex2Bytes(tt) 826 | // big.Int -> address, hash 827 | a := big.NewInt(0).SetBytes(bytearr) 828 | want20 := bytesToAddress(a.Bytes()) 829 | want32 := bytesToHash(a.Bytes()) 830 | 831 | // uint256.Int -> address 832 | b := new(Int).SetBytes(bytearr) 833 | have20 := gethAddress(b.Bytes20()) 834 | have32 := gethHash(b.Bytes32()) 835 | 836 | if have, want := want20, have20; have != want { 837 | t.Errorf("test %d: have %x want %x", i, have, want) 838 | } 839 | if have, want := want32, have32; have != want { 840 | t.Errorf("test %d: have %x want %x", i, have, want) 841 | } 842 | } 843 | } 844 | 845 | func testLog10(t *testing.T, z *Int) { 846 | want := uint(len(z.Dec())) 847 | if want > 0 { 848 | want-- 849 | } 850 | if have := z.Log10(); have != want { 851 | t.Errorf("%s (%s): have %v want %v", z.Hex(), z.Dec(), have, want) 852 | } 853 | } 854 | 855 | func TestLog10(t *testing.T) { 856 | testLog10(t, new(Int)) 857 | for i := uint(0); i < 255; i++ { 858 | z := NewInt(1) 859 | testLog10(t, z.Lsh(z, i)) 860 | if i != 0 { 861 | testLog10(t, new(Int).SubUint64(z, 1)) 862 | } 863 | } 864 | z := NewInt(1) 865 | ten := NewInt(10) 866 | for i := uint(0); i < 80; i++ { 867 | testLog10(t, z.Mul(z, ten)) 868 | testLog10(t, new(Int).SubUint64(z, 1)) 869 | } 870 | } 871 | 872 | func FuzzLog10(f *testing.F) { 873 | f.Fuzz(func(t *testing.T, aa, bb, cc, dd uint64) { 874 | testLog10(t, &Int{aa, bb, cc, dd}) 875 | }) 876 | } 877 | 878 | func BenchmarkLog10(b *testing.B) { 879 | var u256Ints []*Int 880 | var bigints []*big.Int 881 | 882 | for i := uint(0); i < 255; i++ { 883 | a := NewInt(1) 884 | a.Lsh(a, i) 885 | u256Ints = append(u256Ints, a) 886 | bigints = append(bigints, a.ToBig()) 887 | } 888 | b.Run("Log10/uint256", func(b *testing.B) { 889 | b.ReportAllocs() 890 | for i := 0; i < b.N; i++ { 891 | for _, z := range u256Ints { 892 | _ = z.Log10() 893 | } 894 | } 895 | }) 896 | b.Run("Log10/big", func(b *testing.B) { 897 | b.ReportAllocs() 898 | for i := 0; i < b.N; i++ { 899 | for _, z := range bigints { 900 | f, _ := new(big.Float).SetInt(z).Float64() 901 | _ = int(math.Log10(f)) 902 | } 903 | } 904 | }) 905 | } 906 | 907 | func TestCmpUint64(t *testing.T) { 908 | check := func(z *Int, x uint64) { 909 | want := z.ToBig().Cmp(new(big.Int).SetUint64(x)) 910 | have := z.CmpUint64(x) 911 | if have != want { 912 | t.Errorf("%s.CmpUint64( %x ) : have %v want %v", z.Hex(), x, have, want) 913 | } 914 | } 915 | for i := uint(0); i < 255; i++ { 916 | z := NewInt(1) 917 | z.Lsh(z, i) 918 | check(z, new(Int).Set(z).Uint64()) // z, z 919 | check(z, new(Int).AddUint64(z, 1).Uint64()) // z, z + 1 920 | check(z, new(Int).SubUint64(z, 1).Uint64()) // z, z - 1 921 | check(z, new(big.Int).Rsh(new(Int).Set(z).ToBig(), 64).Uint64()) // z, z >> 64 922 | } 923 | } 924 | 925 | func TestCmpBig(t *testing.T) { 926 | check := func(z *Int, x *big.Int) { 927 | want := z.ToBig().Cmp(x) 928 | have := z.CmpBig(x) 929 | if have != want { 930 | t.Errorf("%s.CmpBig( %x ) : have %v want %v", z.Hex(), x, have, want) 931 | } 932 | } 933 | for i := uint(0); i < 255; i++ { 934 | z := NewInt(1) 935 | z.Lsh(z, i) 936 | check(z, new(Int).Set(z).ToBig()) // z, z 937 | check(z, new(Int).AddUint64(z, 1).ToBig()) // z, z + 1 938 | check(z, new(Int).SubUint64(z, 1).ToBig()) // z, z - 1 939 | check(z, new(big.Int).Neg(new(Int).Set(z).ToBig())) // z, -z 940 | check(z, new(big.Int).Lsh(new(Int).Set(z).ToBig(), 256)) // z, z << 256 941 | } 942 | } 943 | -------------------------------------------------------------------------------- /benchmarks_test.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | package uint256 6 | 7 | import ( 8 | "math/big" 9 | "math/rand" 10 | "testing" 11 | ) 12 | 13 | const numSamples = 1024 14 | 15 | var ( 16 | int32Samples [numSamples]Int 17 | int32SamplesLt [numSamples]Int 18 | int64Samples [numSamples]Int 19 | int64SamplesLt [numSamples]Int 20 | int128Samples [numSamples]Int 21 | int128SamplesLt [numSamples]Int 22 | int192Samples [numSamples]Int 23 | int192SamplesLt [numSamples]Int 24 | int256Samples [numSamples]Int 25 | int256SamplesLt [numSamples]Int // int256SamplesLt[i] <= int256Samples[i] 26 | 27 | big32Samples [numSamples]big.Int 28 | big32SamplesLt [numSamples]big.Int 29 | big64Samples [numSamples]big.Int 30 | big64SamplesLt [numSamples]big.Int 31 | big128Samples [numSamples]big.Int 32 | big128SamplesLt [numSamples]big.Int 33 | big192Samples [numSamples]big.Int 34 | big192SamplesLt [numSamples]big.Int 35 | big256Samples [numSamples]big.Int 36 | big256SamplesLt [numSamples]big.Int // big256SamplesLt[i] <= big256Samples[i] 37 | 38 | _ = initSamples() 39 | ) 40 | 41 | func initSamples() bool { 42 | rnd := rand.New(rand.NewSource(0)) // #nosec G404 43 | 44 | // newRandInt creates new Int with so many highly likely non-zero random words. 45 | newRandInt := func(numWords int) Int { 46 | var z Int 47 | for i := 0; i < numWords; i++ { 48 | z[i] = rnd.Uint64() 49 | } 50 | return z 51 | } 52 | 53 | for i := 0; i < numSamples; i++ { 54 | x32g := rnd.Uint32() 55 | x32l := rnd.Uint32() 56 | if x32g < x32l { 57 | x32g, x32l = x32l, x32g 58 | } 59 | int32Samples[i].SetUint64(uint64(x32g)) 60 | big32Samples[i] = *int32Samples[i].ToBig() 61 | int32SamplesLt[i].SetUint64(uint64(x32l)) 62 | big32SamplesLt[i] = *int32SamplesLt[i].ToBig() 63 | 64 | l := newRandInt(1) 65 | g := newRandInt(1) 66 | if g.Lt(&l) { 67 | g, l = l, g 68 | } 69 | if g[0] == 0 { 70 | g[0]++ 71 | } 72 | int64Samples[i] = g 73 | big64Samples[i] = *int64Samples[i].ToBig() 74 | int64SamplesLt[i] = l 75 | big64SamplesLt[i] = *int64SamplesLt[i].ToBig() 76 | 77 | l = newRandInt(2) 78 | g = newRandInt(2) 79 | if g.Lt(&l) { 80 | g, l = l, g 81 | } 82 | if g[1] == 0 { 83 | g[1]++ 84 | } 85 | int128Samples[i] = g 86 | big128Samples[i] = *int128Samples[i].ToBig() 87 | int128SamplesLt[i] = l 88 | big128SamplesLt[i] = *int128SamplesLt[i].ToBig() 89 | 90 | l = newRandInt(3) 91 | g = newRandInt(3) 92 | if g.Lt(&l) { 93 | g, l = l, g 94 | } 95 | if g[2] == 0 { 96 | g[2]++ 97 | } 98 | int192Samples[i] = g 99 | big192Samples[i] = *int192Samples[i].ToBig() 100 | int192SamplesLt[i] = l 101 | big192SamplesLt[i] = *int192SamplesLt[i].ToBig() 102 | 103 | l = newRandInt(4) 104 | g = newRandInt(4) 105 | if g.Lt(&l) { 106 | g, l = l, g 107 | } 108 | if g[3] == 0 { 109 | g[3]++ 110 | } 111 | int256Samples[i] = g 112 | big256Samples[i] = *int256Samples[i].ToBig() 113 | int256SamplesLt[i] = l 114 | big256SamplesLt[i] = *int256SamplesLt[i].ToBig() 115 | } 116 | 117 | return true 118 | } 119 | 120 | func benchmark_Add_Bit(bench *testing.B) { 121 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 122 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 123 | f, _ := FromBig(b1) 124 | f2, _ := FromBig(b2) 125 | bench.ResetTimer() 126 | for i := 0; i < bench.N; i++ { 127 | f.Add(f, f2) 128 | } 129 | } 130 | func benchmark_Add_Big(bench *testing.B) { 131 | b := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 132 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 133 | bench.ResetTimer() 134 | for i := 0; i < bench.N; i++ { 135 | b.Add(b, b2) 136 | } 137 | } 138 | func BenchmarkAdd(bench *testing.B) { 139 | bench.Run("single/big", benchmark_Add_Big) 140 | bench.Run("single/uint256", benchmark_Add_Bit) 141 | } 142 | 143 | func benchmark_SubOverflow_Bit(bench *testing.B) { 144 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 145 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 146 | f, _ := FromBig(b1) 147 | f2, _ := FromBig(b2) 148 | 149 | bench.ResetTimer() 150 | for i := 0; i < bench.N; i++ { 151 | f.SubOverflow(f, f2) 152 | } 153 | } 154 | func benchmark_Sub_Bit(bench *testing.B) { 155 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 156 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 157 | f, _ := FromBig(b1) 158 | f2, _ := FromBig(b2) 159 | 160 | bench.ResetTimer() 161 | for i := 0; i < bench.N; i++ { 162 | f.Sub(f, f2) 163 | } 164 | } 165 | 166 | func benchmark_Sub_Big(bench *testing.B) { 167 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 168 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 169 | 170 | bench.ResetTimer() 171 | for i := 0; i < bench.N; i++ { 172 | b1.Sub(b1, b2) 173 | } 174 | } 175 | func BenchmarkSub(bench *testing.B) { 176 | bench.Run("single/big", benchmark_Sub_Big) 177 | bench.Run("single/uint256", benchmark_Sub_Bit) 178 | bench.Run("single/uint256_of", benchmark_SubOverflow_Bit) 179 | } 180 | 181 | func BenchmarkMul(bench *testing.B) { 182 | benchmarkUint256 := func(bench *testing.B) { 183 | a := big.NewInt(0).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 184 | b := big.NewInt(0).SetBytes(hex2Bytes("f123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 185 | fa, _ := FromBig(a) 186 | fb, _ := FromBig(b) 187 | 188 | result := new(Int) 189 | bench.ResetTimer() 190 | for i := 0; i < bench.N; i++ { 191 | result.Mul(fa, fb) 192 | } 193 | } 194 | benchmarkBig := func(bench *testing.B) { 195 | a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 196 | b := new(big.Int).SetBytes(hex2Bytes("f123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 197 | 198 | result := new(big.Int) 199 | bench.ResetTimer() 200 | for i := 0; i < bench.N; i++ { 201 | bigU256(result.Mul(a, b)) 202 | } 203 | } 204 | 205 | bench.Run("single/uint256", benchmarkUint256) 206 | bench.Run("single/big", benchmarkBig) 207 | } 208 | 209 | func BenchmarkMulOverflow(bench *testing.B) { 210 | benchmarkUint256 := func(bench *testing.B) { 211 | a := big.NewInt(0).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 212 | b := big.NewInt(0).SetBytes(hex2Bytes("f123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 213 | fa, _ := FromBig(a) 214 | fb, _ := FromBig(b) 215 | 216 | result := new(Int) 217 | bench.ResetTimer() 218 | for i := 0; i < bench.N; i++ { 219 | result.MulOverflow(fa, fb) 220 | } 221 | } 222 | benchmarkBig := func(bench *testing.B) { 223 | a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 224 | b := new(big.Int).SetBytes(hex2Bytes("f123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 225 | 226 | result := new(big.Int) 227 | bench.ResetTimer() 228 | for i := 0; i < bench.N; i++ { 229 | bigU256(result.Mul(a, b)) 230 | } 231 | } 232 | 233 | bench.Run("single/uint256", benchmarkUint256) 234 | bench.Run("single/big", benchmarkBig) 235 | } 236 | 237 | func BenchmarkSquare(bench *testing.B) { 238 | 239 | benchmarkUint256 := func(bench *testing.B) { 240 | a := new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 241 | 242 | result := new(Int) 243 | bench.ResetTimer() 244 | for i := 0; i < bench.N; i++ { 245 | result.Set(a).squared() 246 | } 247 | } 248 | benchmarkBig := func(bench *testing.B) { 249 | a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 250 | 251 | result := new(big.Int) 252 | bench.ResetTimer() 253 | for i := 0; i < bench.N; i++ { 254 | bigU256(result.Mul(a, a)) 255 | } 256 | } 257 | 258 | bench.Run("single/uint256", benchmarkUint256) 259 | bench.Run("single/big", benchmarkBig) 260 | } 261 | 262 | func BenchmarkSqrt(bench *testing.B) { 263 | benchmarkUint256 := func(bench *testing.B) { 264 | bench.ReportAllocs() 265 | a := new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 266 | 267 | result := new(Int) 268 | bench.ResetTimer() 269 | for i := 0; i < bench.N; i++ { 270 | result.Sqrt(a) 271 | } 272 | } 273 | benchmarkBig := func(bench *testing.B) { 274 | bench.ReportAllocs() 275 | a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 276 | 277 | result := new(big.Int) 278 | bench.ResetTimer() 279 | for i := 0; i < bench.N; i++ { 280 | result.Sqrt(a) 281 | } 282 | } 283 | bench.Run("single/uint256", benchmarkUint256) 284 | bench.Run("single/big", benchmarkBig) 285 | } 286 | 287 | func benchmark_And_Big(bench *testing.B) { 288 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 289 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 290 | bench.ResetTimer() 291 | for i := 0; i < bench.N; i++ { 292 | b1.And(b1, b2) 293 | } 294 | } 295 | func benchmark_And_Bit(bench *testing.B) { 296 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 297 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 298 | f, _ := FromBig(b1) 299 | f2, _ := FromBig(b2) 300 | bench.ResetTimer() 301 | for i := 0; i < bench.N; i++ { 302 | f.And(f, f2) 303 | } 304 | } 305 | func BenchmarkAnd(bench *testing.B) { 306 | bench.Run("single/big", benchmark_And_Big) 307 | bench.Run("single/uint256", benchmark_And_Bit) 308 | } 309 | 310 | func benchmark_Or_Big(bench *testing.B) { 311 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 312 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 313 | bench.ResetTimer() 314 | for i := 0; i < bench.N; i++ { 315 | b1.Or(b1, b2) 316 | } 317 | } 318 | func benchmark_Or_Bit(bench *testing.B) { 319 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 320 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 321 | f, _ := FromBig(b1) 322 | f2, _ := FromBig(b2) 323 | bench.ResetTimer() 324 | for i := 0; i < bench.N; i++ { 325 | f.Or(f, f2) 326 | } 327 | } 328 | func BenchmarkOr(bench *testing.B) { 329 | bench.Run("single/big", benchmark_Or_Big) 330 | bench.Run("single/uint256", benchmark_Or_Bit) 331 | } 332 | 333 | func benchmark_Xor_Big(bench *testing.B) { 334 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 335 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 336 | bench.ResetTimer() 337 | for i := 0; i < bench.N; i++ { 338 | b1.Xor(b1, b2) 339 | } 340 | } 341 | func benchmark_Xor_Bit(bench *testing.B) { 342 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 343 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 344 | f, _ := FromBig(b1) 345 | f2, _ := FromBig(b2) 346 | bench.ResetTimer() 347 | for i := 0; i < bench.N; i++ { 348 | f.Xor(f, f2) 349 | } 350 | } 351 | 352 | func BenchmarkXor(bench *testing.B) { 353 | bench.Run("single/big", benchmark_Xor_Big) 354 | bench.Run("single/uint256", benchmark_Xor_Bit) 355 | } 356 | 357 | func benchmark_Cmp_Big(bench *testing.B) { 358 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 359 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 360 | bench.ResetTimer() 361 | for i := 0; i < bench.N; i++ { 362 | b1.Cmp(b2) 363 | b2.Cmp(b1) 364 | } 365 | } 366 | func benchmark_Cmp_Bit(bench *testing.B) { 367 | b1 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 368 | b2 := big.NewInt(0).SetBytes(hex2Bytes("0123456789abcdefaaaaaa9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 369 | f, _ := FromBig(b1) 370 | f2, _ := FromBig(b2) 371 | 372 | bench.ResetTimer() 373 | for i := 0; i < bench.N; i++ { 374 | f.Cmp(f2) 375 | f2.Cmp(f) 376 | } 377 | } 378 | 379 | func BenchmarkCmp(bench *testing.B) { 380 | bench.Run("single/big", benchmark_Cmp_Big) 381 | bench.Run("single/uint256", benchmark_Cmp_Bit) 382 | } 383 | 384 | func BenchmarkCmpBig(bench *testing.B) { 385 | // This bench tests where the Cmp is non-equal 386 | bench.Run("nonequal", func(b *testing.B) { 387 | b.ReportAllocs() 388 | for i := 0; i < b.N; i++ { 389 | x := &big256Samples[i%len(big256Samples)] 390 | z := &int256Samples[len(int256Samples)-(i%len(int256Samples))-1] 391 | _ = z.CmpBig(x) 392 | } 393 | }) 394 | bench.Run("equal", func(b *testing.B) { 395 | b.ReportAllocs() 396 | for i := 0; i < b.N; i++ { 397 | x := &big256Samples[i%len(big256Samples)] 398 | z := &int256Samples[i%len(big256Samples)] 399 | if z.CmpBig(x) != 0 { 400 | b.Fatal("test error") 401 | } 402 | } 403 | }) 404 | } 405 | 406 | func BenchmarkLt(b *testing.B) { 407 | benchmarkUint256 := func(b *testing.B, samples *[numSamples]Int) (flag bool) { 408 | var x Int 409 | for j := 0; j < b.N; j += numSamples { 410 | for i := 0; i < numSamples; i++ { 411 | y := samples[i] 412 | flag = x.Lt(&y) 413 | x = y 414 | } 415 | } 416 | return 417 | } 418 | benchmarkBig := func(b *testing.B, samples *[numSamples]big.Int) (flag bool) { 419 | var x big.Int 420 | for j := 0; j < b.N; j += numSamples { 421 | for i := 0; i < numSamples; i++ { 422 | y := samples[i] 423 | flag = x.Cmp(&y) < 0 424 | x = y 425 | } 426 | } 427 | return 428 | } 429 | 430 | b.Run("large/uint256", func(b *testing.B) { benchmarkUint256(b, &int256Samples) }) 431 | b.Run("large/big", func(b *testing.B) { benchmarkBig(b, &big256Samples) }) 432 | b.Run("small/uint256", func(b *testing.B) { benchmarkUint256(b, &int64Samples) }) 433 | b.Run("small/big", func(b *testing.B) { benchmarkBig(b, &big64Samples) }) 434 | } 435 | 436 | func BenchmarkEq(b *testing.B) { 437 | benchmarkUint256 := func(b *testing.B, samples *[numSamples]Int) (flag bool) { 438 | var x Int 439 | for j := 0; j < b.N; j += numSamples { 440 | for i := 0; i < numSamples; i++ { 441 | y := samples[i] 442 | flag = x.Eq(&y) 443 | x = y 444 | } 445 | } 446 | return 447 | } 448 | benchmarkBig := func(b *testing.B, samples *[numSamples]big.Int) (flag bool) { 449 | var x big.Int 450 | for j := 0; j < b.N; j += numSamples { 451 | for i := 0; i < numSamples; i++ { 452 | y := samples[i] 453 | flag = x.Cmp(&y) == 0 454 | x = y 455 | } 456 | } 457 | return 458 | } 459 | 460 | b.Run("large/uint256", func(b *testing.B) { benchmarkUint256(b, &int256Samples) }) 461 | b.Run("large/big", func(b *testing.B) { benchmarkBig(b, &big256Samples) }) 462 | b.Run("small/uint256", func(b *testing.B) { benchmarkUint256(b, &int64Samples) }) 463 | b.Run("small/big", func(b *testing.B) { benchmarkBig(b, &big64Samples) }) 464 | } 465 | 466 | func benchmark_Lsh_Big(n uint, bench *testing.B) { 467 | original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) 468 | bench.ResetTimer() 469 | for i := 0; i < bench.N; i++ { 470 | b1 := big.NewInt(0) 471 | b1.Lsh(original, n) 472 | } 473 | } 474 | func benchmark_Lsh_Big_N_EQ_0(bench *testing.B) { 475 | benchmark_Lsh_Big(0, bench) 476 | } 477 | func benchmark_Lsh_Big_N_GT_192(bench *testing.B) { 478 | benchmark_Lsh_Big(193, bench) 479 | } 480 | func benchmark_Lsh_Big_N_GT_128(bench *testing.B) { 481 | benchmark_Lsh_Big(129, bench) 482 | } 483 | func benchmark_Lsh_Big_N_GT_64(bench *testing.B) { 484 | benchmark_Lsh_Big(65, bench) 485 | } 486 | func benchmark_Lsh_Big_N_GT_0(bench *testing.B) { 487 | benchmark_Lsh_Big(1, bench) 488 | } 489 | func benchmark_Lsh_Bit(n uint, bench *testing.B) { 490 | original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) 491 | f2, _ := FromBig(original) 492 | bench.ResetTimer() 493 | for i := 0; i < bench.N; i++ { 494 | f1 := new(Int) 495 | f1.Lsh(f2, n) 496 | } 497 | } 498 | func benchmark_Lsh_Bit_N_EQ_0(bench *testing.B) { 499 | benchmark_Lsh_Bit(0, bench) 500 | } 501 | func benchmark_Lsh_Bit_N_GT_192(bench *testing.B) { 502 | benchmark_Lsh_Bit(193, bench) 503 | } 504 | func benchmark_Lsh_Bit_N_GT_128(bench *testing.B) { 505 | benchmark_Lsh_Bit(129, bench) 506 | } 507 | func benchmark_Lsh_Bit_N_GT_64(bench *testing.B) { 508 | benchmark_Lsh_Bit(65, bench) 509 | } 510 | func benchmark_Lsh_Bit_N_GT_0(bench *testing.B) { 511 | benchmark_Lsh_Bit(1, bench) 512 | } 513 | func BenchmarkLsh(bench *testing.B) { 514 | bench.Run("n_eq_0/big", benchmark_Lsh_Big_N_EQ_0) 515 | bench.Run("n_gt_192/big", benchmark_Lsh_Big_N_GT_192) 516 | bench.Run("n_gt_128/big", benchmark_Lsh_Big_N_GT_128) 517 | bench.Run("n_gt_64/big", benchmark_Lsh_Big_N_GT_64) 518 | bench.Run("n_gt_0/big", benchmark_Lsh_Big_N_GT_0) 519 | 520 | bench.Run("n_eq_0/uint256", benchmark_Lsh_Bit_N_EQ_0) 521 | bench.Run("n_gt_192/uint256", benchmark_Lsh_Bit_N_GT_192) 522 | bench.Run("n_gt_128/uint256", benchmark_Lsh_Bit_N_GT_128) 523 | bench.Run("n_gt_64/uint256", benchmark_Lsh_Bit_N_GT_64) 524 | bench.Run("n_gt_0/uint256", benchmark_Lsh_Bit_N_GT_0) 525 | } 526 | 527 | func benchmark_Rsh_Big(n uint, bench *testing.B) { 528 | original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) 529 | bench.ResetTimer() 530 | for i := 0; i < bench.N; i++ { 531 | b1 := big.NewInt(0) 532 | b1.Rsh(original, n) 533 | } 534 | } 535 | func benchmark_Rsh_Big_N_EQ_0(bench *testing.B) { 536 | benchmark_Rsh_Big(0, bench) 537 | } 538 | func benchmark_Rsh_Big_N_GT_192(bench *testing.B) { 539 | benchmark_Rsh_Big(193, bench) 540 | } 541 | func benchmark_Rsh_Big_N_GT_128(bench *testing.B) { 542 | benchmark_Rsh_Big(129, bench) 543 | } 544 | func benchmark_Rsh_Big_N_GT_64(bench *testing.B) { 545 | benchmark_Rsh_Big(65, bench) 546 | } 547 | func benchmark_Rsh_Big_N_GT_0(bench *testing.B) { 548 | benchmark_Rsh_Big(1, bench) 549 | } 550 | func benchmark_Rsh_Bit(n uint, bench *testing.B) { 551 | original := big.NewInt(0).SetBytes(hex2Bytes("FBCDEF090807060504030201ffffffffFBCDEF090807060504030201ffffffff")) 552 | f2, _ := FromBig(original) 553 | bench.ResetTimer() 554 | for i := 0; i < bench.N; i++ { 555 | f1 := new(Int) 556 | f1.Rsh(f2, n) 557 | } 558 | } 559 | func benchmark_Rsh_Bit_N_EQ_0(bench *testing.B) { 560 | benchmark_Rsh_Bit(0, bench) 561 | } 562 | func benchmark_Rsh_Bit_N_GT_192(bench *testing.B) { 563 | benchmark_Rsh_Bit(193, bench) 564 | } 565 | func benchmark_Rsh_Bit_N_GT_128(bench *testing.B) { 566 | benchmark_Rsh_Bit(129, bench) 567 | } 568 | func benchmark_Rsh_Bit_N_GT_64(bench *testing.B) { 569 | benchmark_Rsh_Bit(65, bench) 570 | } 571 | func benchmark_Rsh_Bit_N_GT_0(bench *testing.B) { 572 | benchmark_Rsh_Bit(1, bench) 573 | } 574 | func BenchmarkRsh(bench *testing.B) { 575 | bench.Run("n_eq_0/big", benchmark_Rsh_Big_N_EQ_0) 576 | bench.Run("n_gt_192/big", benchmark_Rsh_Big_N_GT_192) 577 | bench.Run("n_gt_128/big", benchmark_Rsh_Big_N_GT_128) 578 | bench.Run("n_gt_64/big", benchmark_Rsh_Big_N_GT_64) 579 | bench.Run("n_gt_0/big", benchmark_Rsh_Big_N_GT_0) 580 | 581 | bench.Run("n_eq_0/uint256", benchmark_Rsh_Bit_N_EQ_0) 582 | bench.Run("n_gt_192/uint256", benchmark_Rsh_Bit_N_GT_192) 583 | bench.Run("n_gt_128/uint256", benchmark_Rsh_Bit_N_GT_128) 584 | bench.Run("n_gt_64/uint256", benchmark_Rsh_Bit_N_GT_64) 585 | bench.Run("n_gt_0/uint256", benchmark_Rsh_Bit_N_GT_0) 586 | } 587 | 588 | // bigExp implements exponentiation by squaring. 589 | // The result is truncated to 256 bits. 590 | func bigExp(result, base, exponent *big.Int) *big.Int { 591 | result.SetUint64(1) 592 | 593 | for _, word := range exponent.Bits() { 594 | for i := 0; i < wordBits; i++ { 595 | if word&1 == 1 { 596 | bigU256(result.Mul(result, base)) 597 | } 598 | bigU256(base.Mul(base, base)) 599 | word >>= 1 600 | } 601 | } 602 | return result 603 | } 604 | 605 | func benchmark_Exp_Big(bench *testing.B, x, y string) { 606 | orig := big.NewInt(0).SetBytes(hex2Bytes(x)) 607 | base := big.NewInt(0).SetBytes(hex2Bytes(x)) 608 | exp := big.NewInt(0).SetBytes(hex2Bytes(y)) 609 | 610 | result := new(big.Int) 611 | bench.ResetTimer() 612 | for i := 0; i < bench.N; i++ { 613 | bigExp(result, base, exp) 614 | base.Set(orig) 615 | } 616 | } 617 | 618 | func benchmark_Exp_U256(bench *testing.B, x, y string) { 619 | var ( 620 | base = big.NewInt(0).SetBytes(hex2Bytes(x)) 621 | exp = big.NewInt(0).SetBytes(hex2Bytes(y)) 622 | 623 | f_base, _ = FromBig(base) 624 | f_orig, _ = FromBig(base) 625 | f_exp, _ = FromBig(exp) 626 | f_res Int 627 | ) 628 | bench.ResetTimer() 629 | for i := 0; i < bench.N; i++ { 630 | f_res.Exp(f_base, f_exp) 631 | f_base.Set(f_orig) 632 | } 633 | } 634 | 635 | func BenchmarkExp(bench *testing.B) { 636 | { // Large values 637 | base := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" 638 | exp := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" 639 | bench.Run("large/big", func(b *testing.B) { 640 | benchmark_Exp_Big(b, base, exp) 641 | }) 642 | bench.Run("large/uint256", func(b *testing.B) { 643 | benchmark_Exp_U256(b, base, exp) 644 | }) 645 | } 646 | { // Smaller exponent 647 | base := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" 648 | exp := "8abcdef" 649 | bench.Run("small/big", func(b *testing.B) { 650 | benchmark_Exp_Big(b, base, exp) 651 | }) 652 | bench.Run("small/uint256", func(b *testing.B) { 653 | benchmark_Exp_U256(b, base, exp) 654 | }) 655 | } 656 | { // Even base (and very small exponent) 657 | base := "ABCDEF090807060504030201fffffffffffffffffffffffffffffffffffffffe" 658 | exp := "ff" 659 | bench.Run("even/big", func(b *testing.B) { 660 | benchmark_Exp_Big(b, base, exp) 661 | }) 662 | bench.Run("even/uint256", func(b *testing.B) { 663 | benchmark_Exp_U256(b, base, exp) 664 | }) 665 | } 666 | } 667 | 668 | func BenchmarkDiv(b *testing.B) { 669 | benchmarkDivUint256 := func(b *testing.B, xSamples, modSamples *[numSamples]Int) { 670 | var sink Int 671 | for j := 0; j < b.N; j += numSamples { 672 | for i := 0; i < numSamples; i++ { 673 | sink.Div(&xSamples[i], &modSamples[i]) 674 | } 675 | } 676 | } 677 | benchmarkDivBig := func(b *testing.B, xSamples, modSamples *[numSamples]big.Int) { 678 | var sink big.Int 679 | for j := 0; j < b.N; j += numSamples { 680 | for i := 0; i < numSamples; i++ { 681 | sink.Div(&xSamples[i], &modSamples[i]) 682 | } 683 | } 684 | } 685 | 686 | b.Run("small/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int32Samples, &int32SamplesLt) }) 687 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int64Samples) }) 688 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int128Samples) }) 689 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int192Samples) }) 690 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkDivUint256(b, &int256Samples, &int256SamplesLt) }) 691 | b.Run("small/big", func(b *testing.B) { benchmarkDivBig(b, &big32Samples, &big32SamplesLt) }) 692 | b.Run("mod64/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big64Samples) }) 693 | b.Run("mod128/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big128Samples) }) 694 | b.Run("mod192/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big192Samples) }) 695 | b.Run("mod256/big", func(b *testing.B) { benchmarkDivBig(b, &big256Samples, &big256SamplesLt) }) 696 | } 697 | 698 | func BenchmarkMod(b *testing.B) { 699 | benchmarkModUint256 := func(b *testing.B, xSamples, modSamples *[numSamples]Int) { 700 | var sink Int 701 | for j := 0; j < b.N; j += numSamples { 702 | for i := 0; i < numSamples; i++ { 703 | sink.Mod(&xSamples[i], &modSamples[i]) 704 | } 705 | } 706 | } 707 | benchmarkModBig := func(b *testing.B, xSamples, modSamples *[numSamples]big.Int) { 708 | var sink big.Int 709 | for j := 0; j < b.N; j += numSamples { 710 | for i := 0; i < numSamples; i++ { 711 | sink.Mod(&xSamples[i], &modSamples[i]) 712 | } 713 | } 714 | } 715 | 716 | b.Run("small/uint256", func(b *testing.B) { benchmarkModUint256(b, &int32Samples, &int32SamplesLt) }) 717 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int64Samples) }) 718 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int128Samples) }) 719 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int192Samples) }) 720 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkModUint256(b, &int256Samples, &int256SamplesLt) }) 721 | b.Run("small/big", func(b *testing.B) { benchmarkModBig(b, &big32Samples, &big32SamplesLt) }) 722 | b.Run("mod64/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big64Samples) }) 723 | b.Run("mod128/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big128Samples) }) 724 | b.Run("mod192/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big192Samples) }) 725 | b.Run("mod256/big", func(b *testing.B) { benchmarkModBig(b, &big256Samples, &big256SamplesLt) }) 726 | } 727 | 728 | func BenchmarkDivMod(b *testing.B) { 729 | benchmarkDivModUint256 := func(b *testing.B, xSamples, modSamples *[numSamples]Int) { 730 | var sink, mod Int 731 | for j := 0; j < b.N; j += numSamples { 732 | for i := 0; i < numSamples; i++ { 733 | sink.DivMod(&xSamples[i], &modSamples[i], &mod) 734 | } 735 | } 736 | } 737 | benchmarkDivModBig := func(b *testing.B, xSamples, modSamples *[numSamples]big.Int) { 738 | var sink, mod big.Int 739 | for j := 0; j < b.N; j += numSamples { 740 | for i := 0; i < numSamples; i++ { 741 | sink.DivMod(&xSamples[i], &modSamples[i], &mod) 742 | } 743 | } 744 | } 745 | 746 | b.Run("small/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int32Samples, &int32SamplesLt) }) 747 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int64Samples) }) 748 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int128Samples) }) 749 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int192Samples) }) 750 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkDivModUint256(b, &int256Samples, &int256SamplesLt) }) 751 | b.Run("small/big", func(b *testing.B) { benchmarkDivModBig(b, &big32Samples, &big32SamplesLt) }) 752 | b.Run("mod64/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big64Samples) }) 753 | b.Run("mod128/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big128Samples) }) 754 | b.Run("mod192/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big192Samples) }) 755 | b.Run("mod256/big", func(b *testing.B) { benchmarkDivModBig(b, &big256Samples, &big256SamplesLt) }) 756 | } 757 | 758 | func BenchmarkAddMod(b *testing.B) { 759 | benchmarkAddModUint256 := func(b *testing.B, factorsSamples, modSamples *[numSamples]Int) { 760 | iter := (b.N + numSamples - 1) / numSamples 761 | 762 | for j := 0; j < numSamples; j++ { 763 | var x Int 764 | y := factorsSamples[j] 765 | 766 | for i := 0; i < iter; i++ { 767 | x.AddMod(&x, &y, &modSamples[j]) 768 | } 769 | } 770 | } 771 | benchmarkAddModBig := func(b *testing.B, factorsSamples, modSamples *[numSamples]big.Int) { 772 | iter := (b.N + numSamples - 1) / numSamples 773 | 774 | for j := 0; j < numSamples; j++ { 775 | var x big.Int 776 | y := factorsSamples[j] 777 | 778 | for i := 0; i < iter; i++ { 779 | x.Add(&x, &y) 780 | x.Mod(&x, &modSamples[j]) 781 | } 782 | } 783 | } 784 | 785 | b.Run("small/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int32SamplesLt, &int32Samples) }) 786 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int64SamplesLt, &int64Samples) }) 787 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int128SamplesLt, &int128Samples) }) 788 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int192SamplesLt, &int192Samples) }) 789 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkAddModUint256(b, &int256SamplesLt, &int256Samples) }) 790 | b.Run("small/big", func(b *testing.B) { benchmarkAddModBig(b, &big32SamplesLt, &big32Samples) }) 791 | b.Run("mod64/big", func(b *testing.B) { benchmarkAddModBig(b, &big64SamplesLt, &big64Samples) }) 792 | b.Run("mod128/big", func(b *testing.B) { benchmarkAddModBig(b, &big128SamplesLt, &big128Samples) }) 793 | b.Run("mod192/big", func(b *testing.B) { benchmarkAddModBig(b, &big192SamplesLt, &big192Samples) }) 794 | b.Run("mod256/big", func(b *testing.B) { benchmarkAddModBig(b, &big256SamplesLt, &big256Samples) }) 795 | } 796 | 797 | func BenchmarkMulMod(b *testing.B) { 798 | benchmarkMulModUint256R := func(b *testing.B, factorsSamples, modSamples *[numSamples]Int) { 799 | iter := (b.N + numSamples - 1) / numSamples 800 | 801 | var mu [numSamples][5]uint64 802 | 803 | for i := 0; i < numSamples; i++ { 804 | mu[i] = Reciprocal(&modSamples[i]) 805 | } 806 | 807 | b.ResetTimer() 808 | 809 | for j := 0; j < numSamples; j++ { 810 | x := factorsSamples[j] 811 | 812 | for i := 0; i < iter; i++ { 813 | x.MulModWithReciprocal(&x, &factorsSamples[j], &modSamples[j], &mu[j]) 814 | } 815 | } 816 | } 817 | benchmarkMulModUint256 := func(b *testing.B, factorsSamples, modSamples *[numSamples]Int) { 818 | iter := (b.N + numSamples - 1) / numSamples 819 | 820 | for j := 0; j < numSamples; j++ { 821 | x := factorsSamples[j] 822 | 823 | for i := 0; i < iter; i++ { 824 | x.MulMod(&x, &factorsSamples[j], &modSamples[j]) 825 | } 826 | } 827 | } 828 | benchmarkMulModBig := func(b *testing.B, factorsSamples, modSamples *[numSamples]big.Int) { 829 | iter := (b.N + numSamples - 1) / numSamples 830 | 831 | for j := 0; j < numSamples; j++ { 832 | x := factorsSamples[j] 833 | 834 | for i := 0; i < iter; i++ { 835 | x.Mul(&x, &factorsSamples[j]) 836 | x.Mod(&x, &modSamples[j]) 837 | } 838 | } 839 | } 840 | 841 | b.Run("small/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int32SamplesLt, &int32Samples) }) 842 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int64SamplesLt, &int64Samples) }) 843 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int128SamplesLt, &int128Samples) }) 844 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int192SamplesLt, &int192Samples) }) 845 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkMulModUint256(b, &int256SamplesLt, &int256Samples) }) 846 | b.Run("mod256/uint256r", func(b *testing.B) { benchmarkMulModUint256R(b, &int256SamplesLt, &int256Samples) }) 847 | b.Run("small/big", func(b *testing.B) { benchmarkMulModBig(b, &big32SamplesLt, &big32Samples) }) 848 | b.Run("mod64/big", func(b *testing.B) { benchmarkMulModBig(b, &big64SamplesLt, &big64Samples) }) 849 | b.Run("mod128/big", func(b *testing.B) { benchmarkMulModBig(b, &big128SamplesLt, &big128Samples) }) 850 | b.Run("mod192/big", func(b *testing.B) { benchmarkMulModBig(b, &big192SamplesLt, &big192Samples) }) 851 | b.Run("mod256/big", func(b *testing.B) { benchmarkMulModBig(b, &big256SamplesLt, &big256Samples) }) 852 | } 853 | 854 | func benchmark_SdivLarge_Big(bench *testing.B) { 855 | a := new(big.Int).SetBytes(hex2Bytes("800fffffffffffffffffffffffffd1e870eec79504c60144cc7f5fc2bad1e611")) 856 | b := new(big.Int).SetBytes(hex2Bytes("ff3f9014f20db29ae04af2c2d265de17")) 857 | 858 | bench.ResetTimer() 859 | 860 | for i := 0; i < bench.N; i++ { 861 | bigU256(bigSDiv(new(big.Int), a, b)) 862 | } 863 | } 864 | 865 | func benchmark_SdivLarge_Bit(bench *testing.B) { 866 | a := big.NewInt(0).SetBytes(hex2Bytes("800fffffffffffffffffffffffffd1e870eec79504c60144cc7f5fc2bad1e611")) 867 | b := big.NewInt(0).SetBytes(hex2Bytes("ff3f9014f20db29ae04af2c2d265de17")) 868 | fa, _ := FromBig(a) 869 | fb, _ := FromBig(b) 870 | 871 | bench.ResetTimer() 872 | for i := 0; i < bench.N; i++ { 873 | f := new(Int) 874 | f.SDiv(fa, fb) 875 | } 876 | } 877 | 878 | func BenchmarkSDiv(bench *testing.B) { 879 | bench.Run("large/big", benchmark_SdivLarge_Big) 880 | bench.Run("large/uint256", benchmark_SdivLarge_Bit) 881 | } 882 | 883 | func BenchmarkEncodeHex(b *testing.B) { 884 | hexEncodeU256 := func(b *testing.B, samples *[numSamples]Int) { 885 | b.ReportAllocs() 886 | for j := 0; j < b.N; j += numSamples { 887 | for i := 0; i < numSamples; i++ { 888 | samples[i].Hex() 889 | } 890 | } 891 | } 892 | hexEncodeBig := func(b *testing.B, samples *[numSamples]big.Int) { 893 | b.ReportAllocs() 894 | for j := 0; j < b.N; j += numSamples { 895 | for i := 0; i < numSamples; i++ { 896 | // We're being nice to big.Int here, because this method 897 | // does not add the 0x-prefix -- so an extra alloc is needed to get 898 | // the same result. We still win the benchmark though... 899 | samples[i].Text(16) 900 | } 901 | } 902 | } 903 | b.Run("large/uint256", func(b *testing.B) { hexEncodeU256(b, &int256Samples) }) 904 | b.Run("large/big", func(b *testing.B) { hexEncodeBig(b, &big256Samples) }) 905 | } 906 | 907 | func BenchmarkFromHexString(b *testing.B) { 908 | var hexStrings []string 909 | for _, z := range &int256Samples { 910 | hexStrings = append(hexStrings, (&z).Hex()) 911 | } 912 | b.Run("uint256", func(b *testing.B) { 913 | b.ReportAllocs() 914 | for j := 0; j < b.N; j++ { 915 | i := j % numSamples 916 | if _, err := FromHex(hexStrings[i]); err != nil { 917 | b.Fatalf("%v: %v", err, string(hexStrings[i])) 918 | } 919 | } 920 | }) 921 | b.Run("big", func(b *testing.B) { 922 | b.ReportAllocs() 923 | for j := 0; j < b.N; j++ { 924 | i := j % numSamples 925 | if _, ok := big.NewInt(0).SetString(hexStrings[i], 0); !ok { 926 | b.Fatalf("Error on %v", string(hexStrings[i])) 927 | } 928 | } 929 | }) 930 | } 931 | 932 | func BenchmarkMulDivOverflow(b *testing.B) { 933 | benchmarkUint256 := func(b *testing.B, factorsSamples, muldivSamples *[numSamples]Int) { 934 | iter := (b.N + numSamples - 1) / numSamples 935 | 936 | for j := 0; j < numSamples; j++ { 937 | x := factorsSamples[j] 938 | 939 | for i := 0; i < iter; i++ { 940 | res := new(Int) 941 | res.MulDivOverflow(&x, &x, &muldivSamples[j]) 942 | } 943 | } 944 | } 945 | 946 | benchmarkBig := func(b *testing.B, factorsSamples, muldivSamples *[numSamples]big.Int) { 947 | iter := (b.N + numSamples - 1) / numSamples 948 | 949 | for j := 0; j < numSamples; j++ { 950 | x := factorsSamples[j] 951 | 952 | for i := 0; i < iter; i++ { 953 | res := new(big.Int) 954 | res.Mul(&x, &x) 955 | res.Div(res, &muldivSamples[j]) 956 | } 957 | } 958 | } 959 | 960 | b.Run("small/uint256", func(b *testing.B) { benchmarkUint256(b, &int32SamplesLt, &int32Samples) }) 961 | b.Run("div64/uint256", func(b *testing.B) { benchmarkUint256(b, &int64SamplesLt, &int64Samples) }) 962 | b.Run("div128/uint256", func(b *testing.B) { benchmarkUint256(b, &int128SamplesLt, &int128Samples) }) 963 | b.Run("div192/uint256", func(b *testing.B) { benchmarkUint256(b, &int192SamplesLt, &int192Samples) }) 964 | b.Run("div256/uint256", func(b *testing.B) { benchmarkUint256(b, &int256SamplesLt, &int256Samples) }) 965 | b.Run("small/big", func(b *testing.B) { benchmarkBig(b, &big32SamplesLt, &big32Samples) }) 966 | b.Run("div64/big", func(b *testing.B) { benchmarkBig(b, &big64SamplesLt, &big64Samples) }) 967 | b.Run("div128/big", func(b *testing.B) { benchmarkBig(b, &big128SamplesLt, &big128Samples) }) 968 | b.Run("div192/big", func(b *testing.B) { benchmarkBig(b, &big192SamplesLt, &big192Samples) }) 969 | b.Run("div256/big", func(b *testing.B) { benchmarkBig(b, &big256SamplesLt, &big256Samples) }) 970 | 971 | } 972 | 973 | func BenchmarkHashTreeRoot(b *testing.B) { 974 | var ( 975 | z = &Int{1, 2, 3, 4} 976 | exp = [32]byte{1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0} 977 | ) 978 | b.ReportAllocs() 979 | for i := 0; i < b.N; i++ { 980 | r, err := z.HashTreeRoot() 981 | if err != nil { 982 | b.Fatal(err) 983 | } 984 | if r != exp { 985 | b.Fatalf("have %v want %v", r, exp) 986 | } 987 | } 988 | } 989 | 990 | func BenchmarkSet(bench *testing.B) { 991 | benchmarkUint256 := func(bench *testing.B) { 992 | a := new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 993 | 994 | result := new(Int) 995 | bench.ResetTimer() 996 | for i := 0; i < bench.N; i++ { 997 | result.Set(a) 998 | } 999 | } 1000 | benchmarkBig := func(bench *testing.B) { 1001 | a := new(big.Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 1002 | 1003 | result := new(big.Int) 1004 | bench.ResetTimer() 1005 | for i := 0; i < bench.N; i++ { 1006 | result.Set(a) 1007 | } 1008 | } 1009 | 1010 | bench.Run("single/uint256", benchmarkUint256) 1011 | bench.Run("single/big", benchmarkBig) 1012 | } 1013 | 1014 | func BenchmarkByte(bench *testing.B) { 1015 | var ( 1016 | a = new(Int).SetBytes(hex2Bytes("f123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9")) 1017 | num = NewInt(0) 1018 | result = new(Int) 1019 | ) 1020 | bench.ResetTimer() 1021 | for i := 0; i < bench.N; i++ { 1022 | for ii := uint64(0); ii < 32; ii++ { 1023 | result.Set(a) 1024 | num.SetUint64(ii) 1025 | _ = result.Byte(num) 1026 | } 1027 | } 1028 | } 1029 | 1030 | func BenchmarkExtendSign(b *testing.B) { 1031 | a, err := FromHex("0xf123456789abcdeffedcba9876543210f2f3f4f5f6f7f8f9fff3f4f5f6f7f8f9") 1032 | if err != nil { 1033 | b.Fatal(err) 1034 | } 1035 | result := new(Int) 1036 | n := NewInt(0) 1037 | b.ResetTimer() 1038 | for i := uint64(0); i < uint64(b.N); i++ { 1039 | n.SetUint64(i % 33) 1040 | result.ExtendSign(a, n) 1041 | } 1042 | } 1043 | 1044 | func BenchmarkWriteTo(b *testing.B) { 1045 | fa, err := FromHex("0x1100030405060708090a0b0c0d0ed1e870eec79504c60144cc7f5fc2bad1e611") 1046 | if err != nil { 1047 | b.Fatal(err) 1048 | } 1049 | b.Run("fixed-20", func(b *testing.B) { 1050 | dest := [20]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 1051 | for i := 0; i < b.N; i++ { 1052 | fa.WriteToArray20(&dest) 1053 | } 1054 | _ = (string(dest[:])) // Prevent the compiler from optimizing away the op 1055 | }) 1056 | b.Run("fixed-32", func(b *testing.B) { 1057 | dest := [32]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} 1058 | for i := 0; i < b.N; i++ { 1059 | fa.WriteToArray32(&dest) 1060 | } 1061 | _ = (string(dest[:])) // Prevent the compiler from optimizing away the op 1062 | }) 1063 | b.Run("slice", func(b *testing.B) { 1064 | dest := make([]byte, 64) 1065 | for i := 0; i < b.N; i++ { 1066 | fa.WriteToSlice(dest) 1067 | } 1068 | _ = (string(dest[:])) // Prevent the compiler from optimizing away the op 1069 | }) 1070 | b.Run("put256", func(b *testing.B) { 1071 | dest := make([]byte, 64) 1072 | for i := 0; i < b.N; i++ { 1073 | fa.PutUint256(dest) 1074 | } 1075 | _ = (string(dest[:])) // Prevent the compiler from optimizing away the op 1076 | }) 1077 | } 1078 | 1079 | func BenchmarkSgt(b *testing.B) { 1080 | benchmarkSgtUint256 := func(b *testing.B, aSamples, bSamples *[numSamples]Int) { 1081 | var sink bool 1082 | for j := 0; j < b.N; j += numSamples { 1083 | for i := 0; i < numSamples; i++ { 1084 | sink = aSamples[i].Sgt(&bSamples[i]) 1085 | } 1086 | } 1087 | _ = sink 1088 | } 1089 | 1090 | b.Run("small/uint256", func(b *testing.B) { benchmarkSgtUint256(b, &int32Samples, &int32Samples) }) 1091 | b.Run("large/uint256", func(b *testing.B) { benchmarkSgtUint256(b, &int256Samples, &int256Samples) }) 1092 | } 1093 | 1094 | func BenchmarkSlt(b *testing.B) { 1095 | benchmarkSltUint256 := func(b *testing.B, aSamples, bSamples *[numSamples]Int) { 1096 | var sink bool 1097 | for j := 0; j < b.N; j += numSamples { 1098 | for i := 0; i < numSamples; i++ { 1099 | sink = aSamples[i].Slt(&bSamples[i]) 1100 | } 1101 | } 1102 | _ = sink 1103 | } 1104 | 1105 | b.Run("small/uint256", func(b *testing.B) { benchmarkSltUint256(b, &int32Samples, &int32Samples) }) 1106 | b.Run("large/uint256", func(b *testing.B) { benchmarkSltUint256(b, &int256Samples, &int256Samples) }) 1107 | } 1108 | 1109 | func BenchmarkInt_PaddedBytes(b *testing.B) { 1110 | bytearr := hex2Bytes("0e320219838e859b2f9f18b72e3d4073ca50b37d") 1111 | aa := new(Int).SetBytes(bytearr) 1112 | for i := 0; i < b.N; i++ { 1113 | _ = aa.PaddedBytes(40) 1114 | } 1115 | } 1116 | 1117 | func BenchmarkSMod(b *testing.B) { 1118 | benchmarkSmodUint256 := func(b *testing.B, xSamples, modSamples *[numSamples]Int) { 1119 | var sink Int 1120 | for j := 0; j < b.N; j += numSamples { 1121 | for i := 0; i < numSamples; i++ { 1122 | sink.SMod(&xSamples[i], &modSamples[i]) 1123 | } 1124 | } 1125 | } 1126 | 1127 | b.Run("small/uint256", func(b *testing.B) { benchmarkSmodUint256(b, &int32Samples, &int32SamplesLt) }) 1128 | b.Run("mod64/uint256", func(b *testing.B) { benchmarkSmodUint256(b, &int256Samples, &int64Samples) }) 1129 | b.Run("mod128/uint256", func(b *testing.B) { benchmarkSmodUint256(b, &int256Samples, &int128Samples) }) 1130 | b.Run("mod192/uint256", func(b *testing.B) { benchmarkSmodUint256(b, &int256Samples, &int192Samples) }) 1131 | b.Run("mod256/uint256", func(b *testing.B) { benchmarkSmodUint256(b, &int256Samples, &int256SamplesLt) }) 1132 | } 1133 | 1134 | func BenchmarkSRsh(b *testing.B) { 1135 | f2 := NewInt(1) 1136 | b.ResetTimer() 1137 | for i := 0; i < b.N; i++ { 1138 | _ = f2.SRsh(f2, 10) 1139 | } 1140 | } 1141 | -------------------------------------------------------------------------------- /uint256.go: -------------------------------------------------------------------------------- 1 | // uint256: Fixed size 256-bit math library 2 | // Copyright 2018-2020 uint256 Authors 3 | // SPDX-License-Identifier: BSD-3-Clause 4 | 5 | // Package math provides integer math utilities. 6 | 7 | package uint256 8 | 9 | import ( 10 | "encoding/binary" 11 | "math" 12 | "math/big" 13 | "math/bits" 14 | ) 15 | 16 | // Int is represented as an array of 4 uint64, in little-endian order, 17 | // so that Int[3] is the most significant, and Int[0] is the least significant 18 | type Int [4]uint64 19 | 20 | // NewInt returns a new initialized Int. 21 | func NewInt(val uint64) *Int { 22 | z := &Int{} 23 | z.SetUint64(val) 24 | return z 25 | } 26 | 27 | // SetBytes interprets buf as the bytes of a big-endian unsigned 28 | // integer, sets z to that value, and returns z. 29 | // If buf is larger than 32 bytes, the last 32 bytes is used. This operation 30 | // is semantically equivalent to `FromBig(new(big.Int).SetBytes(buf))` 31 | func (z *Int) SetBytes(buf []byte) *Int { 32 | switch l := len(buf); l { 33 | case 0: 34 | z.Clear() 35 | case 1: 36 | z.SetBytes1(buf) 37 | case 2: 38 | z.SetBytes2(buf) 39 | case 3: 40 | z.SetBytes3(buf) 41 | case 4: 42 | z.SetBytes4(buf) 43 | case 5: 44 | z.SetBytes5(buf) 45 | case 6: 46 | z.SetBytes6(buf) 47 | case 7: 48 | z.SetBytes7(buf) 49 | case 8: 50 | z.SetBytes8(buf) 51 | case 9: 52 | z.SetBytes9(buf) 53 | case 10: 54 | z.SetBytes10(buf) 55 | case 11: 56 | z.SetBytes11(buf) 57 | case 12: 58 | z.SetBytes12(buf) 59 | case 13: 60 | z.SetBytes13(buf) 61 | case 14: 62 | z.SetBytes14(buf) 63 | case 15: 64 | z.SetBytes15(buf) 65 | case 16: 66 | z.SetBytes16(buf) 67 | case 17: 68 | z.SetBytes17(buf) 69 | case 18: 70 | z.SetBytes18(buf) 71 | case 19: 72 | z.SetBytes19(buf) 73 | case 20: 74 | z.SetBytes20(buf) 75 | case 21: 76 | z.SetBytes21(buf) 77 | case 22: 78 | z.SetBytes22(buf) 79 | case 23: 80 | z.SetBytes23(buf) 81 | case 24: 82 | z.SetBytes24(buf) 83 | case 25: 84 | z.SetBytes25(buf) 85 | case 26: 86 | z.SetBytes26(buf) 87 | case 27: 88 | z.SetBytes27(buf) 89 | case 28: 90 | z.SetBytes28(buf) 91 | case 29: 92 | z.SetBytes29(buf) 93 | case 30: 94 | z.SetBytes30(buf) 95 | case 31: 96 | z.SetBytes31(buf) 97 | default: 98 | z.SetBytes32(buf[l-32:]) 99 | } 100 | return z 101 | } 102 | 103 | // Bytes32 returns the value of z as a 32-byte big-endian array. 104 | func (z *Int) Bytes32() [32]byte { 105 | // The PutUint64()s are inlined and we get 4x (load, bswap, store) instructions. 106 | var b [32]byte 107 | binary.BigEndian.PutUint64(b[0:8], z[3]) 108 | binary.BigEndian.PutUint64(b[8:16], z[2]) 109 | binary.BigEndian.PutUint64(b[16:24], z[1]) 110 | binary.BigEndian.PutUint64(b[24:32], z[0]) 111 | return b 112 | } 113 | 114 | // Bytes20 returns the value of z as a 20-byte big-endian array. 115 | func (z *Int) Bytes20() [20]byte { 116 | var b [20]byte 117 | // The PutUint*()s are inlined and we get 3x (load, bswap, store) instructions. 118 | binary.BigEndian.PutUint32(b[0:4], uint32(z[2])) 119 | binary.BigEndian.PutUint64(b[4:12], z[1]) 120 | binary.BigEndian.PutUint64(b[12:20], z[0]) 121 | return b 122 | } 123 | 124 | // Bytes returns the value of z as a big-endian byte slice. 125 | func (z *Int) Bytes() []byte { 126 | b := z.Bytes32() 127 | return b[32-z.ByteLen():] 128 | } 129 | 130 | // WriteToSlice writes the content of z into the given byteslice. 131 | // If dest is larger than 32 bytes, z will fill the first parts, and leave 132 | // the end untouched. 133 | // OBS! If dest is smaller than 32 bytes, only the end parts of z will be used 134 | // for filling the array, making it useful for filling an Address object 135 | func (z *Int) WriteToSlice(dest []byte) { 136 | // ensure 32 bytes 137 | // A too large buffer. Fill last 32 bytes 138 | end := len(dest) - 1 139 | if end > 31 { 140 | end = 31 141 | } 142 | 143 | i := 0 144 | for ; i+7 <= end; i += 8 { 145 | binary.BigEndian.PutUint64(dest[end-i-7:], z[i/8]) 146 | } 147 | 148 | for ; i <= end; i++ { 149 | dest[end-i] = byte(z[i/8] >> uint64(8*(i%8))) 150 | } 151 | } 152 | 153 | // PutUint256 writes all 32 bytes of z to the destination slice, including zero-bytes. 154 | // If dest is larger than 32 bytes, z will fill the first parts, and leave 155 | // the end untouched. 156 | // Note: The dest slice must be at least 32 bytes large, otherwise this 157 | // method will panic. The method WriteToSlice, which is slower, should be used 158 | // if the destination slice is smaller or of unknown size. 159 | func (z *Int) PutUint256(dest []byte) { 160 | _ = dest[31] 161 | binary.BigEndian.PutUint64(dest[0:8], z[3]) 162 | binary.BigEndian.PutUint64(dest[8:16], z[2]) 163 | binary.BigEndian.PutUint64(dest[16:24], z[1]) 164 | binary.BigEndian.PutUint64(dest[24:32], z[0]) 165 | } 166 | 167 | // WriteToArray32 writes all 32 bytes of z to the destination array, including zero-bytes 168 | func (z *Int) WriteToArray32(dest *[32]byte) { 169 | // The PutUint64()s are inlined and we get 4x (load, bswap, store) instructions. 170 | binary.BigEndian.PutUint64(dest[0:8], z[3]) 171 | binary.BigEndian.PutUint64(dest[8:16], z[2]) 172 | binary.BigEndian.PutUint64(dest[16:24], z[1]) 173 | binary.BigEndian.PutUint64(dest[24:32], z[0]) 174 | } 175 | 176 | // WriteToArray20 writes the last 20 bytes of z to the destination array, including zero-bytes 177 | func (z *Int) WriteToArray20(dest *[20]byte) { 178 | // The PutUint*()s are inlined and we get 3x (load, bswap, store) instructions. 179 | binary.BigEndian.PutUint32(dest[0:4], uint32(z[2])) 180 | binary.BigEndian.PutUint64(dest[4:12], z[1]) 181 | binary.BigEndian.PutUint64(dest[12:20], z[0]) 182 | } 183 | 184 | // Uint64 returns the lower 64-bits of z 185 | func (z *Int) Uint64() uint64 { 186 | return z[0] 187 | } 188 | 189 | // Uint64WithOverflow returns the lower 64-bits of z and bool whether overflow occurred 190 | func (z *Int) Uint64WithOverflow() (uint64, bool) { 191 | return z[0], (z[1] | z[2] | z[3]) != 0 192 | } 193 | 194 | // Clone creates a new Int identical to z 195 | func (z *Int) Clone() *Int { 196 | return &Int{z[0], z[1], z[2], z[3]} 197 | } 198 | 199 | // Add sets z to the sum x+y 200 | func (z *Int) Add(x, y *Int) *Int { 201 | var carry uint64 202 | z[0], carry = bits.Add64(x[0], y[0], 0) 203 | z[1], carry = bits.Add64(x[1], y[1], carry) 204 | z[2], carry = bits.Add64(x[2], y[2], carry) 205 | z[3], _ = bits.Add64(x[3], y[3], carry) 206 | return z 207 | } 208 | 209 | // IAdd adds the value of x to z itself and returns z, modifying z in place. 210 | func (z *Int) IAdd(x *Int) *Int { 211 | return z.Add(z, x) 212 | } 213 | 214 | // AddOverflow sets z to the sum x+y, and returns z and whether overflow occurred 215 | func (z *Int) AddOverflow(x, y *Int) (*Int, bool) { 216 | var carry uint64 217 | z[0], carry = bits.Add64(x[0], y[0], 0) 218 | z[1], carry = bits.Add64(x[1], y[1], carry) 219 | z[2], carry = bits.Add64(x[2], y[2], carry) 220 | z[3], carry = bits.Add64(x[3], y[3], carry) 221 | return z, carry != 0 222 | } 223 | 224 | // AddMod sets z to the sum ( x+y ) mod m, and returns z. 225 | // If m == 0, z is set to 0 (OBS: differs from the big.Int) 226 | func (z *Int) AddMod(x, y, m *Int) *Int { 227 | 228 | // Fast path for m >= 2^192, with x and y at most slightly bigger than m. 229 | // This is always the case when x and y are already reduced modulo such m. 230 | 231 | if (m[3] != 0) && (x[3] <= m[3]) && (y[3] <= m[3]) { 232 | var ( 233 | gteC1 uint64 234 | gteC2 uint64 235 | tmpX Int 236 | tmpY Int 237 | res Int 238 | ) 239 | 240 | // reduce x/y modulo m if they are gte m 241 | tmpX[0], gteC1 = bits.Sub64(x[0], m[0], gteC1) 242 | tmpX[1], gteC1 = bits.Sub64(x[1], m[1], gteC1) 243 | tmpX[2], gteC1 = bits.Sub64(x[2], m[2], gteC1) 244 | tmpX[3], gteC1 = bits.Sub64(x[3], m[3], gteC1) 245 | 246 | tmpY[0], gteC2 = bits.Sub64(y[0], m[0], gteC2) 247 | tmpY[1], gteC2 = bits.Sub64(y[1], m[1], gteC2) 248 | tmpY[2], gteC2 = bits.Sub64(y[2], m[2], gteC2) 249 | tmpY[3], gteC2 = bits.Sub64(y[3], m[3], gteC2) 250 | 251 | if gteC1 == 0 { 252 | x = &tmpX 253 | } 254 | if gteC2 == 0 { 255 | y = &tmpY 256 | } 257 | var ( 258 | c1 uint64 259 | c2 uint64 260 | tmp Int 261 | ) 262 | 263 | res[0], c1 = bits.Add64(x[0], y[0], c1) 264 | res[1], c1 = bits.Add64(x[1], y[1], c1) 265 | res[2], c1 = bits.Add64(x[2], y[2], c1) 266 | res[3], c1 = bits.Add64(x[3], y[3], c1) 267 | 268 | tmp[0], c2 = bits.Sub64(res[0], m[0], c2) 269 | tmp[1], c2 = bits.Sub64(res[1], m[1], c2) 270 | tmp[2], c2 = bits.Sub64(res[2], m[2], c2) 271 | tmp[3], c2 = bits.Sub64(res[3], m[3], c2) 272 | 273 | // final sub was unnecessary 274 | if c1 == 0 && c2 != 0 { 275 | return z.Set(&res) 276 | } 277 | 278 | return z.Set(&tmp) 279 | } 280 | 281 | if m.IsZero() { 282 | return z.Clear() 283 | } 284 | if z == m { // z is an alias for m and will be overwritten by AddOverflow before m is read 285 | m = m.Clone() 286 | } 287 | if _, overflow := z.AddOverflow(x, y); overflow { 288 | sum := [5]uint64{z[0], z[1], z[2], z[3], 1} 289 | var quot [5]uint64 290 | var rem Int 291 | udivrem(quot[:], sum[:], m, &rem) 292 | return z.Set(&rem) 293 | } 294 | return z.Mod(z, m) 295 | } 296 | 297 | // IAddMod adds x to z itself modulo m, modifying z in place, and returns z. 298 | // Mathematically: z = (z + x) mod m. 299 | func (z *Int) IAddMod(x, m *Int) *Int { 300 | return z.AddMod(z, x, m) 301 | } 302 | 303 | // AddUint64 sets z to x + y, where y is a uint64, and returns z 304 | func (z *Int) AddUint64(x *Int, y uint64) *Int { 305 | var carry uint64 306 | 307 | z[0], carry = bits.Add64(x[0], y, 0) 308 | z[1], carry = bits.Add64(x[1], 0, carry) 309 | z[2], carry = bits.Add64(x[2], 0, carry) 310 | z[3], _ = bits.Add64(x[3], 0, carry) 311 | return z 312 | } 313 | 314 | // IAddUint64 adds uint64 x to z itself, modifying z in place, and returns z. 315 | // Mathematically: z = z + x. 316 | func (z *Int) IAddUint64(x uint64) *Int { 317 | return z.AddUint64(z, x) 318 | } 319 | 320 | // PaddedBytes encodes a Int as a 0-padded byte slice. The length 321 | // of the slice is at least n bytes. 322 | // Example, z =1, n = 20 => [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] 323 | func (z *Int) PaddedBytes(n int) []byte { 324 | b := make([]byte, n) 325 | 326 | i := 0 327 | for ; i < 32 && i+8 <= n; i += 8 { 328 | binary.BigEndian.PutUint64(b[n-i-8:], z[i/8]) 329 | } 330 | for ; i < 32 && i < n; i++ { 331 | b[n-1-i] = byte(z[i/8] >> uint64(8*(i%8))) 332 | } 333 | return b 334 | } 335 | 336 | // SubUint64 set z to the difference x - y, where y is a uint64, and returns z 337 | func (z *Int) SubUint64(x *Int, y uint64) *Int { 338 | var carry uint64 339 | z[0], carry = bits.Sub64(x[0], y, carry) 340 | z[1], carry = bits.Sub64(x[1], 0, carry) 341 | z[2], carry = bits.Sub64(x[2], 0, carry) 342 | z[3], _ = bits.Sub64(x[3], 0, carry) 343 | return z 344 | } 345 | 346 | // ISubUint64 subtracts uint64 x from z itself, modifying z in place, and returns z. 347 | // Mathematically: z = z - x. 348 | func (z *Int) ISubUint64(x uint64) *Int { 349 | return z.SubUint64(z, x) 350 | } 351 | 352 | // SubOverflow sets z to the difference x-y and returns z and true if the operation underflowed 353 | func (z *Int) SubOverflow(x, y *Int) (*Int, bool) { 354 | var carry uint64 355 | z[0], carry = bits.Sub64(x[0], y[0], 0) 356 | z[1], carry = bits.Sub64(x[1], y[1], carry) 357 | z[2], carry = bits.Sub64(x[2], y[2], carry) 358 | z[3], carry = bits.Sub64(x[3], y[3], carry) 359 | return z, carry != 0 360 | } 361 | 362 | // Sub sets z to the difference x-y 363 | func (z *Int) Sub(x, y *Int) *Int { 364 | var carry uint64 365 | z[0], carry = bits.Sub64(x[0], y[0], 0) 366 | z[1], carry = bits.Sub64(x[1], y[1], carry) 367 | z[2], carry = bits.Sub64(x[2], y[2], carry) 368 | z[3], _ = bits.Sub64(x[3], y[3], carry) 369 | return z 370 | } 371 | 372 | // ISub subtracts x from z itself, modifying z in place, and returns z. 373 | // Mathematically: z = z - x. 374 | func (z *Int) ISub(x *Int) *Int { 375 | return z.Sub(z, x) 376 | } 377 | 378 | // umulStep computes (hi * 2^64 + lo) = z + (x * y) + carry. 379 | func umulStep(z, x, y, carry uint64) (hi, lo uint64) { 380 | hi, lo = bits.Mul64(x, y) 381 | lo, carry = bits.Add64(lo, carry, 0) 382 | hi, _ = bits.Add64(hi, 0, carry) 383 | lo, carry = bits.Add64(lo, z, 0) 384 | hi, _ = bits.Add64(hi, 0, carry) 385 | return hi, lo 386 | } 387 | 388 | // umulHop computes (hi * 2^64 + lo) = z + (x * y) 389 | func umulHop(z, x, y uint64) (hi, lo uint64) { 390 | hi, lo = bits.Mul64(x, y) 391 | lo, carry := bits.Add64(lo, z, 0) 392 | hi, _ = bits.Add64(hi, 0, carry) 393 | return hi, lo 394 | } 395 | 396 | // umul computes full 256 x 256 -> 512 multiplication. 397 | func umul(x, y *Int, res *[8]uint64) { 398 | var ( 399 | carry, carry4, carry5, carry6 uint64 400 | res1, res2, res3, res4, res5 uint64 401 | ) 402 | 403 | carry, res[0] = bits.Mul64(x[0], y[0]) 404 | carry, res1 = umulHop(carry, x[1], y[0]) 405 | carry, res2 = umulHop(carry, x[2], y[0]) 406 | carry4, res3 = umulHop(carry, x[3], y[0]) 407 | 408 | carry, res[1] = umulHop(res1, x[0], y[1]) 409 | carry, res2 = umulStep(res2, x[1], y[1], carry) 410 | carry, res3 = umulStep(res3, x[2], y[1], carry) 411 | carry5, res4 = umulStep(carry4, x[3], y[1], carry) 412 | 413 | carry, res[2] = umulHop(res2, x[0], y[2]) 414 | carry, res3 = umulStep(res3, x[1], y[2], carry) 415 | carry, res4 = umulStep(res4, x[2], y[2], carry) 416 | carry6, res5 = umulStep(carry5, x[3], y[2], carry) 417 | 418 | carry, res[3] = umulHop(res3, x[0], y[3]) 419 | carry, res[4] = umulStep(res4, x[1], y[3], carry) 420 | carry, res[5] = umulStep(res5, x[2], y[3], carry) 421 | res[7], res[6] = umulStep(carry6, x[3], y[3], carry) 422 | } 423 | 424 | // Mul sets z to the product x*y 425 | func (z *Int) Mul(x, y *Int) *Int { 426 | var ( 427 | carry0, carry1, carry2 uint64 428 | res1, res2 uint64 429 | x0, x1, x2, x3 = x[0], x[1], x[2], x[3] 430 | y0, y1, y2, y3 = y[0], y[1], y[2], y[3] 431 | ) 432 | 433 | carry0, z[0] = bits.Mul64(x0, y0) 434 | carry0, res1 = umulHop(carry0, x1, y0) 435 | carry0, res2 = umulHop(carry0, x2, y0) 436 | 437 | carry1, z[1] = umulHop(res1, x0, y1) 438 | carry1, res2 = umulStep(res2, x1, y1, carry1) 439 | 440 | carry2, z[2] = umulHop(res2, x0, y2) 441 | 442 | z[3] = x3*y0 + x2*y1 + x0*y3 + x1*y2 + carry0 + carry1 + carry2 443 | return z 444 | } 445 | 446 | // IMul multiplies z by x, modifying z in place, and returns z. 447 | // Mathematically: z = z * x. 448 | func (z *Int) IMul(x *Int) *Int { 449 | return z.Mul(z, x) 450 | } 451 | 452 | // MulOverflow sets z to the product x*y, and returns z and whether overflow occurred 453 | func (z *Int) MulOverflow(x, y *Int) (*Int, bool) { 454 | var p [8]uint64 455 | umul(x, y, &p) 456 | copy(z[:], p[:4]) 457 | return z, (p[4] | p[5] | p[6] | p[7]) != 0 458 | } 459 | 460 | func (z *Int) squared() { 461 | var ( 462 | carry0, carry1, carry2 uint64 463 | res0, res1, res2, res3 uint64 464 | ) 465 | 466 | carry0, res0 = bits.Mul64(z[0], z[0]) 467 | carry0, res1 = umulHop(carry0, z[0], z[1]) 468 | carry0, res2 = umulHop(carry0, z[0], z[2]) 469 | 470 | carry1, res1 = umulHop(res1, z[0], z[1]) 471 | carry1, res2 = umulStep(res2, z[1], z[1], carry1) 472 | 473 | carry2, res2 = umulHop(res2, z[0], z[2]) 474 | 475 | res3 = 2*(z[0]*z[3]+z[1]*z[2]) + carry0 + carry1 + carry2 476 | 477 | z[0], z[1], z[2], z[3] = res0, res1, res2, res3 478 | } 479 | 480 | // addTo computes x += y. 481 | // Requires len(x) >= len(y) > 0. 482 | func addTo(x, y []uint64) uint64 { 483 | var carry uint64 484 | _ = x[len(y)-1] // bounds check hint to compiler; see golang.org/issue/14808 485 | for i := 0; i < len(y); i++ { 486 | x[i], carry = bits.Add64(x[i], y[i], carry) 487 | } 488 | return carry 489 | } 490 | 491 | // subMulTo computes x -= y * multiplier. 492 | // Requires len(x) >= len(y) > 0. 493 | func subMulTo(x, y []uint64, multiplier uint64) uint64 { 494 | var borrow uint64 495 | _ = x[len(y)-1] // bounds check hint to compiler; see golang.org/issue/14808 496 | for i := 0; i < len(y); i++ { 497 | s, carry1 := bits.Sub64(x[i], borrow, 0) 498 | ph, pl := bits.Mul64(y[i], multiplier) 499 | t, carry2 := bits.Sub64(s, pl, 0) 500 | x[i] = t 501 | borrow = ph + carry1 + carry2 502 | } 503 | return borrow 504 | } 505 | 506 | // udivremBy1 divides u by single normalized word d and produces both quotient and remainder. 507 | // The quotient is stored in provided quot. 508 | func udivremBy1(quot, u []uint64, d uint64) (rem uint64) { 509 | reciprocal := reciprocal2by1(d) 510 | rem = u[len(u)-1] // Set the top word as remainder. 511 | for j := len(u) - 2; j >= 0; j-- { 512 | quot[j], rem = udivrem2by1(rem, u[j], d, reciprocal) 513 | } 514 | return rem 515 | } 516 | 517 | // udivremKnuth implements the division of u by normalized multiple word d from the Knuth's division algorithm. 518 | // The quotient is stored in provided quot - len(u)-len(d) words. 519 | // Updates u to contain the remainder - len(d) words. 520 | func udivremKnuth(quot, u, d []uint64) { 521 | dh := d[len(d)-1] 522 | dl := d[len(d)-2] 523 | reciprocal := reciprocal2by1(dh) 524 | 525 | for j := len(u) - len(d) - 1; j >= 0; j-- { 526 | u2 := u[j+len(d)] 527 | u1 := u[j+len(d)-1] 528 | u0 := u[j+len(d)-2] 529 | 530 | var qhat, rhat uint64 531 | if u2 >= dh { // Division overflows. 532 | qhat = ^uint64(0) 533 | // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). 534 | } else { 535 | qhat, rhat = udivrem2by1(u2, u1, dh, reciprocal) 536 | ph, pl := bits.Mul64(qhat, dl) 537 | if ph > rhat || (ph == rhat && pl > u0) { 538 | qhat-- 539 | // TODO: Add "qhat one to big" adjustment (not needed for correctness, but helps avoiding "add back" case). 540 | } 541 | } 542 | 543 | // Multiply and subtract. 544 | borrow := subMulTo(u[j:], d, qhat) 545 | u[j+len(d)] = u2 - borrow 546 | if u2 < borrow { // Too much subtracted, add back. 547 | qhat-- 548 | u[j+len(d)] += addTo(u[j:], d) 549 | } 550 | 551 | quot[j] = qhat // Store quotient digit. 552 | } 553 | } 554 | 555 | // udivrem divides u by d and produces both quotient and remainder. 556 | // The quotient is stored in provided quot - len(u)-len(d)+1 words. 557 | // It loosely follows the Knuth's division algorithm (sometimes referenced as "schoolbook" division) using 64-bit words. 558 | // See Knuth, Volume 2, section 4.3.1, Algorithm D. 559 | func udivrem(quot, u []uint64, d, rem *Int) { 560 | var dLen int 561 | for i := len(d) - 1; i >= 0; i-- { 562 | if d[i] != 0 { 563 | dLen = i + 1 564 | break 565 | } 566 | } 567 | 568 | shift := uint(bits.LeadingZeros64(d[dLen-1])) 569 | 570 | var dnStorage Int 571 | dn := dnStorage[:dLen] 572 | for i := dLen - 1; i > 0; i-- { 573 | dn[i] = (d[i] << shift) | (d[i-1] >> (64 - shift)) 574 | } 575 | dn[0] = d[0] << shift 576 | 577 | var uLen int 578 | for i := len(u) - 1; i >= 0; i-- { 579 | if u[i] != 0 { 580 | uLen = i + 1 581 | break 582 | } 583 | } 584 | 585 | if uLen < dLen { 586 | if rem != nil { 587 | copy(rem[:], u) 588 | } 589 | return 590 | } 591 | 592 | var unStorage [9]uint64 593 | un := unStorage[:uLen+1] 594 | un[uLen] = u[uLen-1] >> (64 - shift) 595 | for i := uLen - 1; i > 0; i-- { 596 | un[i] = (u[i] << shift) | (u[i-1] >> (64 - shift)) 597 | } 598 | un[0] = u[0] << shift 599 | 600 | // TODO: Skip the highest word of numerator if not significant. 601 | 602 | if dLen == 1 { 603 | r := udivremBy1(quot, un, dn[0]) 604 | if rem != nil { 605 | rem.SetUint64(r >> shift) 606 | } 607 | return 608 | } 609 | 610 | udivremKnuth(quot, un, dn) 611 | 612 | if rem != nil { 613 | for i := 0; i < dLen-1; i++ { 614 | rem[i] = (un[i] >> shift) | (un[i+1] << (64 - shift)) 615 | } 616 | rem[dLen-1] = un[dLen-1] >> shift 617 | } 618 | } 619 | 620 | // Div sets z to the quotient x/y for returns z. 621 | // If y == 0, z is set to 0 622 | func (z *Int) Div(x, y *Int) *Int { 623 | if y.IsZero() || y.Gt(x) { 624 | return z.Clear() 625 | } 626 | if x.Eq(y) { 627 | return z.SetOne() 628 | } 629 | // Shortcut some cases 630 | if x.IsUint64() { 631 | return z.SetUint64(x.Uint64() / y.Uint64()) 632 | } 633 | 634 | // At this point, we know 635 | // x/y ; x > y > 0 636 | 637 | var quot Int 638 | udivrem(quot[:], x[:], y, nil) 639 | return z.Set(") 640 | } 641 | 642 | // IDiv divides z by x, modifying z in place, and returns z. 643 | // Mathematically: z = z / x. 644 | func (z *Int) IDiv(x *Int) *Int { 645 | return z.Div(z, x) 646 | } 647 | 648 | // Mod sets z to the modulus x%y for y != 0 and returns z. 649 | // If y == 0, z is set to 0 (OBS: differs from the big.Int) 650 | func (z *Int) Mod(x, y *Int) *Int { 651 | if y.IsZero() || x.Eq(y) { 652 | return z.Clear() 653 | } 654 | if x.Lt(y) { 655 | return z.Set(x) 656 | } 657 | // At this point: 658 | // x != 0 659 | // y != 0 660 | // x > y 661 | 662 | // Shortcut trivial case 663 | if x.IsUint64() { 664 | return z.SetUint64(x.Uint64() % y.Uint64()) 665 | } 666 | 667 | var quot, rem Int 668 | udivrem(quot[:], x[:], y, &rem) 669 | return z.Set(&rem) 670 | } 671 | 672 | // IMod sets z to the modulus z%x, modifying z in place, and returns z. 673 | // Mathematically: z = z % x. 674 | func (z *Int) IMod(x *Int) *Int { 675 | return z.Mod(z, x) 676 | } 677 | 678 | // DivMod sets z to the quotient x div y and m to the modulus x mod y and returns the pair (z, m) for y != 0. 679 | // If y == 0, both z and m are set to 0 (OBS: differs from the big.Int) 680 | func (z *Int) DivMod(x, y, m *Int) (*Int, *Int) { 681 | if z == m { 682 | // We return both z and m as results, if they are aliased, we have to 683 | // un-alias them to be able to return separate results. 684 | m = new(Int).Set(m) 685 | } 686 | if y.IsZero() { 687 | return z.Clear(), m.Clear() 688 | } 689 | if x.Eq(y) { 690 | return z.SetOne(), m.Clear() 691 | } 692 | if x.Lt(y) { 693 | m.Set(x) 694 | return z.Clear(), m 695 | } 696 | 697 | // At this point: 698 | // x != 0 699 | // y != 0 700 | // x > y 701 | 702 | // Shortcut trivial case 703 | if x.IsUint64() { 704 | x0, y0 := x.Uint64(), y.Uint64() 705 | return z.SetUint64(x0 / y0), m.SetUint64(x0 % y0) 706 | } 707 | 708 | var quot, rem Int 709 | udivrem(quot[:], x[:], y, &rem) 710 | return z.Set("), m.Set(&rem) 711 | } 712 | 713 | // SMod interprets x and y as two's complement signed integers, 714 | // sets z to (sign x) * { abs(x) modulus abs(y) } 715 | // If y == 0, z is set to 0 (OBS: differs from the big.Int) 716 | func (z *Int) SMod(x, y *Int) *Int { 717 | yIsNeg := y.isNeg() 718 | xIsNeg := x.isNeg() 719 | 720 | // abs x 721 | if xIsNeg { 722 | x = new(Int).Neg(x) 723 | } 724 | // abs y 725 | if yIsNeg { 726 | y = new(Int).Neg(y) 727 | } 728 | z.Mod(x, y) 729 | if xIsNeg { 730 | z.Neg(z) 731 | } 732 | return z 733 | } 734 | 735 | // ISMod interprets z and x as two's complement signed integers, sets z to (sign z) * { abs(z) modulus abs(x) }, 736 | // modifying z in place, and returns z. Mathematically: z = (sign z) * (|z| % |x|). 737 | func (z *Int) ISMod(x *Int) *Int { 738 | return z.SMod(z, x) 739 | } 740 | 741 | // MulModWithReciprocal calculates the modulo-m multiplication of x and y 742 | // and returns z, using the reciprocal of m provided as the mu parameter. 743 | // Use uint256.Reciprocal to calculate mu from m. 744 | // If m == 0, z is set to 0 (OBS: differs from the big.Int) 745 | func (z *Int) MulModWithReciprocal(x, y, m *Int, mu *[5]uint64) *Int { 746 | if x.IsZero() || y.IsZero() || m.IsZero() { 747 | return z.Clear() 748 | } 749 | var p [8]uint64 750 | umul(x, y, &p) 751 | 752 | if m[3] != 0 { 753 | return z.reduce4(&p, m, mu) 754 | } 755 | 756 | var ( 757 | pl Int 758 | ph Int 759 | ) 760 | pl[0], pl[1], pl[2], pl[3] = p[0], p[1], p[2], p[3] 761 | ph[0], ph[1], ph[2], ph[3] = p[4], p[5], p[6], p[7] 762 | 763 | // If the multiplication is within 256 bits use Mod(). 764 | if ph.IsZero() { 765 | return z.Mod(&pl, m) 766 | } 767 | 768 | var quot [8]uint64 769 | var rem Int 770 | udivrem(quot[:], p[:], m, &rem) 771 | return z.Set(&rem) 772 | } 773 | 774 | // IMulModWithReciprocal calculates the modulo-m multiplication of z and x, 775 | // modifying z in place, and returns z, using the reciprocal of m provided as mu. 776 | // Mathematically: z = (z * x) % m. 777 | func (z *Int) IMulModWithReciprocal(x, m *Int, mu *[5]uint64) *Int { 778 | return z.MulModWithReciprocal(z, x, m, mu) 779 | } 780 | 781 | // MulMod calculates the modulo-m multiplication of x and y and 782 | // returns z. 783 | // If m == 0, z is set to 0 (OBS: differs from the big.Int) 784 | func (z *Int) MulMod(x, y, m *Int) *Int { 785 | if x.IsZero() || y.IsZero() || m.IsZero() { 786 | return z.Clear() 787 | } 788 | var p [8]uint64 789 | umul(x, y, &p) 790 | 791 | if m[3] != 0 { 792 | mu := Reciprocal(m) 793 | return z.reduce4(&p, m, &mu) 794 | } 795 | 796 | var ( 797 | pl Int 798 | ph Int 799 | ) 800 | pl[0], pl[1], pl[2], pl[3] = p[0], p[1], p[2], p[3] 801 | ph[0], ph[1], ph[2], ph[3] = p[4], p[5], p[6], p[7] 802 | 803 | // If the multiplication is within 256 bits use Mod(). 804 | if ph.IsZero() { 805 | return z.Mod(&pl, m) 806 | } 807 | 808 | var quot [8]uint64 809 | var rem Int 810 | udivrem(quot[:], p[:], m, &rem) 811 | return z.Set(&rem) 812 | } 813 | 814 | // IMulMod calculates the modulo-m multiplication of z and x, modifying z in place, 815 | // and returns z. Mathematically: z = (z * x) % m. 816 | func (z *Int) IMulMod(x, m *Int) *Int { 817 | return z.MulMod(z, x, m) 818 | } 819 | 820 | // MulDivOverflow calculates (x*y)/d with full precision, returns z and whether overflow occurred in multiply process (result does not fit to 256-bit). 821 | // computes 512-bit multiplication and 512 by 256 division. 822 | func (z *Int) MulDivOverflow(x, y, d *Int) (*Int, bool) { 823 | if x.IsZero() || y.IsZero() || d.IsZero() { 824 | return z.Clear(), false 825 | } 826 | var p [8]uint64 827 | umul(x, y, &p) 828 | 829 | var quot [8]uint64 830 | udivrem(quot[:], p[:], d, nil) 831 | 832 | z[0], z[1], z[2], z[3] = quot[0], quot[1], quot[2], quot[3] 833 | 834 | return z, (quot[4] | quot[5] | quot[6] | quot[7]) != 0 835 | } 836 | 837 | // MulDivOverflowRem calculates (x*y)/d with full precision, returns: 838 | // - `z`, 839 | // - sets `m` as `mulmod(x, y, d)` (modulo-d multiplication of x and y) 840 | // - and whether overflow occurred in multiply process (result does not fit to 256-bit). 841 | // computes 512-bit multiplication and 512 by 256 division. 842 | func (z *Int) MulDivOverflowRem(x, y, d, m *Int) (*Int, *Int, bool) { 843 | if x.IsZero() || y.IsZero() || d.IsZero() { 844 | m.Clear() 845 | return z.Clear(), m, false 846 | } 847 | var p [8]uint64 848 | umul(x, y, &p) 849 | 850 | var quot [8]uint64 851 | m.Clear() 852 | udivrem(quot[:], p[:], d, m) 853 | 854 | z[0], z[1], z[2], z[3] = quot[0], quot[1], quot[2], quot[3] 855 | 856 | return z, m, (quot[4] | quot[5] | quot[6] | quot[7]) != 0 857 | } 858 | 859 | // Abs interprets x as a two's complement signed number, 860 | // and sets z to the absolute value 861 | // 862 | // Abs(0) = 0 863 | // Abs(1) = 1 864 | // Abs(2**255) = -2**255 865 | // Abs(2**256-1) = -1 866 | func (z *Int) Abs(x *Int) *Int { 867 | if x[3] < 0x8000000000000000 { 868 | return z.Set(x) 869 | } 870 | return z.Sub(new(Int), x) 871 | } 872 | 873 | // Neg returns -x mod 2**256. 874 | func (z *Int) Neg(x *Int) *Int { 875 | return z.Sub(new(Int), x) 876 | } 877 | 878 | // SDiv interprets n and d as two's complement signed integers, 879 | // does a signed division on the two operands and sets z to the result. 880 | // If d == 0, z is set to 0 881 | func (z *Int) SDiv(n, d *Int) *Int { 882 | if n.IsZero() || d.IsZero() { 883 | return z.Clear() 884 | } 885 | if !n.isNeg() { 886 | if !d.isNeg() { 887 | // pos / pos 888 | z.Div(n, d) 889 | return z 890 | } else { 891 | // pos / neg 892 | z.Div(n, new(Int).Neg(d)) 893 | return z.Neg(z) 894 | } 895 | } 896 | 897 | if d.isNeg() { 898 | // neg / neg 899 | z.Div(new(Int).Neg(n), new(Int).Neg(d)) 900 | return z 901 | } 902 | // neg / pos 903 | z.Div(new(Int).Neg(n), d) 904 | return z.Neg(z) 905 | } 906 | 907 | // ISDiv interprets z and d as two's complement signed integers, performs signed division z by d, 908 | // modifying z in place, and returns z. Mathematically: z = z / d (signed). 909 | func (z *Int) ISDiv(d *Int) *Int { 910 | return z.SDiv(z, d) 911 | } 912 | 913 | // Sign returns: 914 | // 915 | // -1 if z < 0 916 | // 0 if z == 0 917 | // +1 if z > 0 918 | // 919 | // Where z is interpreted as a two's complement signed number 920 | func (z *Int) Sign() int { 921 | if z.IsZero() { 922 | return 0 923 | } 924 | if z[3] < 0x8000000000000000 { 925 | return 1 926 | } 927 | return -1 928 | } 929 | 930 | // isNeg returns true if z is negative when interpreted as a two's complement signed number 931 | func (z *Int) isNeg() bool { 932 | return z[3] >= 0x8000000000000000 933 | } 934 | 935 | // BitLen returns the number of bits required to represent z 936 | func (z *Int) BitLen() int { 937 | switch { 938 | case z[3] != 0: 939 | return 192 + bits.Len64(z[3]) 940 | case z[2] != 0: 941 | return 128 + bits.Len64(z[2]) 942 | case z[1] != 0: 943 | return 64 + bits.Len64(z[1]) 944 | default: 945 | return bits.Len64(z[0]) 946 | } 947 | } 948 | 949 | // ByteLen returns the number of bytes required to represent z 950 | func (z *Int) ByteLen() int { 951 | return (z.BitLen() + 7) / 8 952 | } 953 | 954 | func (z *Int) lsh64(x *Int) { 955 | z[3], z[2], z[1], z[0] = x[2], x[1], x[0], 0 956 | } 957 | 958 | func (z *Int) lsh128(x *Int) { 959 | z[3], z[2], z[1], z[0] = x[1], x[0], 0, 0 960 | } 961 | 962 | func (z *Int) lsh192(x *Int) { 963 | z[3], z[2], z[1], z[0] = x[0], 0, 0, 0 964 | } 965 | 966 | func (z *Int) rsh64(x *Int) { 967 | z[3], z[2], z[1], z[0] = 0, x[3], x[2], x[1] 968 | } 969 | 970 | func (z *Int) rsh128(x *Int) { 971 | z[3], z[2], z[1], z[0] = 0, 0, x[3], x[2] 972 | } 973 | 974 | func (z *Int) rsh192(x *Int) { 975 | z[3], z[2], z[1], z[0] = 0, 0, 0, x[3] 976 | } 977 | 978 | func (z *Int) srsh64(x *Int) { 979 | z[3], z[2], z[1], z[0] = math.MaxUint64, x[3], x[2], x[1] 980 | } 981 | 982 | func (z *Int) srsh128(x *Int) { 983 | z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, x[3], x[2] 984 | } 985 | 986 | func (z *Int) srsh192(x *Int) { 987 | z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, math.MaxUint64, x[3] 988 | } 989 | 990 | // Not sets z = ^x and returns z. 991 | func (z *Int) Not(x *Int) *Int { 992 | z[3], z[2], z[1], z[0] = ^x[3], ^x[2], ^x[1], ^x[0] 993 | return z 994 | } 995 | 996 | // Gt returns true if z > x 997 | func (z *Int) Gt(x *Int) bool { 998 | return x.Lt(z) 999 | } 1000 | 1001 | // Slt interprets z and x as signed integers, and returns 1002 | // true if z < x 1003 | func (z *Int) Slt(x *Int) bool { 1004 | signNotEq := (z[3] ^ x[3]) >= 0x8000000000000000 1005 | if signNotEq { 1006 | // One of them has the high bit set == is negative, 1007 | // so the biggest one (high bit set) is the smallest 1008 | return z[3] > x[3] 1009 | } 1010 | return z.Lt(x) 1011 | } 1012 | 1013 | // Sgt interprets z and x as signed integers, and returns 1014 | // true if z > x 1015 | func (z *Int) Sgt(x *Int) bool { 1016 | signNotEq := (z[3] ^ x[3]) >= 0x8000000000000000 1017 | if signNotEq { 1018 | // One of them has the high bit set == is negative, 1019 | // so the biggest one (high bit set) is the smallest 1020 | return z[3] < x[3] 1021 | } 1022 | return x.Lt(z) 1023 | } 1024 | 1025 | // Lt returns true if z < x 1026 | func (z *Int) Lt(x *Int) bool { 1027 | // z < x <=> z - x < 0 i.e. when subtraction overflows. 1028 | _, carry := bits.Sub64(z[0], x[0], 0) 1029 | _, carry = bits.Sub64(z[1], x[1], carry) 1030 | _, carry = bits.Sub64(z[2], x[2], carry) 1031 | _, carry = bits.Sub64(z[3], x[3], carry) 1032 | return carry != 0 1033 | } 1034 | 1035 | // SetUint64 sets z to the value x 1036 | func (z *Int) SetUint64(x uint64) *Int { 1037 | z[3], z[2], z[1], z[0] = 0, 0, 0, x 1038 | return z 1039 | } 1040 | 1041 | // Eq returns true if z == x 1042 | func (z *Int) Eq(x *Int) bool { 1043 | return ((z[0] ^ x[0]) | (z[1] ^ x[1]) | (z[2] ^ x[2]) | (z[3] ^ x[3])) == 0 1044 | } 1045 | 1046 | // Cmp compares z and x and returns: 1047 | // 1048 | // -1 if z < x 1049 | // 0 if z == x 1050 | // +1 if z > x 1051 | func (z *Int) Cmp(x *Int) (r int) { 1052 | // z < x <=> z - x < 0 i.e. when subtraction overflows. 1053 | d0, carry := bits.Sub64(z[0], x[0], 0) 1054 | d1, carry := bits.Sub64(z[1], x[1], carry) 1055 | d2, carry := bits.Sub64(z[2], x[2], carry) 1056 | d3, carry := bits.Sub64(z[3], x[3], carry) 1057 | if carry == 1 { 1058 | return -1 1059 | } 1060 | if d0|d1|d2|d3 == 0 { 1061 | return 0 1062 | } 1063 | return 1 1064 | } 1065 | 1066 | // CmpUint64 compares z and x and returns: 1067 | // 1068 | // -1 if z < x 1069 | // 0 if z == x 1070 | // +1 if z > x 1071 | func (z *Int) CmpUint64(x uint64) int { 1072 | if z[0] > x || (z[1]|z[2]|z[3]) != 0 { 1073 | return 1 1074 | } 1075 | if z[0] == x { 1076 | return 0 1077 | } 1078 | return -1 1079 | } 1080 | 1081 | // CmpBig compares z and x and returns: 1082 | // 1083 | // -1 if z < x 1084 | // 0 if z == x 1085 | // +1 if z > x 1086 | func (z *Int) CmpBig(x *big.Int) (r int) { 1087 | // If x is negative, it's surely smaller (z > x) 1088 | if x.Sign() == -1 { 1089 | return 1 1090 | } 1091 | y := new(Int) 1092 | if y.SetFromBig(x) { // overflow 1093 | // z < x 1094 | return -1 1095 | } 1096 | return z.Cmp(y) 1097 | } 1098 | 1099 | // LtUint64 returns true if z is smaller than n 1100 | func (z *Int) LtUint64(n uint64) bool { 1101 | return z[0] < n && (z[1]|z[2]|z[3]) == 0 1102 | } 1103 | 1104 | // GtUint64 returns true if z is larger than n 1105 | func (z *Int) GtUint64(n uint64) bool { 1106 | return z[0] > n || (z[1]|z[2]|z[3]) != 0 1107 | } 1108 | 1109 | // IsUint64 reports whether z can be represented as a uint64. 1110 | func (z *Int) IsUint64() bool { 1111 | return (z[1] | z[2] | z[3]) == 0 1112 | } 1113 | 1114 | // IsZero returns true if z == 0 1115 | func (z *Int) IsZero() bool { 1116 | return (z[0] | z[1] | z[2] | z[3]) == 0 1117 | } 1118 | 1119 | // Clear sets z to 0 1120 | func (z *Int) Clear() *Int { 1121 | z[3], z[2], z[1], z[0] = 0, 0, 0, 0 1122 | return z 1123 | } 1124 | 1125 | // SetAllOne sets all the bits of z to 1 1126 | func (z *Int) SetAllOne() *Int { 1127 | z[3], z[2], z[1], z[0] = math.MaxUint64, math.MaxUint64, math.MaxUint64, math.MaxUint64 1128 | return z 1129 | } 1130 | 1131 | // SetOne sets z to 1 1132 | func (z *Int) SetOne() *Int { 1133 | z[3], z[2], z[1], z[0] = 0, 0, 0, 1 1134 | return z 1135 | } 1136 | 1137 | // Lsh sets z = x << n and returns z. 1138 | func (z *Int) Lsh(x *Int, n uint) *Int { 1139 | switch { 1140 | case n == 0: 1141 | return z.Set(x) 1142 | case n >= 192: 1143 | z.lsh192(x) 1144 | n -= 192 1145 | z[3] <<= n 1146 | return z 1147 | case n >= 128: 1148 | z.lsh128(x) 1149 | n -= 128 1150 | z[3] = (z[3] << n) | (z[2] >> (64 - n)) 1151 | z[2] <<= n 1152 | return z 1153 | case n >= 64: 1154 | z.lsh64(x) 1155 | n -= 64 1156 | z[3] = (z[3] << n) | (z[2] >> (64 - n)) 1157 | z[2] = (z[2] << n) | (z[1] >> (64 - n)) 1158 | z[1] <<= n 1159 | return z 1160 | default: 1161 | z.Set(x) 1162 | z[3] = (z[3] << n) | (z[2] >> (64 - n)) 1163 | z[2] = (z[2] << n) | (z[1] >> (64 - n)) 1164 | z[1] = (z[1] << n) | (z[0] >> (64 - n)) 1165 | z[0] <<= n 1166 | return z 1167 | } 1168 | } 1169 | 1170 | // ILsh shifts z left by n bits, modifying z in place, and returns z. Mathematically: z = z << n. 1171 | func (z *Int) ILsh(n uint) *Int { 1172 | return z.Lsh(z, n) 1173 | } 1174 | 1175 | // Rsh sets z = x >> n and returns z. 1176 | func (z *Int) Rsh(x *Int, n uint) *Int { 1177 | switch { 1178 | case n == 0: 1179 | return z.Set(x) 1180 | case n >= 192: 1181 | z.rsh192(x) 1182 | n -= 192 1183 | z[0] >>= n 1184 | return z 1185 | case n >= 128: 1186 | z.rsh128(x) 1187 | n -= 128 1188 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1189 | z[1] >>= n 1190 | return z 1191 | case n >= 64: 1192 | z.rsh64(x) 1193 | n -= 64 1194 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1195 | z[1] = (z[1] >> n) | (z[2] << (64 - n)) 1196 | z[2] >>= n 1197 | return z 1198 | default: 1199 | z.Set(x) 1200 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1201 | z[1] = (z[1] >> n) | (z[2] << (64 - n)) 1202 | z[2] = (z[2] >> n) | (z[3] << (64 - n)) 1203 | z[3] >>= n 1204 | return z 1205 | } 1206 | } 1207 | 1208 | // IRsh shifts z right by n bits, modifying z in place, and returns z. 1209 | // Mathematically: z = z >> n. 1210 | func (z *Int) IRsh(n uint) *Int { 1211 | return z.Rsh(z, n) 1212 | } 1213 | 1214 | // SRsh (Signed/Arithmetic right shift) 1215 | // considers z to be a signed integer, during right-shift 1216 | // and sets z = x >> n and returns z. 1217 | func (z *Int) SRsh(x *Int, n uint) *Int { 1218 | // If the MSB is 0, SRsh is same as Rsh. 1219 | if !x.isNeg() { 1220 | return z.Rsh(x, n) 1221 | } 1222 | var a uint64 = math.MaxUint64 << (64 - n%64) 1223 | 1224 | switch { 1225 | case n == 0: 1226 | return z.Set(x) 1227 | case n >= 256: 1228 | return z.SetAllOne() 1229 | case n >= 192: 1230 | z.srsh192(x) 1231 | n -= 192 1232 | z[0] = (z[0] >> n) | a 1233 | return z 1234 | case n >= 128: 1235 | z.srsh128(x) 1236 | n -= 128 1237 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1238 | z[1] = (z[1] >> n) | a 1239 | return z 1240 | case n >= 64: 1241 | z.srsh64(x) 1242 | n -= 64 1243 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1244 | z[1] = (z[1] >> n) | (z[2] << (64 - n)) 1245 | z[2] = (z[2] >> n) | a 1246 | return z 1247 | default: 1248 | z.Set(x) 1249 | z[0] = (z[0] >> n) | (z[1] << (64 - n)) 1250 | z[1] = (z[1] >> n) | (z[2] << (64 - n)) 1251 | z[2] = (z[2] >> n) | (z[3] << (64 - n)) 1252 | z[3] = (z[3] >> n) | a 1253 | return z 1254 | } 1255 | } 1256 | 1257 | // ISRsh performs a signed right shift on z by n bits, modifying z in place, and returns z. 1258 | // Mathematically: z = z >> n (where z is treated as a signed integer). 1259 | func (z *Int) ISRsh(n uint) *Int { 1260 | return z.SRsh(z, n) 1261 | } 1262 | 1263 | // Set sets z to x and returns z. 1264 | func (z *Int) Set(x *Int) *Int { 1265 | z[0], z[1], z[2], z[3] = x[0], x[1], x[2], x[3] 1266 | return z 1267 | } 1268 | 1269 | // Or sets z = x | y and returns z. 1270 | func (z *Int) Or(x, y *Int) *Int { 1271 | z[0] = x[0] | y[0] 1272 | z[1] = x[1] | y[1] 1273 | z[2] = x[2] | y[2] 1274 | z[3] = x[3] | y[3] 1275 | return z 1276 | } 1277 | 1278 | // And sets z = x & y and returns z. 1279 | func (z *Int) And(x, y *Int) *Int { 1280 | z[0] = x[0] & y[0] 1281 | z[1] = x[1] & y[1] 1282 | z[2] = x[2] & y[2] 1283 | z[3] = x[3] & y[3] 1284 | return z 1285 | } 1286 | 1287 | // Xor sets z = x ^ y and returns z. 1288 | func (z *Int) Xor(x, y *Int) *Int { 1289 | z[0] = x[0] ^ y[0] 1290 | z[1] = x[1] ^ y[1] 1291 | z[2] = x[2] ^ y[2] 1292 | z[3] = x[3] ^ y[3] 1293 | return z 1294 | } 1295 | 1296 | // Byte sets z to the value of the byte at position n, 1297 | // with z considered as a big-endian 32-byte integer. 1298 | // if n >= 32, z is set to 0 1299 | // Example: z=5, n=31 => 5 1300 | func (z *Int) Byte(n *Int) *Int { 1301 | index, overflow := n.Uint64WithOverflow() 1302 | if overflow || index >= 32 { 1303 | return z.Clear() 1304 | } 1305 | // in z, z[0] is the least significant 1306 | number := z[4-1-index/8] 1307 | offset := (index & 0x7) << 3 // 8 * (index % 8) 1308 | z[0] = (number >> (56 - offset)) & 0xff 1309 | z[3], z[2], z[1] = 0, 0, 0 1310 | return z 1311 | } 1312 | 1313 | // Exp sets z = base**exponent mod 2**256, and returns z. 1314 | func (z *Int) Exp(base, exponent *Int) *Int { 1315 | var ( 1316 | res = Int{1, 0, 0, 0} 1317 | multiplier = *base 1318 | expBitLen = exponent.BitLen() 1319 | curBit = 0 1320 | word = exponent[0] 1321 | even = base[0]&1 == 0 1322 | ) 1323 | if even && expBitLen > 8 { 1324 | return z.Clear() 1325 | } 1326 | 1327 | for ; curBit < expBitLen && curBit < 64; curBit++ { 1328 | if word&1 == 1 { 1329 | res.Mul(&res, &multiplier) 1330 | } 1331 | multiplier.squared() 1332 | word >>= 1 1333 | } 1334 | if even { // If the base was even, we are finished now 1335 | return z.Set(&res) 1336 | } 1337 | 1338 | word = exponent[1] 1339 | for ; curBit < expBitLen && curBit < 128; curBit++ { 1340 | if word&1 == 1 { 1341 | res.Mul(&res, &multiplier) 1342 | } 1343 | multiplier.squared() 1344 | word >>= 1 1345 | } 1346 | 1347 | word = exponent[2] 1348 | for ; curBit < expBitLen && curBit < 192; curBit++ { 1349 | if word&1 == 1 { 1350 | res.Mul(&res, &multiplier) 1351 | } 1352 | multiplier.squared() 1353 | word >>= 1 1354 | } 1355 | 1356 | word = exponent[3] 1357 | for ; curBit < expBitLen && curBit < 256; curBit++ { 1358 | if word&1 == 1 { 1359 | res.Mul(&res, &multiplier) 1360 | } 1361 | multiplier.squared() 1362 | word >>= 1 1363 | } 1364 | return z.Set(&res) 1365 | } 1366 | 1367 | // IExp sets z = z**exponent mod 2**256, and returns z. 1368 | func (z *Int) IExp(exponent *Int) *Int { 1369 | return z.Exp(z, exponent) 1370 | } 1371 | 1372 | // ExtendSign extends length of two’s complement signed integer, 1373 | // sets z to 1374 | // - x if byteNum > 30 1375 | // - x interpreted as a signed number with sign-bit at (byteNum*8+7), extended to the full 256 bits 1376 | // 1377 | // and returns z. 1378 | func (z *Int) ExtendSign(x, byteNum *Int) *Int { 1379 | // This implementation is based on evmone. See https://github.com/ethereum/evmone/pull/390 1380 | if byteNum.GtUint64(30) { 1381 | return z.Set(x) 1382 | } 1383 | 1384 | e := byteNum.Uint64() 1385 | z.Set(x) 1386 | signWordIndex := e >> 3 // Index of the word with the sign bit. 1387 | signByteIndex := e & 7 // Index of the sign byte in the sign word. 1388 | signWord := z[signWordIndex] 1389 | signByteOffset := signByteIndex << 3 1390 | signByte := signWord >> signByteOffset // Move sign byte to position 0. 1391 | 1392 | // Sign-extend the "sign" byte and move it to the right position. Value bits are zeros. 1393 | sextByte := uint64(int64(int8(signByte))) 1394 | sext := sextByte << signByteOffset 1395 | signMask := uint64(math.MaxUint64 << signByteOffset) 1396 | value := signWord & ^signMask // Reset extended bytes. 1397 | 1398 | z[signWordIndex] = sext | value // Combine the result word. 1399 | 1400 | // Produce bits (all zeros or ones) for extended words. This is done by SAR of 1401 | // the sign-extended byte. Shift by any value 7-63 would work. 1402 | signEx := uint64(int64(sextByte) >> 8) 1403 | 1404 | switch signWordIndex { 1405 | case 2: 1406 | z[3] = signEx 1407 | return z 1408 | case 1: 1409 | z[3], z[2] = signEx, signEx 1410 | return z 1411 | case 0: 1412 | z[3], z[2], z[1] = signEx, signEx, signEx 1413 | return z 1414 | default: 1415 | return z 1416 | } 1417 | } 1418 | 1419 | // Sqrt sets z to ⌊√x⌋, the largest integer such that z² ≤ x, and returns z. 1420 | func (z *Int) Sqrt(x *Int) *Int { 1421 | // This implementation of Sqrt is based on big.Int (see math/big/nat.go). 1422 | if x.IsUint64() { 1423 | var ( 1424 | x0 uint64 = x.Uint64() 1425 | z1 uint64 = 1 << ((bits.Len64(x0) + 1) / 2) 1426 | z2 uint64 1427 | ) 1428 | if x0 < 2 { 1429 | return z.SetUint64(x0) 1430 | } 1431 | for { 1432 | z2 = (z1 + x0/z1) >> 1 1433 | if z2 >= z1 { 1434 | return z.SetUint64(z1) 1435 | } 1436 | z1 = z2 1437 | } 1438 | } 1439 | 1440 | z1 := NewInt(1) 1441 | z2 := NewInt(0) 1442 | 1443 | // Start with value known to be too large and repeat "z = ⌊(z + ⌊x/z⌋)/2⌋" until it stops getting smaller. 1444 | z1.Lsh(z1, uint(x.BitLen()+1)/2) // must be ≥ √x 1445 | 1446 | // We can do the first division outside the loop 1447 | z2.Rsh(x, uint(x.BitLen()+1)/2) // The first div is equal to a right shift 1448 | 1449 | for { 1450 | z2.Add(z2, z1) 1451 | 1452 | // z2 = z2.Rsh(z2, 1) -- the code below does a 1-bit rsh faster 1453 | z2[0] = (z2[0] >> 1) | z2[1]<<63 1454 | z2[1] = (z2[1] >> 1) | z2[2]<<63 1455 | z2[2] = (z2[2] >> 1) | z2[3]<<63 1456 | z2[3] >>= 1 1457 | 1458 | if !z2.Lt(z1) { 1459 | return z.Set(z1) 1460 | } 1461 | z1.Set(z2) 1462 | 1463 | // Next iteration of the loop 1464 | // z2.Div(x, z1) -- x > MaxUint64, x > z1 > 0 1465 | z2.Clear() 1466 | udivrem(z2[:], x[:], z1, nil) 1467 | } 1468 | } 1469 | 1470 | // ISqrt sets z to ⌊√z⌋, the largest integer such that z² ≤ original z, modifying z in place, and returns z. 1471 | // Mathematically: z = ⌊√z⌋. 1472 | func (z *Int) ISqrt() *Int { 1473 | return z.Sqrt(z) 1474 | } 1475 | 1476 | var ( 1477 | // pows64 contains 10^0 ... 10^19 1478 | pows64 = [20]uint64{ 1479 | 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1480 | } 1481 | // pows contain 10 ** 20 ... 10 ** 80 1482 | pows = [60]Int{ 1483 | {7766279631452241920, 5, 0, 0}, {3875820019684212736, 54, 0, 0}, {1864712049423024128, 542, 0, 0}, {200376420520689664, 5421, 0, 0}, {2003764205206896640, 54210, 0, 0}, {1590897978359414784, 542101, 0, 0}, {15908979783594147840, 5421010, 0, 0}, {11515845246265065472, 54210108, 0, 0}, {4477988020393345024, 542101086, 0, 0}, {7886392056514347008, 5421010862, 0, 0}, {5076944270305263616, 54210108624, 0, 0}, {13875954555633532928, 542101086242, 0, 0}, {9632337040368467968, 5421010862427, 0, 0}, 1484 | {4089650035136921600, 54210108624275, 0, 0}, {4003012203950112768, 542101086242752, 0, 0}, {3136633892082024448, 5421010862427522, 0, 0}, {12919594847110692864, 54210108624275221, 0, 0}, {68739955140067328, 542101086242752217, 0, 0}, {687399551400673280, 5421010862427522170, 0, 0}, {6873995514006732800, 17316620476856118468, 2, 0}, {13399722918938673152, 7145508105175220139, 29, 0}, {4870020673419870208, 16114848830623546549, 293, 0}, {11806718586779598848, 13574535716559052564, 2938, 0}, 1485 | {7386721425538678784, 6618148649623664334, 29387, 0}, {80237960548581376, 10841254275107988496, 293873, 0}, {802379605485813760, 16178822382532126880, 2938735, 0}, {8023796054858137600, 14214271235644855872, 29387358, 0}, {6450984253743169536, 13015503840481697412, 293873587, 0}, {9169610316303040512, 1027829888850112811, 2938735877, 0}, {17909126868192198656, 10278298888501128114, 29387358770, 0}, {13070572018536022016, 10549268516463523069, 293873587705, 0}, {1578511669393358848, 13258964796087472617, 2938735877055, 0}, {15785116693933588480, 3462439444907864858, 29387358770557, 0}, 1486 | {10277214349659471872, 16177650375369096972, 293873587705571, 0}, {10538423128046960640, 14202551164014556797, 2938735877055718, 0}, {13150510911921848320, 12898303124178706663, 29387358770557187, 0}, {2377900603251621888, 18302566799529756941, 293873587705571876, 0}, {5332261958806667264, 17004971331911604867, 2938735877055718769, 0}, {16429131440647569408, 4029016655730084128, 10940614696847636083, 1}, {16717361816799281152, 3396678409881738056, 17172426599928602752, 15}, {1152921504606846976, 15520040025107828953, 5703569335900062977, 159}, {11529215046068469760, 7626447661401876602, 1695461137871974930, 1593}, {4611686018427387904, 2477500319180559562, 16954611378719749304, 15930}, {9223372036854775808, 6328259118096044006, 3525417123811528497, 159309}, 1487 | {0, 7942358959831785217, 16807427164405733357, 1593091}, {0, 5636613303479645706, 2053574980671369030, 15930919}, {0, 1025900813667802212, 2089005733004138687, 159309191}, {0, 10259008136678022120, 2443313256331835254, 1593091911}, {0, 10356360998232463120, 5986388489608800929, 15930919111}, {0, 11329889613776873120, 4523652674959354447, 159309191113}, {0, 2618431695511421504, 8343038602174441244, 1593091911132}, {0, 7737572881404663424, 9643409726906205977, 15930919111324}, {0, 3588752519208427776, 4200376900514301694, 159309191113245}, {0, 17440781118374726144, 5110280857723913709, 1593091911132452}, {0, 8387114520361296896, 14209320429820033867, 15930919111324522}, {0, 10084168908774762496, 12965995782233477362, 159309191113245227}, {0, 8607968719199866880, 532749306367912313, 1593091911132452277}, {0, 12292710897160462336, 5327493063679123134, 15930919111324522770}, {0, 12246644529347313664, 16381442489372128114, 11735238523568814774}, {0, 11785980851215826944, 16240472304044868218, 6671920793430838052}, 1488 | } 1489 | ) 1490 | 1491 | // Log10 returns the log in base 10, floored to nearest integer. 1492 | // **OBS** This method returns '0' for '0', not `-Inf`. 1493 | func (z *Int) Log10() uint { 1494 | // The following algorithm is taken from "Bit twiddling hacks" 1495 | // https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 1496 | // 1497 | // The idea is that log10(z) = log2(z) / log2(10) 1498 | // log2(z) trivially is z.Bitlen() 1499 | // 1/log2(10) is a constant ~ 1233 / 4096. The approximation is correct up to 5 digit after 1500 | // the decimal point and it seems no further refinement is needed. 1501 | // Our tests check all boundary cases anyway. 1502 | 1503 | bitlen := z.BitLen() 1504 | if bitlen == 0 { 1505 | return 0 1506 | } 1507 | 1508 | t := (bitlen + 1) * 1233 >> 12 1509 | if bitlen <= 64 && z[0] < pows64[t] || t >= 20 && z.Lt(&pows[t-20]) { 1510 | return uint(t - 1) 1511 | } 1512 | return uint(t) 1513 | } 1514 | --------------------------------------------------------------------------------